1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.panels.teststeps;
14
15 import java.awt.BorderLayout;
16 import java.awt.Component;
17 import java.awt.Dimension;
18 import java.awt.event.ActionEvent;
19 import java.util.Date;
20
21 import javax.swing.AbstractAction;
22 import javax.swing.Action;
23 import javax.swing.BorderFactory;
24 import javax.swing.DefaultListModel;
25 import javax.swing.JButton;
26 import javax.swing.JComboBox;
27 import javax.swing.JComponent;
28 import javax.swing.JLabel;
29 import javax.swing.JList;
30 import javax.swing.JPanel;
31 import javax.swing.JScrollPane;
32 import javax.swing.JSplitPane;
33 import javax.swing.JTextArea;
34 import javax.swing.ListSelectionModel;
35 import javax.swing.event.ListSelectionEvent;
36 import javax.swing.event.ListSelectionListener;
37 import javax.swing.text.Document;
38
39 import com.eviware.soapui.SoapUI;
40 import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
41 import com.eviware.soapui.impl.support.http.HttpRequestTestStep;
42 import com.eviware.soapui.impl.wsdl.panels.support.TestRunComponentEnabler;
43 import com.eviware.soapui.impl.wsdl.panels.teststeps.support.GotoTestStepsComboBoxModel;
44 import com.eviware.soapui.impl.wsdl.support.HelpUrls;
45 import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext;
46 import com.eviware.soapui.impl.wsdl.teststeps.WsdlGotoTestStep;
47 import com.eviware.soapui.impl.wsdl.teststeps.WsdlGotoTestStep.GotoCondition;
48 import com.eviware.soapui.model.ModelItem;
49 import com.eviware.soapui.model.support.TestRunListenerAdapter;
50 import com.eviware.soapui.model.testsuite.TestCaseRunContext;
51 import com.eviware.soapui.model.testsuite.TestCaseRunner;
52 import com.eviware.soapui.model.testsuite.TestStepResult;
53 import com.eviware.soapui.support.DocumentListenerAdapter;
54 import com.eviware.soapui.support.StringUtils;
55 import com.eviware.soapui.support.UISupport;
56 import com.eviware.soapui.support.components.JComponentInspector;
57 import com.eviware.soapui.support.components.JInspectorPanel;
58 import com.eviware.soapui.support.components.JInspectorPanelFactory;
59 import com.eviware.soapui.support.components.JUndoableTextArea;
60 import com.eviware.soapui.support.components.JXToolBar;
61 import com.eviware.soapui.support.log.JLogList;
62 import com.eviware.soapui.support.xml.XmlUtils;
63 import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
64
65 /***
66 * DesktopPanel for WsdlGotoTestSteps
67 *
68 * @author Ole.Matzura
69 */
70
71 public class GotoStepDesktopPanel extends ModelItemDesktopPanel<WsdlGotoTestStep>
72 {
73 private final WsdlGotoTestStep gotoStep;
74 private DefaultListModel listModel;
75 private JList conditionList;
76 private JTextArea expressionArea;
77 private JButton copyButton;
78 private JButton deleteButton;
79 private JButton declareButton;
80 private GotoTestStepsComboBoxModel testStepsModel;
81 private JComboBox testStepsCombo;
82 private JButton testConditionButton;
83 private TestRunComponentEnabler componentEnabler;
84 private GotoCondition currentCondition;
85 private JButton renameButton;
86 private JButton runButton;
87 private JButton addButton;
88 private JLogList logList;
89 private InternalTestRunListener testRunListener = new InternalTestRunListener();
90 private JInspectorPanel inspectorPanel;
91
92 public GotoStepDesktopPanel( WsdlGotoTestStep testStep )
93 {
94 super( testStep );
95 this.gotoStep = testStep;
96 componentEnabler = new TestRunComponentEnabler( testStep.getTestCase() );
97 gotoStep.getTestCase().addTestRunListener( testRunListener );
98
99 buildUI();
100 }
101
102 public TestRunComponentEnabler getComponentEnabler()
103 {
104 return componentEnabler;
105 }
106
107 public JList getConditionList()
108 {
109 return conditionList;
110 }
111
112 public JButton getCopyButton()
113 {
114 return copyButton;
115 }
116
117 public JButton getDeclareButton()
118 {
119 return declareButton;
120 }
121
122 public JButton getDeleteButton()
123 {
124 return deleteButton;
125 }
126
127 public JTextArea getExpressionArea()
128 {
129 return expressionArea;
130 }
131
132 public WsdlGotoTestStep getGotoStep()
133 {
134 return gotoStep;
135 }
136
137 public DefaultListModel getListModel()
138 {
139 return listModel;
140 }
141
142 public JButton getTestConditionButton()
143 {
144 return testConditionButton;
145 }
146
147 public JComboBox getTestStepsCombo()
148 {
149 return testStepsCombo;
150 }
151
152 public GotoTestStepsComboBoxModel getTestStepsModel()
153 {
154 return testStepsModel;
155 }
156
157 private void buildUI()
158 {
159 JSplitPane splitPane = UISupport.createHorizontalSplit();
160 splitPane.setLeftComponent( buildConditionList() );
161
162 splitPane.setRightComponent( buildExpressionArea() );
163 splitPane.setResizeWeight( 0.1 );
164 splitPane.setDividerLocation( 120 );
165
166 inspectorPanel = JInspectorPanelFactory.build( splitPane );
167 inspectorPanel.addInspector( new JComponentInspector<JComponent>( buildLog(), "Log",
168 "A log of evaluated conditions", true ) );
169
170 add( inspectorPanel.getComponent(), BorderLayout.CENTER );
171
172 setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) );
173 setPreferredSize( new Dimension( 550, 300 ) );
174
175 if( listModel.getSize() > 0 )
176 conditionList.setSelectedIndex( 0 );
177
178 componentEnabler.add( conditionList );
179 componentEnabler.add( expressionArea );
180 componentEnabler.add( testStepsCombo );
181 componentEnabler.add( testConditionButton );
182 componentEnabler.add( copyButton );
183 componentEnabler.add( declareButton );
184 componentEnabler.add( deleteButton );
185 componentEnabler.add( addButton );
186 componentEnabler.add( runButton );
187 componentEnabler.add( renameButton );
188 }
189
190 private JComponent buildLog()
191 {
192 logList = new JLogList( "ConditionLog" + getModelItem().getName() );
193 return logList;
194 }
195
196 private JPanel buildExpressionArea()
197 {
198 expressionArea = new JUndoableTextArea();
199 expressionArea.setEnabled( false );
200 expressionArea.getDocument().addDocumentListener( new SourceAreaDocumentListener() );
201
202 JPanel expressionPanel = new JPanel( new BorderLayout() );
203 JScrollPane scrollPane = new JScrollPane( expressionArea );
204 UISupport.addTitledBorder( scrollPane, "Condition XPath Expression" );
205
206 expressionPanel.add( scrollPane, BorderLayout.CENTER );
207 expressionPanel.add( buildConditionToolbar(), BorderLayout.NORTH );
208 expressionPanel.add( buildTargetToolbar(), BorderLayout.SOUTH );
209 return expressionPanel;
210 }
211
212 private JPanel buildConditionList()
213 {
214 listModel = new DefaultListModel();
215
216 for( int c = 0; c < gotoStep.getConditionCount(); c++ )
217 {
218 listModel.addElement( gotoStep.getConditionAt( c ).getName() );
219 }
220
221 conditionList = new JList( listModel );
222 conditionList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
223 conditionList.addListSelectionListener( new ConditionListSelectionListener() );
224
225 JScrollPane listScrollPane = new JScrollPane( conditionList );
226 UISupport.addTitledBorder( listScrollPane, "Conditions" );
227
228 JPanel p = new JPanel( new BorderLayout() );
229 p.add( buildConditionListToolbar(), BorderLayout.NORTH );
230 p.add( listScrollPane, BorderLayout.CENTER );
231 return p;
232 }
233
234 private Component buildConditionListToolbar()
235 {
236 JXToolBar toolbar = UISupport.createSmallToolbar();
237
238 addButton = UISupport.createToolbarButton( new AddAction() );
239 toolbar.addFixed( addButton );
240 copyButton = UISupport.createToolbarButton( new CopyAction() );
241 copyButton.setEnabled( false );
242 toolbar.addFixed( copyButton );
243 deleteButton = UISupport.createToolbarButton( new DeleteAction() );
244 deleteButton.setEnabled( false );
245 toolbar.addFixed( deleteButton );
246 renameButton = UISupport.createToolbarButton( new RenameAction() );
247 renameButton.setEnabled( false );
248 toolbar.addFixed( renameButton );
249 return toolbar;
250 }
251
252 private Component buildConditionToolbar()
253 {
254 JXToolBar toolbar = UISupport.createSmallToolbar();
255
256 declareButton = UISupport.createToolbarButton( new DeclareNamespacesAction() );
257 declareButton.setEnabled( false );
258 toolbar.addFixed( declareButton );
259 runButton = UISupport.createToolbarButton( new RunAction() );
260 toolbar.addFixed( runButton );
261
262 toolbar.addGlue();
263 toolbar.addFixed( UISupport.createToolbarButton( new ShowOnlineHelpAction( HelpUrls.GOTOSTEPEDITOR_HELP_URL ) ) );
264 return toolbar;
265 }
266
267 protected JXToolBar buildTargetToolbar()
268 {
269 JXToolBar builder = UISupport.createSmallToolbar();
270 testStepsModel = new GotoTestStepsComboBoxModel( gotoStep.getTestCase(), null );
271 testStepsCombo = new JComboBox( testStepsModel );
272 testStepsCombo.setToolTipText( "The step the test case will go to if the current condition is true" );
273 testStepsCombo.setEnabled( false );
274 builder.addFixed( new JLabel( "<html><b>Target step:</b></html>" ) );
275 builder.addRelatedGap();
276 builder.addFixed( testStepsCombo );
277 builder.addGlue();
278 testConditionButton = new JButton( new TestConditionAction() );
279 testConditionButton.setEnabled( false );
280 builder.addFixed( testConditionButton );
281 builder.setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) );
282 return builder;
283 }
284
285 private final class SourceAreaDocumentListener extends DocumentListenerAdapter
286 {
287 @Override
288 public void update( Document document )
289 {
290 int ix = conditionList.getSelectedIndex();
291 if( ix != -1 )
292 {
293 gotoStep.getConditionAt( ix ).setExpression( expressionArea.getText() );
294 }
295 }
296 }
297
298 private final class ConditionListSelectionListener implements ListSelectionListener
299 {
300 public void valueChanged( ListSelectionEvent e )
301 {
302 int ix = conditionList.getSelectedIndex();
303 if( ix == -1 )
304 {
305 expressionArea.setText( "" );
306 testStepsModel.setCondition( null );
307 currentCondition = null;
308 }
309 else
310 {
311 currentCondition = gotoStep.getConditionAt( ix );
312 expressionArea.setText( currentCondition.getExpression() );
313 testStepsModel.setCondition( currentCondition );
314 }
315
316 boolean b = ix != -1;
317 enableEditComponents( b );
318 }
319 }
320
321 private final class AddAction extends AbstractAction
322 {
323 public AddAction()
324 {
325 putValue( Action.SHORT_DESCRIPTION, "Adds a new Conditionr" );
326 putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/add_property.gif" ) );
327 }
328
329 public void actionPerformed( ActionEvent e )
330 {
331 String name = UISupport.prompt( "Specify name for condition", "Add Condition", "Condition "
332 + ( gotoStep.getConditionCount() + 1 ) );
333 if( name == null || name.trim().length() == 0 )
334 return;
335
336 gotoStep.addCondition( name );
337
338 listModel.addElement( name );
339 conditionList.setSelectedIndex( listModel.getSize() - 1 );
340 }
341 }
342
343 private final class CopyAction extends AbstractAction
344 {
345 public CopyAction()
346 {
347 putValue( Action.SHORT_DESCRIPTION, "Copies the selected Condition" );
348 putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/clone_request.gif" ) );
349 }
350
351 public void actionPerformed( ActionEvent e )
352 {
353 int ix = conditionList.getSelectedIndex();
354 GotoCondition config = gotoStep.getConditionAt( ix );
355
356 String name = UISupport.prompt( "Specify name for condition", "Copy Condition", config.getName() );
357 if( name == null || name.trim().length() == 0 )
358 return;
359
360 GotoCondition condition = gotoStep.addCondition( name );
361 condition.setExpression( config.getExpression() );
362 condition.setTargetStep( config.getTargetStep() );
363 condition.setType( config.getType() );
364
365 listModel.addElement( name );
366 conditionList.setSelectedIndex( listModel.getSize() - 1 );
367 }
368 }
369
370 private final class DeleteAction extends AbstractAction
371 {
372 public DeleteAction()
373 {
374 putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/remove_property.gif" ) );
375 putValue( Action.SHORT_DESCRIPTION, "Deletes the selected Condition" );
376 }
377
378 public void actionPerformed( ActionEvent e )
379 {
380 if( UISupport.confirm( "Delete selected condition", "Delete Condition" ) )
381 {
382 int ix = conditionList.getSelectedIndex();
383
384 conditionList.setSelectedIndex( -1 );
385
386 gotoStep.removeConditionAt( ix );
387 listModel.remove( ix );
388
389 if( listModel.getSize() > 0 )
390 {
391 conditionList.setSelectedIndex( ix > listModel.getSize() - 1 ? listModel.getSize() - 1 : ix );
392 }
393 }
394 }
395 }
396
397 private final class RenameAction extends AbstractAction
398 {
399 public RenameAction()
400 {
401 putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/rename.gif" ) );
402 putValue( Action.SHORT_DESCRIPTION, "Renames the selected Condition" );
403 }
404
405 public void actionPerformed( ActionEvent e )
406 {
407 int ix = conditionList.getSelectedIndex();
408 GotoCondition config = gotoStep.getConditionAt( ix );
409
410 String name = UISupport.prompt( "Specify name for condition", "Copy Condition", config.getName() );
411 if( name == null || name.trim().length() == 0 )
412 return;
413
414 config.setName( name );
415 listModel.setElementAt( name, ix );
416 }
417 }
418
419 private final class DeclareNamespacesAction extends AbstractAction
420 {
421 public DeclareNamespacesAction()
422 {
423 putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/declareNs.gif" ) );
424 putValue( Action.SHORT_DESCRIPTION, "Declare available response namespaces in condition expression" );
425 }
426
427 public void actionPerformed( ActionEvent e )
428 {
429 try
430 {
431 HttpRequestTestStep previousStep = ( HttpRequestTestStep )gotoStep.getTestCase().findPreviousStepOfType(
432 gotoStep, HttpRequestTestStep.class );
433
434 if( previousStep != null )
435 {
436 String xml = previousStep.getHttpRequest().getResponse().getContentAsString();
437 if( StringUtils.hasContent( xml ) )
438 {
439 expressionArea.setText( XmlUtils.declareXPathNamespaces( xml ) + expressionArea.getText() );
440 }
441 else
442 {
443 UISupport.showErrorMessage( "Missing response in previous request step [" + previousStep.getName()
444 + "]" );
445 }
446 }
447 else
448 {
449 UISupport.showErrorMessage( "Missing previous request step" );
450 }
451 }
452 catch( Exception e1 )
453 {
454 SoapUI.logError( e1 );
455 }
456 }
457 }
458
459 private final class RunAction extends AbstractAction
460 {
461 public RunAction()
462 {
463 putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run_all.gif" ) );
464 putValue( Action.SHORT_DESCRIPTION, "Runs the current conditions against the previous response" );
465 }
466
467 public void actionPerformed( ActionEvent e )
468 {
469 if( listModel.getSize() == 0 )
470 {
471 UISupport.showErrorMessage( "Missing conditions!" );
472 return;
473 }
474
475 HttpRequestTestStep previousStep = gotoStep.getTestCase().findPreviousStepOfType( gotoStep,
476 HttpRequestTestStep.class );
477
478 if( previousStep == null )
479 {
480 UISupport.showErrorMessage( "Missing previous request step" );
481 }
482 else
483 {
484 if( previousStep.getHttpRequest().getResponse() == null
485 || StringUtils.isNullOrEmpty( previousStep.getHttpRequest().getResponse().getContentAsXml() ) )
486 {
487 UISupport.showErrorMessage( "Missing response in previous message" );
488 return;
489 }
490
491 WsdlTestRunContext context = new WsdlTestRunContext( gotoStep );
492 GotoCondition target = gotoStep.runConditions( previousStep, context );
493 if( target == null )
494 {
495 logList.addLine( "No condition true for current response in [" + previousStep.getName() + "]" );
496 }
497 else
498 {
499 logList.addLine( "Condition triggered for go to [" + target.getTargetStep() + "]" );
500 }
501
502 inspectorPanel.setCurrentInspector( "Log" );
503 }
504 }
505 }
506
507 private final class TestConditionAction extends AbstractAction
508 {
509 public TestConditionAction()
510 {
511 putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run.gif" ) );
512 putValue( Action.SHORT_DESCRIPTION,
513 "Runs the current condition against the previous response and shows the result" );
514 }
515
516 public void actionPerformed( ActionEvent e )
517 {
518 HttpRequestTestStep previousStep = gotoStep.getTestCase().findPreviousStepOfType( gotoStep,
519 HttpRequestTestStep.class );
520
521 if( previousStep == null )
522 {
523 UISupport.showErrorMessage( "Missing previous request step" );
524 }
525 else
526 {
527 if( previousStep.getHttpRequest().getResponse() == null
528 || !StringUtils.hasContent( previousStep.getHttpRequest().getResponse().getContentAsXml() ) )
529 {
530 UISupport
531 .showErrorMessage( "Missing response in previous request step [" + previousStep.getName() + "]" );
532 return;
533 }
534
535 try
536 {
537 GotoCondition condition = gotoStep.getConditionAt( conditionList.getSelectedIndex() );
538 WsdlTestRunContext context = new WsdlTestRunContext( gotoStep );
539 boolean evaluate = condition.evaluate( previousStep, context );
540 if( !evaluate )
541 {
542 UISupport.showInfoMessage( "Condition not true for current response in [" + previousStep.getName()
543 + "]" );
544 }
545 else
546 {
547 UISupport.showInfoMessage( "Condition true for current response in [" + previousStep.getName() + "]" );
548 }
549 }
550 catch( Exception e1 )
551 {
552 UISupport.showErrorMessage( "Error checking condition: " + e1.getMessage() );
553 }
554 }
555 }
556 }
557
558 public boolean onClose( boolean canCancel )
559 {
560 super.release();
561 componentEnabler.release();
562 gotoStep.getTestCase().removeTestRunListener( testRunListener );
563 testStepsModel.release();
564 inspectorPanel.release();
565
566 return true;
567 }
568
569 public JComponent getComponent()
570 {
571 return this;
572 }
573
574 public boolean dependsOn( ModelItem modelItem )
575 {
576 return modelItem == gotoStep || modelItem == gotoStep.getTestCase()
577 || modelItem == gotoStep.getTestCase().getTestSuite()
578 || modelItem == gotoStep.getTestCase().getTestSuite().getProject();
579 }
580
581 public GotoCondition getCurrentCondition()
582 {
583 return currentCondition;
584 }
585
586 protected void enableEditComponents( boolean b )
587 {
588 expressionArea.setEnabled( b );
589 testStepsCombo.setEnabled( b );
590 copyButton.setEnabled( b );
591 deleteButton.setEnabled( b );
592 declareButton.setEnabled( b );
593 testConditionButton.setEnabled( b );
594 renameButton.setEnabled( b );
595 }
596
597 private class InternalTestRunListener extends TestRunListenerAdapter
598 {
599 @Override
600 public void afterStep( TestCaseRunner testRunner, TestCaseRunContext runContext, TestStepResult result )
601 {
602 if( result.getTestStep() == gotoStep )
603 {
604 logList.addLine( new Date( result.getTimeStamp() ).toString() + ": " + result.getMessages()[0] );
605 inspectorPanel.setCurrentInspector( "Log" );
606 }
607 }
608 }
609 }