1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.panels.testcase;
14
15 import java.awt.BorderLayout;
16 import java.awt.Component;
17 import java.awt.Dimension;
18 import java.awt.dnd.DnDConstants;
19 import java.awt.dnd.DragSource;
20 import java.awt.event.ActionEvent;
21 import java.text.SimpleDateFormat;
22 import java.util.Date;
23
24 import javax.swing.AbstractAction;
25 import javax.swing.Action;
26 import javax.swing.BorderFactory;
27 import javax.swing.Box;
28 import javax.swing.JButton;
29 import javax.swing.JComponent;
30 import javax.swing.JList;
31 import javax.swing.JPanel;
32 import javax.swing.JProgressBar;
33 import javax.swing.JScrollPane;
34 import javax.swing.JTabbedPane;
35 import javax.swing.JTextArea;
36 import javax.swing.JToggleButton;
37 import javax.swing.JToolBar;
38 import javax.swing.ListModel;
39 import javax.swing.SwingConstants;
40 import javax.swing.SwingUtilities;
41 import javax.swing.text.Document;
42
43 import com.eviware.soapui.SoapUI;
44 import com.eviware.soapui.config.TestStepConfig;
45 import com.eviware.soapui.impl.wsdl.actions.support.ShowOnlineHelpAction;
46 import com.eviware.soapui.impl.wsdl.actions.testcase.TestCaseOptionsAction;
47 import com.eviware.soapui.impl.wsdl.panels.support.MockTestRunContext;
48 import com.eviware.soapui.impl.wsdl.panels.support.MockTestRunner;
49 import com.eviware.soapui.impl.wsdl.panels.support.ProgressBarTestCaseAdapter;
50 import com.eviware.soapui.impl.wsdl.panels.testcase.actions.SetCredentialsAction;
51 import com.eviware.soapui.impl.wsdl.panels.testcase.actions.SetEndpointAction;
52 import com.eviware.soapui.impl.wsdl.panels.teststeps.support.AbstractGroovyEditorModel;
53 import com.eviware.soapui.impl.wsdl.panels.teststeps.support.PropertyHolderTable;
54 import com.eviware.soapui.impl.wsdl.support.HelpUrls;
55 import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
56 import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCaseRunner;
57 import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestStep;
58 import com.eviware.soapui.impl.wsdl.teststeps.registry.WsdlTestStepFactory;
59 import com.eviware.soapui.impl.wsdl.teststeps.registry.WsdlTestStepRegistry;
60 import com.eviware.soapui.model.ModelItem;
61 import com.eviware.soapui.model.support.TestRunListenerAdapter;
62 import com.eviware.soapui.model.testsuite.LoadTestRunner;
63 import com.eviware.soapui.model.testsuite.TestRunContext;
64 import com.eviware.soapui.model.testsuite.TestRunner;
65 import com.eviware.soapui.model.testsuite.TestStep;
66 import com.eviware.soapui.model.testsuite.TestStepResult;
67 import com.eviware.soapui.monitor.support.TestMonitorListenerAdapter;
68 import com.eviware.soapui.support.DocumentListenerAdapter;
69 import com.eviware.soapui.support.UISupport;
70 import com.eviware.soapui.support.action.swing.SwingActionDelegate;
71 import com.eviware.soapui.support.components.GroovyEditorComponent;
72 import com.eviware.soapui.support.components.GroovyEditorInspector;
73 import com.eviware.soapui.support.components.JComponentInspector;
74 import com.eviware.soapui.support.components.JFocusableComponentInspector;
75 import com.eviware.soapui.support.components.JInspectorPanel;
76 import com.eviware.soapui.support.components.JUndoableTextArea;
77 import com.eviware.soapui.support.components.JXToolBar;
78 import com.eviware.soapui.support.dnd.DropType;
79 import com.eviware.soapui.support.dnd.JListDragAndDropable;
80 import com.eviware.soapui.support.dnd.SoapUIDragAndDropHandler;
81 import com.eviware.soapui.support.swing.ComponentBag;
82 import com.eviware.soapui.support.types.StringToObjectMap;
83 import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
84
85 /***
86 * WsdlTestCase desktop panel
87 *
88 * @author Ole.Matzura
89 */
90
91 public class WsdlTestCaseDesktopPanel extends ModelItemDesktopPanel<WsdlTestCase>
92 {
93 private JProgressBar progressBar;
94 private TestStepList testStepList;
95 private InternalTestRunListener testRunListener = new InternalTestRunListener();
96 private JButton runButton;
97 private JButton cancelButton;
98 private TestRunner runner;
99 private JButton setEndpointButton;
100 private JButton setCredentialsButton;
101 private JButton optionsButton;
102 private ComponentBag stateDependantComponents = new ComponentBag();
103 private TestRunLog testCaseLog;
104 private JToggleButton loopButton;
105 @SuppressWarnings( "unused" )
106 private ProgressBarTestCaseAdapter progressBarAdapter;
107 private InternalTestMonitorListener testMonitorListener;
108 public boolean canceled;
109 private JTextArea descriptionArea;
110 private PropertyHolderTable propertiesTable;
111 private GroovyEditorComponent tearDownGroovyEditor;
112 private GroovyEditorComponent setupGroovyEditor;
113
114 public WsdlTestCaseDesktopPanel( WsdlTestCase testCase )
115 {
116 super( testCase );
117
118 buildUI();
119
120 setPreferredSize( new Dimension( 400, 550 ) );
121 setRunningState();
122
123 testCase.addTestRunListener( testRunListener );
124 progressBarAdapter = new ProgressBarTestCaseAdapter( progressBar, testCase );
125 testMonitorListener = new InternalTestMonitorListener();
126
127 SoapUI.getTestMonitor().addTestMonitorListener( testMonitorListener );
128
129 DragSource dragSource = DragSource.getDefaultDragSource();
130 SoapUIDragAndDropHandler dragAndDropHandler = new SoapUIDragAndDropHandler(
131 new ModelItemListDragAndDropable( getTestStepList().getTestStepList(), testCase ), DropType.BEFORE_AND_AFTER );
132
133 dragSource.createDefaultDragGestureRecognizer( getTestStepList().getTestStepList(), DnDConstants.ACTION_COPY_OR_MOVE,
134 dragAndDropHandler );
135 }
136
137 /***
138 * There are three states: - enabled, no testcases or testschedules running -
139 * enabled, standalone testcase running - disabled, testschedule is running
140 */
141
142 private void setRunningState()
143 {
144 stateDependantComponents.setEnabled( !SoapUI.getTestMonitor().hasRunningLoadTest( getModelItem() ) );
145 }
146
147 private void buildUI()
148 {
149 JPanel panel = new JPanel( new BorderLayout() );
150
151 panel.add( buildToolbar(), BorderLayout.PAGE_START );
152 panel.add( buildRunnerBar(), BorderLayout.CENTER );
153
154 add( panel, BorderLayout.NORTH );
155
156 JInspectorPanel inspectorPanel = new JInspectorPanel( buildContent() );
157 inspectorPanel.addInspector( new JComponentInspector( buildTestLog(), "TestCase Log", "TestCase Execution Log", true ) );
158 inspectorPanel.setDefaultDividerLocation( 0.7F );
159 inspectorPanel.setCurrentInspector( "TestCase Log" );
160
161 add( inspectorPanel, BorderLayout.CENTER );
162 }
163
164 protected TestStepList getTestStepList()
165 {
166 return testStepList;
167 }
168
169 private JComponent buildTestLog()
170 {
171 testCaseLog = new TestCaseTestRunLog(getModelItem());
172 stateDependantComponents.add( testCaseLog );
173 return testCaseLog;
174 }
175
176 private JComponent buildContent()
177 {
178 JTabbedPane tabs = new JTabbedPane( JTabbedPane.TOP );
179 JInspectorPanel inspectorPanel = new JInspectorPanel( buildTestStepList(),
180 SwingConstants.BOTTOM);
181
182 tabs.addTab( "TestSteps", inspectorPanel );
183
184 addTabs( tabs, inspectorPanel );
185 tabs.setTabLayoutPolicy( JTabbedPane.SCROLL_TAB_LAYOUT );
186
187 return UISupport.createTabPanel( tabs, true );
188 }
189
190 protected JComponent buildTestStepList()
191 {
192 JPanel p = new JPanel( new BorderLayout() );
193 JXToolBar toolbar = UISupport.createToolbar();
194
195 WsdlTestStepFactory[] factories = WsdlTestStepRegistry.getInstance().getFactories();
196 for( WsdlTestStepFactory factory : factories )
197 {
198 toolbar.addFixed( UISupport.createToolbarButton( new AddWsdlTestStepAction( factory ) ) );
199 }
200
201 p.add( toolbar, BorderLayout.NORTH );
202 testStepList = new TestStepList( getModelItem() );
203 stateDependantComponents.add( testStepList );
204
205 p.add( new JScrollPane( testStepList ), BorderLayout.CENTER );
206
207 return p;
208 }
209
210 protected void addTabs( JTabbedPane tabs, JInspectorPanel inspectorPanel )
211 {
212 inspectorPanel.addInspector( new JFocusableComponentInspector<JPanel>( buildDescriptionPanel(),
213 descriptionArea, "Description", "TestCase Description", true ) );
214 inspectorPanel.addInspector( new JComponentInspector( buildPropertiesPanel(), "Properties", "TestCase level properties", true ) );
215 inspectorPanel.addInspector( new GroovyEditorInspector( buildSetupScriptPanel(), "Setup Script", "Script to run before tunning a TestCase" ) );
216 inspectorPanel.addInspector( new GroovyEditorInspector( buildTearDownScriptPanel(), "TearDown Script", "Script to run after a TestCase Run" ) );
217 }
218
219 protected GroovyEditorComponent buildTearDownScriptPanel()
220 {
221 tearDownGroovyEditor = new GroovyEditorComponent( new TearDownScriptGroovyEditorModel(), null );
222 return tearDownGroovyEditor;
223 }
224
225 protected GroovyEditorComponent buildSetupScriptPanel()
226 {
227 setupGroovyEditor = new GroovyEditorComponent( new SetupScriptGroovyEditorModel(), null );
228 return setupGroovyEditor;
229 }
230
231 protected JComponent buildPropertiesPanel()
232 {
233 JPanel panel = new JPanel( new BorderLayout() );
234 propertiesTable = buildPropertiesTable();
235 panel.add( new JScrollPane( propertiesTable ), BorderLayout.CENTER );
236 return panel;
237 }
238
239 protected PropertyHolderTable buildPropertiesTable()
240 {
241 return new PropertyHolderTable( getModelItem() );
242 }
243
244 private JPanel buildDescriptionPanel()
245 {
246 JPanel panel = new JPanel( new BorderLayout() );
247 descriptionArea = new JUndoableTextArea( getModelItem().getDescription() );
248 descriptionArea.getDocument().addDocumentListener( new DocumentListenerAdapter()
249 {
250 public void update( Document document )
251 {
252 getModelItem().setDescription( descriptionArea.getText() );
253 }
254 } );
255
256 panel.setBorder( BorderFactory.createEmptyBorder( 2, 2, 2, 2 ) );
257 panel.add( new JScrollPane( descriptionArea ), BorderLayout.CENTER );
258 UISupport.addTitledBorder( panel, "TestCase Description" );
259
260 return panel;
261 }
262
263 private Component buildToolbar()
264 {
265 JToolBar toolbar = UISupport.createToolbar();
266
267 runButton = UISupport.createToolbarButton( new RunTestCaseAction() );
268 optionsButton = UISupport.createToolbarButton( SwingActionDelegate.createDelegate(
269 TestCaseOptionsAction.SOAPUI_ACTION_ID, getModelItem(), null, "/options.gif" ) );
270 optionsButton.setText( null );
271 cancelButton = UISupport.createToolbarButton( new CancelRunTestCaseAction(), false );
272
273 loopButton = new JToggleButton( UISupport.createImageIcon( "/loop.gif" ) );
274 loopButton.setPreferredSize( UISupport.getPreferredButtonSize() );
275 loopButton.setToolTipText( "Loop TestCase continuously" );
276
277 setCredentialsButton = UISupport.createToolbarButton( new SetCredentialsAction( getModelItem() ) );
278 setEndpointButton = UISupport.createToolbarButton( new SetEndpointAction( getModelItem() ) );
279
280 stateDependantComponents.add( runButton );
281 stateDependantComponents.add( optionsButton );
282 stateDependantComponents.add( cancelButton );
283 stateDependantComponents.add( setCredentialsButton );
284 stateDependantComponents.add( setEndpointButton );
285
286 addToolbarActions( toolbar );
287
288 toolbar.add( Box.createHorizontalGlue() );
289 toolbar.add( UISupport.createToolbarButton( new ShowOnlineHelpAction( HelpUrls.TESTCASEEDITOR_HELP_URL ) ) );
290
291 return toolbar;
292 }
293
294 protected void addToolbarActions( JToolBar toolbar )
295 {
296 toolbar.add( runButton );
297 toolbar.add( cancelButton );
298 toolbar.add( loopButton );
299 toolbar.add( setCredentialsButton );
300 toolbar.add( setEndpointButton );
301 toolbar.add( optionsButton );
302 }
303
304 private Component buildRunnerBar()
305 {
306 progressBar = new JProgressBar( 0, getModelItem().getTestStepCount() );
307 return UISupport.createProgressBarPanel( progressBar, 10, false );
308 }
309
310 private final class InternalTestMonitorListener extends TestMonitorListenerAdapter
311 {
312 public void loadTestStarted( LoadTestRunner runner )
313 {
314 setRunningState();
315 }
316
317 public void loadTestFinished( LoadTestRunner runner )
318 {
319 setRunningState();
320 }
321 }
322
323 public class InternalTestRunListener extends TestRunListenerAdapter
324 {
325 private SimpleDateFormat dateFormat;
326
327 public InternalTestRunListener()
328 {
329 dateFormat = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss.SSS" );
330 }
331
332 public void beforeRun( TestRunner testRunner, TestRunContext runContext )
333 {
334 if( SoapUI.getTestMonitor().hasRunningLoadTest( getModelItem() ) )
335 return;
336
337 runButton.setEnabled( false );
338 cancelButton.setEnabled( true );
339 testStepList.setEnabled( false );
340 testStepList.setSelectedIndex( -1 );
341 testCaseLog.clear();
342
343 testCaseLog.addText( "Test started at " + dateFormat.format( new Date() ) );
344
345 WsdlTestCaseDesktopPanel.this.beforeRun();
346 }
347
348 public void beforeStep( TestRunner testRunner, TestRunContext runContext )
349 {
350 if( SoapUI.getTestMonitor().hasRunningLoadTest( getModelItem() ) )
351 return;
352
353 TestStep testStep = runContext.getCurrentStep();
354 testStepList.setSelectedValue( testStep, true );
355 }
356
357 public void afterRun( TestRunner testRunner, TestRunContext runContext )
358 {
359 if( SoapUI.getTestMonitor().hasRunningLoadTest( getModelItem() ) )
360 return;
361
362 WsdlTestCaseRunner wsdlRunner = ( WsdlTestCaseRunner ) testRunner;
363
364 if( testRunner.getStatus() == TestRunner.Status.CANCELED )
365 testCaseLog.addText( "TestCase canceled [" + testRunner.getReason() + "], time taken = "
366 + wsdlRunner.getTimeTaken() );
367 else if( testRunner.getStatus() == TestRunner.Status.FAILED )
368 {
369 String msg = wsdlRunner.getReason();
370 if( wsdlRunner.getError() != null )
371 {
372 if( msg != null )
373 msg += ":";
374
375 msg += wsdlRunner.getError();
376 }
377
378 testCaseLog.addText( "TestCase failed [" + msg + "], time taken = "
379 + wsdlRunner.getTimeTaken() );
380 }
381 else
382 testCaseLog.addText( "TestCase finished with status [" + testRunner.getStatus() + "], time taken = " + wsdlRunner.getTimeTaken() );
383
384 runner = null;
385
386 JToggleButton loopButton = ( JToggleButton ) runContext.getProperty( "loopButton" );
387 if( loopButton != null && loopButton.isSelected() && testRunner.getStatus() == TestRunner.Status.FINISHED )
388 {
389 SwingUtilities.invokeLater( new Runnable()
390 {
391 public void run()
392 {
393 runTestCase();
394 }
395 } );
396 }
397 else
398 {
399 WsdlTestCaseDesktopPanel.this.afterRun();
400 }
401 }
402
403 public void afterStep( TestRunner testRunner, TestRunContext runContext, TestStepResult stepResult )
404 {
405 if( SoapUI.getTestMonitor().hasRunningLoadTest( getModelItem() ) )
406 return;
407
408 testCaseLog.addTestStepResult( stepResult );
409 }
410 }
411
412 protected void runTestCase()
413 {
414 if( canceled )
415 {
416
417 runButton.setEnabled( true );
418 cancelButton.setEnabled( false );
419 testStepList.setEnabled( true );
420 return;
421 }
422
423 StringToObjectMap properties = new StringToObjectMap();
424 properties.put( "loopButton", loopButton );
425 runner = getModelItem().run( properties, true );
426 }
427
428 public class RunTestCaseAction extends AbstractAction
429 {
430 public RunTestCaseAction()
431 {
432 putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run_testcase.gif" ) );
433 putValue( Action.SHORT_DESCRIPTION, "Runs this testcase" );
434 }
435
436 public void actionPerformed( ActionEvent e )
437 {
438 canceled = false;
439 runTestCase();
440 }
441 }
442
443 public class CancelRunTestCaseAction extends AbstractAction
444 {
445 public CancelRunTestCaseAction()
446 {
447 putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/stop_testcase.gif" ) );
448 putValue( Action.SHORT_DESCRIPTION, "Stops running this testcase" );
449 }
450
451 public void actionPerformed( ActionEvent e )
452 {
453 if( runner != null )
454 runner.cancel( "canceled in UI" );
455
456 canceled = true;
457 }
458 }
459
460 public boolean onClose( boolean canCancel )
461 {
462 if( canCancel )
463 {
464 if( runner != null && runner.getStatus() == TestRunner.Status.RUNNING )
465 {
466 Boolean retval = UISupport.confirmOrCancel( "Cancel running TestCase?", "Cancel Run" );
467
468 if( retval == null )
469 return false;
470 if( retval.booleanValue() )
471 {
472 runner.cancel( null );
473 }
474 }
475 }
476 else
477 {
478 if( runner != null && runner.getStatus() == TestRunner.Status.RUNNING )
479 {
480 runner.cancel( null );
481 }
482 }
483
484 SoapUI.getTestMonitor().removeTestMonitorListener( testMonitorListener );
485 getModelItem().removeTestRunListener( testRunListener );
486 testStepList.release();
487 progressBarAdapter.release();
488 propertiesTable.release();
489
490 setupGroovyEditor.getEditor().release();
491 tearDownGroovyEditor.getEditor().release();
492
493 testCaseLog.release();
494
495 return release();
496 }
497
498 public boolean dependsOn( ModelItem modelItem )
499 {
500 return modelItem == getModelItem() || modelItem == getModelItem().getTestSuite()
501 || modelItem == getModelItem().getTestSuite().getProject();
502 }
503
504 protected void beforeRun()
505 {
506 }
507
508 protected void afterRun()
509 {
510 runButton.setEnabled( true );
511 cancelButton.setEnabled( false );
512 testStepList.setEnabled( true );
513 }
514
515 private class SetupScriptGroovyEditorModel extends AbstractGroovyEditorModel
516 {
517 @Override
518 public Action createRunAction()
519 {
520 return new AbstractAction(){
521
522 public void actionPerformed( ActionEvent e )
523 {
524 try
525 {
526 MockTestRunner mockTestRunner = new MockTestRunner( getModelItem(), SoapUI.ensureGroovyLog() );
527 getModelItem().runSetupScript( new MockTestRunContext(mockTestRunner,null), mockTestRunner );
528 }
529 catch( Exception e1 )
530 {
531 UISupport.showErrorMessage( e1 );
532 }
533 }};
534 }
535
536 public SetupScriptGroovyEditorModel()
537 {
538 super( new String[] {"log", "context", "testRunner" }, getModelItem().getSettings(), "Setup" );
539 }
540
541 public String getScript()
542 {
543 return getModelItem().getSetupScript();
544 }
545
546 public void setScript( String text )
547 {
548 getModelItem().setSetupScript( text );
549 }
550 }
551
552 private class TearDownScriptGroovyEditorModel extends AbstractGroovyEditorModel
553 {
554 @Override
555 public Action createRunAction()
556 {
557 return new AbstractAction(){
558
559 public void actionPerformed( ActionEvent e )
560 {
561 try
562 {
563 MockTestRunner mockTestRunner = new MockTestRunner( getModelItem(), SoapUI.ensureGroovyLog() );
564 getModelItem().runTearDownScript( new MockTestRunContext(mockTestRunner,null), mockTestRunner );
565 }
566 catch( Exception e1 )
567 {
568 UISupport.showErrorMessage( e1 );
569 }
570 }};
571 }
572
573 public TearDownScriptGroovyEditorModel()
574 {
575 super( new String[] {"log", "context", "testRunner" }, getModelItem().getSettings(), "TearDown" );
576 }
577
578 public String getScript()
579 {
580 return getModelItem().getTearDownScript();
581 }
582
583 public void setScript( String text )
584 {
585 getModelItem().setTearDownScript( text );
586 }
587 }
588
589 private class AddWsdlTestStepAction extends AbstractAction
590 {
591 private final WsdlTestStepFactory factory;
592
593 public AddWsdlTestStepAction( WsdlTestStepFactory factory )
594 {
595 this.factory = factory;
596 putValue( SMALL_ICON, UISupport.createImageIcon( factory.getTestStepIconPath() ));
597 putValue( SHORT_DESCRIPTION, "Create a new " + factory.getTestStepName() + " TestStep");
598 }
599
600 public void actionPerformed( ActionEvent e )
601 {
602 int ix = testStepList.getTestStepList().getSelectedIndex();
603
604 String name = UISupport.prompt( "Specify name for new step", ix == -1 ? "Add Step" : "Insert Step", factory.getTestStepName());
605 if( name != null )
606 {
607 TestStepConfig newTestStepConfig = factory.createNewTestStep(getModelItem(), name);
608 if( newTestStepConfig != null )
609 {
610 WsdlTestStep testStep = getModelItem().insertTestStep(newTestStepConfig, ix);
611 UISupport.selectAndShow( testStep );
612 }
613 }
614
615 }
616 }
617
618 public static class ModelItemListDragAndDropable extends JListDragAndDropable<JList>
619 {
620 public ModelItemListDragAndDropable( JList list, WsdlTestCase testCase )
621 {
622 super( list, testCase );
623 }
624
625 @Override
626 public ModelItem getModelItemAtRow( int row )
627 {
628 return ( ModelItem ) getList().getModel().getElementAt( row );
629 }
630
631 @Override
632 public int getModelItemRow( ModelItem modelItem )
633 {
634 ListModel model = getList().getModel();
635
636 for( int c = 0; c < model.getSize(); c++ )
637 {
638 if( model.getElementAt( c ) == modelItem )
639 return c;
640 }
641
642 return -1;
643 }
644
645 public Component getRenderer( ModelItem modelItem )
646 {
647 return getList().getCellRenderer().getListCellRendererComponent( getList(), modelItem,
648 getModelItemRow( modelItem ), true, true );
649 }
650
651 @Override
652 public void setDragInfo( String dropInfo )
653 {
654 super.setDragInfo( dropInfo == null || dropInfo.length() == 0 ? null : dropInfo );
655 }
656 }
657 }