| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package org.netbeans.modules.selenium2.webclient.mocha; |
| |
| import java.awt.EventQueue; |
| import java.awt.event.ActionEvent; |
| import java.awt.event.ActionListener; |
| import java.io.File; |
| import javax.swing.GroupLayout; |
| import javax.swing.JButton; |
| import javax.swing.JCheckBox; |
| import javax.swing.JLabel; |
| import javax.swing.JSpinner; |
| import javax.swing.JTextField; |
| import javax.swing.LayoutStyle; |
| import javax.swing.SpinnerNumberModel; |
| import javax.swing.event.ChangeEvent; |
| import javax.swing.event.ChangeListener; |
| import javax.swing.event.DocumentEvent; |
| import javax.swing.event.DocumentListener; |
| import org.netbeans.api.project.Project; |
| import org.netbeans.modules.selenium2.webclient.mocha.preferences.MochaJSPreferences; |
| import org.netbeans.modules.selenium2.webclient.mocha.preferences.MochaSeleniumPreferences; |
| import org.netbeans.modules.selenium2.webclient.mocha.preferences.MochaPreferencesValidator; |
| import org.netbeans.modules.web.common.api.ValidationResult; |
| import org.openide.awt.Mnemonics; |
| import org.openide.filesystems.FileChooserBuilder; |
| import org.openide.filesystems.FileUtil; |
| import org.openide.util.ChangeSupport; |
| import org.openide.util.NbBundle; |
| |
| public final class CustomizerMocha extends javax.swing.JPanel { |
| |
| private final Project project; |
| private final boolean isSelenium; |
| private final ChangeSupport changeSupport = new ChangeSupport(this); |
| private final SpinnerNumberModel timeoutModel; |
| private boolean autoDiscovered = false; |
| |
| private volatile String mochaInstallFolder; |
| private volatile int timeout; |
| |
| // @GuardedBy("EDT") |
| private ValidationResult validationResult; |
| |
| |
| public CustomizerMocha(Project project, boolean isSelenium) { |
| assert EventQueue.isDispatchThread(); |
| assert project != null; |
| |
| this.project = project; |
| this.isSelenium = isSelenium; |
| timeoutModel = new SpinnerNumberModel(65534, 1, 65534, 1); |
| |
| initComponents(); |
| init(); |
| } |
| |
| public void addChangeListener(ChangeListener listener) { |
| changeSupport.addChangeListener(listener); |
| } |
| |
| public void removeChangeListener(ChangeListener listener) { |
| changeSupport.removeChangeListener(listener); |
| } |
| |
| public String getMochaInstallFolder() { |
| return mochaInstallFolder; |
| } |
| |
| public int getTimeout() { |
| return timeout; |
| } |
| |
| public boolean getAutoWatch() { |
| return autowatchCheckBox.isSelected(); |
| } |
| |
| public String getWarningMessage() { |
| assert EventQueue.isDispatchThread(); |
| for (ValidationResult.Message message : validationResult.getWarnings()) { |
| return message.getMessage(); |
| } |
| return null; |
| } |
| |
| public String getErrorMessage() { |
| assert EventQueue.isDispatchThread(); |
| for (ValidationResult.Message message : validationResult.getErrors()) { |
| return message.getMessage(); |
| } |
| return null; |
| } |
| |
| @NbBundle.Messages({"CustomizerMocha.mocha.dir.info=Full path of mocha installation dir (typically node_modules/mocha).", |
| "CustomizerMocha.timeout.info=Test-case timeout in milliseconds."}) |
| private void init() { |
| assert EventQueue.isDispatchThread(); |
| String mochaDir; |
| // get saved mocha install dir if previously set from selenium/unit mocha preferences |
| mochaDir = isSelenium ? MochaSeleniumPreferences.getMochaDir(project) : MochaJSPreferences.getMochaDir(project); |
| if(mochaDir == null) { |
| // that did not work so try to get saved mocha install dir from unit/selenium mocha preferences |
| mochaDir = isSelenium ? MochaJSPreferences.getMochaDir(project) : MochaSeleniumPreferences.getMochaDir(project); |
| } |
| if(mochaDir == null) { // mocha dir not set yet, try searching for it in project's local node_modules dir |
| String dir = new File(FileUtil.toFile(project.getProjectDirectory()), "node_modules/mocha").getAbsolutePath(); |
| ValidationResult result = new MochaPreferencesValidator() |
| .validateMochaInstallFolder(dir) |
| .getResult(); |
| if(result.isFaultless()) { // mocha is installed in project's local node_modules dir |
| mochaDir = dir; |
| autoDiscovered = true; |
| } |
| } |
| mochaDirTextField.setText(mochaDir); |
| mochaDirInfoLabel.setText(Bundle.CustomizerMocha_mocha_dir_info()); |
| timeoutSpinner.setModel(timeoutModel); |
| timeout = isSelenium ? MochaSeleniumPreferences.getTimeout(project) : MochaJSPreferences.getTimeout(project); |
| timeoutModel.setValue(timeout); |
| timeoutInfoLabel.setText(Bundle.CustomizerMocha_timeout_info()); |
| if(isSelenium) { |
| autowatchCheckBox.setVisible(false); |
| } else { |
| autowatchCheckBox.setSelected(MochaJSPreferences.isAutoWatch(project)); |
| } |
| // listeners |
| addListeners(); |
| // initial validation |
| validateData(); |
| } |
| |
| private void addListeners() { |
| DocumentListener defaultDocumentListener = new DefaultDocumentListener(); |
| mochaDirTextField.getDocument().addDocumentListener(defaultDocumentListener); |
| timeoutModel.addChangeListener(new DefaultChangeListener()); |
| } |
| |
| @NbBundle.Messages({"CustomizerMocha.confirm.autodiscovered.info=Mocha installation dir was auto-discovered. Please confirm by clicking OK."}) |
| void validateData() { |
| assert EventQueue.isDispatchThread(); |
| mochaInstallFolder = mochaDirTextField.getText(); |
| validationResult = new MochaPreferencesValidator() |
| .validateMochaInstallFolder(mochaInstallFolder) |
| .getResult(); |
| if (autoDiscovered) { // auto-discovered, show confirmation message to the user |
| validationResult.addWarning(new ValidationResult.Message("path", Bundle.CustomizerMocha_confirm_autodiscovered_info())); // NOI18N |
| } |
| changeSupport.fireChange(); |
| } |
| |
| |
| /** |
| * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of this method is always regenerated by the Form |
| * Editor. |
| */ |
| @SuppressWarnings("unchecked") |
| // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents |
| private void initComponents() { |
| |
| mochaDirLabel = new JLabel(); |
| mochaDirTextField = new JTextField(); |
| mochaDirBrowseButton = new JButton(); |
| mochaDirInfoLabel = new JLabel(); |
| timeoutLabel = new JLabel(); |
| timeoutInfoLabel = new JLabel(); |
| timeoutSpinner = new JSpinner(); |
| autowatchCheckBox = new JCheckBox(); |
| |
| Mnemonics.setLocalizedText(mochaDirLabel, NbBundle.getMessage(CustomizerMocha.class, "CustomizerMocha.mochaDirLabel.text")); // NOI18N |
| |
| Mnemonics.setLocalizedText(mochaDirBrowseButton, NbBundle.getMessage(CustomizerMocha.class, "CustomizerMocha.mochaDirBrowseButton.text")); // NOI18N |
| mochaDirBrowseButton.addActionListener(new ActionListener() { |
| public void actionPerformed(ActionEvent evt) { |
| mochaDirBrowseButtonActionPerformed(evt); |
| } |
| }); |
| |
| Mnemonics.setLocalizedText(mochaDirInfoLabel, NbBundle.getMessage(CustomizerMocha.class, "CustomizerMocha.mochaDirInfoLabel.text")); // NOI18N |
| |
| timeoutLabel.setLabelFor(timeoutSpinner); |
| Mnemonics.setLocalizedText(timeoutLabel, NbBundle.getMessage(CustomizerMocha.class, "CustomizerMocha.timeoutLabel.text")); // NOI18N |
| |
| Mnemonics.setLocalizedText(timeoutInfoLabel, NbBundle.getMessage(CustomizerMocha.class, "CustomizerMocha.timeoutInfoLabel.text")); // NOI18N |
| |
| timeoutSpinner.setEditor(new JSpinner.NumberEditor(timeoutSpinner, "#")); |
| |
| Mnemonics.setLocalizedText(autowatchCheckBox, NbBundle.getMessage(CustomizerMocha.class, "CustomizerMocha.autowatchCheckBox.text")); // NOI18N |
| |
| GroupLayout layout = new GroupLayout(this); |
| this.setLayout(layout); |
| layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) |
| .addGroup(layout.createSequentialGroup() |
| .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) |
| .addComponent(mochaDirLabel) |
| .addComponent(timeoutLabel)) |
| .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) |
| .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) |
| .addGroup(layout.createSequentialGroup() |
| .addComponent(mochaDirTextField, GroupLayout.DEFAULT_SIZE, 237, Short.MAX_VALUE) |
| .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) |
| .addComponent(mochaDirBrowseButton) |
| .addContainerGap()) |
| .addGroup(layout.createSequentialGroup() |
| .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) |
| .addComponent(mochaDirInfoLabel) |
| .addComponent(timeoutInfoLabel) |
| .addComponent(timeoutSpinner, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) |
| .addGap(0, 0, Short.MAX_VALUE)))) |
| .addGroup(layout.createSequentialGroup() |
| .addContainerGap() |
| .addComponent(autowatchCheckBox) |
| .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) |
| ); |
| layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) |
| .addGroup(layout.createSequentialGroup() |
| .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) |
| .addComponent(mochaDirLabel) |
| .addComponent(mochaDirTextField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) |
| .addComponent(mochaDirBrowseButton)) |
| .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) |
| .addComponent(mochaDirInfoLabel) |
| .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) |
| .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) |
| .addComponent(timeoutLabel) |
| .addComponent(timeoutSpinner, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) |
| .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) |
| .addComponent(timeoutInfoLabel) |
| .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) |
| .addComponent(autowatchCheckBox) |
| .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) |
| ); |
| }// </editor-fold>//GEN-END:initComponents |
| |
| @NbBundle.Messages("CustomizerMocha.chooser.config=Select mocha install location") |
| private void mochaDirBrowseButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_mochaDirBrowseButtonActionPerformed |
| assert EventQueue.isDispatchThread(); |
| File file = new FileChooserBuilder(CustomizerMocha.class) |
| .setTitle(Bundle.CustomizerMocha_chooser_config()) |
| // .setFilesOnly(true) |
| .setDirectoriesOnly(true) |
| .setDefaultWorkingDirectory(FileUtil.toFile(project.getProjectDirectory())) |
| .forceUseOfDefaultWorkingDirectory(true) |
| .showOpenDialog(); |
| if (file != null) { |
| mochaDirTextField.setText(file.getAbsolutePath()); |
| } |
| }//GEN-LAST:event_mochaDirBrowseButtonActionPerformed |
| |
| // Variables declaration - do not modify//GEN-BEGIN:variables |
| private JCheckBox autowatchCheckBox; |
| private JButton mochaDirBrowseButton; |
| private JLabel mochaDirInfoLabel; |
| private JLabel mochaDirLabel; |
| private JTextField mochaDirTextField; |
| private JLabel timeoutInfoLabel; |
| private JLabel timeoutLabel; |
| private JSpinner timeoutSpinner; |
| // End of variables declaration//GEN-END:variables |
| |
| //~ Inner classes |
| |
| private final class DefaultDocumentListener implements DocumentListener { |
| |
| @Override |
| public void insertUpdate(DocumentEvent e) { |
| processChange(); |
| } |
| |
| @Override |
| public void removeUpdate(DocumentEvent e) { |
| processChange(); |
| } |
| |
| @Override |
| public void changedUpdate(DocumentEvent e) { |
| processChange(); |
| } |
| |
| private void processChange() { |
| validateData(); |
| } |
| |
| } |
| |
| private final class DefaultChangeListener implements ChangeListener { |
| |
| @Override |
| public void stateChanged(ChangeEvent e) { |
| timeout = timeoutModel.getNumber().intValue(); |
| validateData(); |
| } |
| |
| } |
| |
| } |