/* * SoapUI, Copyright (C) 2004-2016 SmartBear Software * * Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent * versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * * http://ec.europa.eu/idabc/eupl * * Unless required by applicable law or agreed to in writing, software distributed under the Licence is * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the Licence for the specific language governing permissions and limitations * under the Licence. */ package com.eviware.soapui.impl.wsdl.panels.teststeps; import com.eviware.soapui.SoapUI; import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction; import com.eviware.soapui.impl.wsdl.panels.support.TestRunComponentEnabler; import com.eviware.soapui.impl.wsdl.panels.teststeps.support.GotoTestStepsComboBoxModel; import com.eviware.soapui.impl.wsdl.support.HelpUrls; import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext; import com.eviware.soapui.impl.wsdl.teststeps.WsdlGotoTestStep; import com.eviware.soapui.impl.wsdl.teststeps.WsdlGotoTestStep.GotoCondition; import com.eviware.soapui.model.ModelItem; import com.eviware.soapui.model.iface.Response; import com.eviware.soapui.model.support.TestRunListenerAdapter; import com.eviware.soapui.model.testsuite.SamplerTestStep; import com.eviware.soapui.model.testsuite.TestCaseRunContext; import com.eviware.soapui.model.testsuite.TestCaseRunner; import com.eviware.soapui.model.testsuite.TestStepResult; import com.eviware.soapui.support.DocumentListenerAdapter; import com.eviware.soapui.support.UISupport; import com.eviware.soapui.support.components.JComponentInspector; import com.eviware.soapui.support.components.JInspectorPanel; import com.eviware.soapui.support.components.JInspectorPanelFactory; import com.eviware.soapui.support.components.JUndoableTextArea; import com.eviware.soapui.support.components.JXToolBar; import com.eviware.soapui.support.log.JLogList; import com.eviware.soapui.support.xml.XmlUtils; import com.eviware.soapui.ui.support.ModelItemDesktopPanel; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.DefaultListModel; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTextArea; import javax.swing.ListSelectionModel; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.text.Document; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.util.Date; /** * DesktopPanel for WsdlGotoTestSteps * * @author Ole.Matzura */ public class GotoStepDesktopPanel extends ModelItemDesktopPanel<WsdlGotoTestStep> { private final WsdlGotoTestStep gotoStep; private DefaultListModel listModel; private JList conditionList; private JTextArea expressionArea; private JButton copyButton; private JButton deleteButton; private JButton declareButton; private GotoTestStepsComboBoxModel testStepsModel; private JComboBox testStepsCombo; private JButton testConditionButton; private TestRunComponentEnabler componentEnabler; private GotoCondition currentCondition; private JButton renameButton; private JButton runButton; private JButton addButton; private JLogList logList; private InternalTestRunListener testRunListener = new InternalTestRunListener(); private JInspectorPanel inspectorPanel; public GotoStepDesktopPanel(WsdlGotoTestStep testStep) { super(testStep); this.gotoStep = testStep; componentEnabler = new TestRunComponentEnabler(testStep.getTestCase()); gotoStep.getTestCase().addTestRunListener(testRunListener); buildUI(); } public TestRunComponentEnabler getComponentEnabler() { return componentEnabler; } public JList getConditionList() { return conditionList; } public JButton getCopyButton() { return copyButton; } public JButton getDeclareButton() { return declareButton; } public JButton getDeleteButton() { return deleteButton; } public JTextArea getExpressionArea() { return expressionArea; } public WsdlGotoTestStep getGotoStep() { return gotoStep; } public DefaultListModel getListModel() { return listModel; } public JButton getTestConditionButton() { return testConditionButton; } public JComboBox getTestStepsCombo() { return testStepsCombo; } public GotoTestStepsComboBoxModel getTestStepsModel() { return testStepsModel; } private void buildUI() { JSplitPane splitPane = UISupport.createHorizontalSplit(); splitPane.setLeftComponent(buildConditionList()); splitPane.setRightComponent(buildExpressionArea()); splitPane.setResizeWeight(0.1); splitPane.setDividerLocation(120); inspectorPanel = JInspectorPanelFactory.build(splitPane); inspectorPanel.addInspector(new JComponentInspector<JComponent>(buildLog(), "Log", "A log of evaluated conditions", true)); add(inspectorPanel.getComponent(), BorderLayout.CENTER); setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3)); setPreferredSize(new Dimension(550, 300)); if (listModel.getSize() > 0) { conditionList.setSelectedIndex(0); } componentEnabler.add(conditionList); componentEnabler.add(expressionArea); componentEnabler.add(testStepsCombo); componentEnabler.add(testConditionButton); componentEnabler.add(copyButton); componentEnabler.add(declareButton); componentEnabler.add(deleteButton); componentEnabler.add(addButton); componentEnabler.add(runButton); componentEnabler.add(renameButton); } private JComponent buildLog() { logList = new JLogList("Condition Log for [" + getModelItem().getName() + "]"); return logList; } private JPanel buildExpressionArea() { expressionArea = new JUndoableTextArea(); expressionArea.setEnabled(false); expressionArea.getDocument().addDocumentListener(new SourceAreaDocumentListener()); JPanel expressionPanel = new JPanel(new BorderLayout()); JScrollPane scrollPane = new JScrollPane(expressionArea); UISupport.addTitledBorder(scrollPane, "Condition XPath Expression"); expressionPanel.add(scrollPane, BorderLayout.CENTER); expressionPanel.add(buildConditionToolbar(), BorderLayout.NORTH); expressionPanel.add(buildTargetToolbar(), BorderLayout.SOUTH); return expressionPanel; } private JPanel buildConditionList() { listModel = new DefaultListModel(); for (int c = 0; c < gotoStep.getConditionCount(); c++) { listModel.addElement(gotoStep.getConditionAt(c).getName()); } conditionList = new JList(listModel); conditionList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); conditionList.addListSelectionListener(new ConditionListSelectionListener()); JScrollPane listScrollPane = new JScrollPane(conditionList); UISupport.addTitledBorder(listScrollPane, "Conditions"); JPanel p = new JPanel(new BorderLayout()); p.add(buildConditionListToolbar(), BorderLayout.NORTH); p.add(listScrollPane, BorderLayout.CENTER); return p; } private Component buildConditionListToolbar() { JXToolBar toolbar = UISupport.createSmallToolbar(); addButton = UISupport.createToolbarButton(new AddAction()); toolbar.addFixed(addButton); copyButton = UISupport.createToolbarButton(new CopyAction()); copyButton.setEnabled(false); toolbar.addFixed(copyButton); deleteButton = UISupport.createToolbarButton(new DeleteAction()); deleteButton.setEnabled(false); toolbar.addFixed(deleteButton); renameButton = UISupport.createToolbarButton(new RenameAction()); renameButton.setEnabled(false); toolbar.addFixed(renameButton); return toolbar; } private Component buildConditionToolbar() { JXToolBar toolbar = UISupport.createSmallToolbar(); declareButton = UISupport.createToolbarButton(new DeclareNamespacesAction()); declareButton.setEnabled(false); toolbar.addFixed(declareButton); runButton = UISupport.createToolbarButton(new RunAction()); toolbar.addFixed(runButton); toolbar.addGlue(); toolbar.addFixed(UISupport.createToolbarButton(new ShowOnlineHelpAction(HelpUrls.GOTOSTEPEDITOR_HELP_URL))); return toolbar; } protected JXToolBar buildTargetToolbar() { JXToolBar builder = UISupport.createSmallToolbar(); testStepsModel = new GotoTestStepsComboBoxModel(gotoStep.getTestCase(), null); testStepsCombo = new JComboBox(testStepsModel); testStepsCombo.setToolTipText("The step the test case will go to if the current condition is true"); testStepsCombo.setEnabled(false); UISupport.setFixedSize(testStepsCombo, 280, 20); builder.addFixed(new JLabel("<html><b>Target step:</b></html>")); builder.addRelatedGap(); builder.addFixed(testStepsCombo); builder.addGlue(); testConditionButton = new JButton(new TestConditionAction()); testConditionButton.setEnabled(false); builder.addFixed(testConditionButton); builder.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3)); return builder; } private final class SourceAreaDocumentListener extends DocumentListenerAdapter { @Override public void update(Document document) { int ix = conditionList.getSelectedIndex(); if (ix != -1) { gotoStep.getConditionAt(ix).setExpression(expressionArea.getText()); } } } private final class ConditionListSelectionListener implements ListSelectionListener { public void valueChanged(ListSelectionEvent e) { int ix = conditionList.getSelectedIndex(); if (ix == -1) { expressionArea.setText(""); testStepsModel.setCondition(null); currentCondition = null; } else { currentCondition = gotoStep.getConditionAt(ix); expressionArea.setText(currentCondition.getExpression()); testStepsModel.setCondition(currentCondition); } boolean b = ix != -1; enableEditComponents(b); } } private final class AddAction extends AbstractAction { public AddAction() { putValue(Action.SHORT_DESCRIPTION, "Adds a new Condition"); putValue(Action.SMALL_ICON, UISupport.createImageIcon("/add.png")); } public void actionPerformed(ActionEvent e) { String name = UISupport.prompt("Specify name for condition", "Add Condition", "Condition " + (gotoStep.getConditionCount() + 1)); if (name == null || name.trim().length() == 0) { return; } gotoStep.addCondition(name); listModel.addElement(name); conditionList.setSelectedIndex(listModel.getSize() - 1); } } private final class CopyAction extends AbstractAction { public CopyAction() { putValue(Action.SHORT_DESCRIPTION, "Copies the selected Condition"); putValue(Action.SMALL_ICON, UISupport.createImageIcon("/clone.png")); } public void actionPerformed(ActionEvent e) { int ix = conditionList.getSelectedIndex(); GotoCondition config = gotoStep.getConditionAt(ix); String name = UISupport.prompt("Specify name for condition", "Copy Condition", config.getName()); if (name == null || name.trim().length() == 0) { return; } GotoCondition condition = gotoStep.addCondition(name); condition.setExpression(config.getExpression()); condition.setTargetStep(config.getTargetStep()); condition.setType(config.getType()); listModel.addElement(name); conditionList.setSelectedIndex(listModel.getSize() - 1); } } private final class DeleteAction extends AbstractAction { public DeleteAction() { putValue(Action.SMALL_ICON, UISupport.createImageIcon("/delete.png")); putValue(Action.SHORT_DESCRIPTION, "Deletes the selected Condition"); } public void actionPerformed(ActionEvent e) { if (UISupport.confirm("Delete selected condition", "Delete Condition")) { int ix = conditionList.getSelectedIndex(); conditionList.setSelectedIndex(-1); gotoStep.removeConditionAt(ix); listModel.remove(ix); if (listModel.getSize() > 0) { conditionList.setSelectedIndex(ix > listModel.getSize() - 1 ? listModel.getSize() - 1 : ix); } } } } private final class RenameAction extends AbstractAction { public RenameAction() { putValue(Action.SMALL_ICON, UISupport.createImageIcon("/rename.gif")); putValue(Action.SHORT_DESCRIPTION, "Renames the selected Condition"); } public void actionPerformed(ActionEvent e) { int ix = conditionList.getSelectedIndex(); GotoCondition config = gotoStep.getConditionAt(ix); String name = UISupport.prompt("Specify name for condition", "Rename Condition", config.getName()); if (name == null || name.trim().length() == 0) { return; } config.setName(name); listModel.setElementAt(name, ix); } } private final class DeclareNamespacesAction extends AbstractAction { public DeclareNamespacesAction() { putValue(Action.SMALL_ICON, UISupport.createImageIcon("/declareNs.gif")); putValue(Action.SHORT_DESCRIPTION, "Declare available response namespaces in condition expression"); } public void actionPerformed(ActionEvent e) { try { SamplerTestStep previousStep = (SamplerTestStep) gotoStep.getTestCase().findPreviousStepOfType(gotoStep, SamplerTestStep.class); if (previousStep != null) { Response response = previousStep.getTestRequest().getResponse(); String xml = response == null ? null : response.getContentAsString(); if (XmlUtils.seemsToBeXml(xml)) { expressionArea.setText(XmlUtils.declareXPathNamespaces(xml) + expressionArea.getText()); } else { UISupport.showErrorMessage("Missing response in previous request step [" + previousStep.getName() + "]"); } } else { UISupport.showErrorMessage("Missing previous request step"); } } catch (Exception e1) { SoapUI.logError(e1); } } } private final class RunAction extends AbstractAction { public RunAction() { putValue(Action.SMALL_ICON, UISupport.createImageIcon("/run_all.png")); putValue(Action.SHORT_DESCRIPTION, "Runs the current conditions against the previous response"); } public void actionPerformed(ActionEvent e) { if (listModel.getSize() == 0) { UISupport.showErrorMessage("Missing conditions!"); return; } SamplerTestStep previousStep = gotoStep.getTestCase().findPreviousStepOfType(gotoStep, SamplerTestStep.class); if (previousStep == null) { UISupport.showErrorMessage("Missing previous request step"); } else { if (previousStep.getTestRequest().getResponse() == null || !XmlUtils.seemsToBeXml(previousStep.getTestRequest().getResponse().getContentAsXml())) { UISupport.showErrorMessage("Missing response in previous message"); return; } WsdlTestRunContext context = new WsdlTestRunContext(gotoStep); GotoCondition target = gotoStep.runConditions(previousStep, context); if (target == null) { logList.addLine("No condition true for current response in [" + previousStep.getName() + "]"); } else { logList.addLine("Condition triggered for go to [" + target.getTargetStep() + "]"); } inspectorPanel.setCurrentInspector("Log"); } } } private final class TestConditionAction extends AbstractAction { public TestConditionAction() { putValue(Action.SMALL_ICON, UISupport.createImageIcon("/run.png")); putValue(Action.SHORT_DESCRIPTION, "Runs the current condition against the previous response and shows the result"); } public void actionPerformed(ActionEvent e) { SamplerTestStep previousStep = gotoStep.getTestCase().findPreviousStepOfType(gotoStep, SamplerTestStep.class); if (previousStep == null) { UISupport.showErrorMessage("Missing previous request step"); } else { if (previousStep.getTestRequest().getResponse() == null || !XmlUtils.seemsToBeXml(previousStep.getTestRequest().getResponse().getContentAsXml())) { UISupport .showErrorMessage("Missing response in previous request step [" + previousStep.getName() + "]"); return; } try { GotoCondition condition = gotoStep.getConditionAt(conditionList.getSelectedIndex()); WsdlTestRunContext context = new WsdlTestRunContext(gotoStep); boolean evaluate = condition.evaluate(previousStep, context); if (!evaluate) { UISupport.showInfoMessage("Condition not true for current response in [" + previousStep.getName() + "]"); } else { UISupport.showInfoMessage("Condition true for current response in [" + previousStep.getName() + "]"); } } catch (Exception e1) { UISupport.showErrorMessage("Error checking condition: " + e1.getMessage()); } } } } public boolean onClose(boolean canCancel) { componentEnabler.release(); gotoStep.getTestCase().removeTestRunListener(testRunListener); testStepsModel.release(); inspectorPanel.release(); return release(); } public JComponent getComponent() { return this; } public boolean dependsOn(ModelItem modelItem) { return modelItem == gotoStep || modelItem == gotoStep.getTestCase() || modelItem == gotoStep.getTestCase().getTestSuite() || modelItem == gotoStep.getTestCase().getTestSuite().getProject(); } public GotoCondition getCurrentCondition() { return currentCondition; } protected void enableEditComponents(boolean b) { expressionArea.setEnabled(b); testStepsCombo.setEnabled(b); copyButton.setEnabled(b); deleteButton.setEnabled(b); declareButton.setEnabled(b); testConditionButton.setEnabled(b); renameButton.setEnabled(b); } private class InternalTestRunListener extends TestRunListenerAdapter { @Override public void afterStep(TestCaseRunner testRunner, TestCaseRunContext runContext, TestStepResult result) { if (result.getTestStep() == gotoStep) { logList.addLine(new Date(result.getTimeStamp()).toString() + ": " + result.getMessages()[0]); inspectorPanel.setCurrentInspector("Log"); } } } }