View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2009 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  
13  package com.eviware.soapui.impl.wsdl.panels.testsuite;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Color;
17  import java.awt.Component;
18  import java.awt.Dimension;
19  import java.awt.event.ActionEvent;
20  import java.awt.event.ActionListener;
21  
22  import javax.swing.AbstractAction;
23  import javax.swing.Action;
24  import javax.swing.BorderFactory;
25  import javax.swing.ButtonGroup;
26  import javax.swing.JComponent;
27  import javax.swing.JPanel;
28  import javax.swing.JProgressBar;
29  import javax.swing.JScrollPane;
30  import javax.swing.JTabbedPane;
31  import javax.swing.JTextArea;
32  import javax.swing.JToggleButton;
33  import javax.swing.text.Document;
34  
35  import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
36  import com.eviware.soapui.impl.wsdl.WsdlTestSuite;
37  import com.eviware.soapui.impl.wsdl.actions.testsuite.AddNewTestCaseAction;
38  import com.eviware.soapui.impl.wsdl.panels.support.MockTestSuiteRunner;
39  import com.eviware.soapui.impl.wsdl.panels.testcase.JTestRunLog;
40  import com.eviware.soapui.impl.wsdl.panels.testcase.TestRunLogTestRunListener;
41  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.AbstractGroovyEditorModel;
42  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.PropertyHolderTable;
43  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
44  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestSuiteRunner;
45  import com.eviware.soapui.model.ModelItem;
46  import com.eviware.soapui.model.support.TestSuiteListenerAdapter;
47  import com.eviware.soapui.model.testsuite.TestCase;
48  import com.eviware.soapui.model.testsuite.TestCaseRunner;
49  import com.eviware.soapui.model.testsuite.TestSuiteRunContext;
50  import com.eviware.soapui.model.testsuite.TestSuiteRunListener;
51  import com.eviware.soapui.model.testsuite.TestSuiteRunner;
52  import com.eviware.soapui.model.testsuite.TestSuite.TestSuiteRunType;
53  import com.eviware.soapui.settings.UISettings;
54  import com.eviware.soapui.support.DocumentListenerAdapter;
55  import com.eviware.soapui.support.StringUtils;
56  import com.eviware.soapui.support.UISupport;
57  import com.eviware.soapui.support.action.swing.SwingActionDelegate;
58  import com.eviware.soapui.support.components.GroovyEditorComponent;
59  import com.eviware.soapui.support.components.GroovyEditorInspector;
60  import com.eviware.soapui.support.components.JComponentInspector;
61  import com.eviware.soapui.support.components.JFocusableComponentInspector;
62  import com.eviware.soapui.support.components.JInspectorPanel;
63  import com.eviware.soapui.support.components.JInspectorPanelFactory;
64  import com.eviware.soapui.support.components.JUndoableTextArea;
65  import com.eviware.soapui.support.components.JXToolBar;
66  import com.eviware.soapui.support.types.StringToObjectMap;
67  import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
68  
69  /***
70   * DesktopPanel for WsdlTestSuite
71   * 
72   * @author Ole.Matzura
73   */
74  
75  @SuppressWarnings( "serial" )
76  public class WsdlTestSuiteDesktopPanel extends ModelItemDesktopPanel<WsdlTestSuite>
77  {
78  	private JProgressBar progressBar;
79  	private JTestSuiteTestCaseList testCaseList;
80  	private RunAction runAction = new RunAction();
81  	private CancelAction cancelAction = new CancelAction();
82  	private JToggleButton sequentialButton;
83  	private JToggleButton parallellButton;
84  	private final InternalTestSuiteListener testSuiteListener = new InternalTestSuiteListener();
85  	private final InternalTestSuiteRunListener testSuiteRunListener = new InternalTestSuiteRunListener();
86  	private JTextArea descriptionArea;
87  	private PropertyHolderTable propertiesTable;
88  	private JTestRunLog testRunLog;
89  	private GroovyEditorComponent tearDownGroovyEditor;
90  	private GroovyEditorComponent setupGroovyEditor;
91  	private JInspectorPanel testCaseListInspectorPanel;
92  	private JInspectorPanel inspectorPanel;
93  	private WsdlTestSuiteRunner testSuiteRunner;
94  
95  	public WsdlTestSuiteDesktopPanel( WsdlTestSuite testSuite )
96  	{
97  		super( testSuite );
98  
99  		buildUI();
100 		testSuite.addTestSuiteListener( testSuiteListener );
101 		testSuite.addTestSuiteRunListener( testSuiteRunListener );
102 	}
103 
104 	private void buildUI()
105 	{
106 		add( buildToolbar(), BorderLayout.NORTH );
107 		add( buildContent(), BorderLayout.CENTER );
108 
109 		setPreferredSize( new Dimension( 500, 500 ) );
110 	}
111 
112 	private JComponent buildContent()
113 	{
114 		inspectorPanel = JInspectorPanelFactory.build( buildTabs() );
115 		inspectorPanel.addInspector( new JComponentInspector<JComponent>( buildRunLog(), "TestSuite Log",
116 				"Log of executed TestCases and TestSteps", true ) );
117 
118 		if( StringUtils.hasContent( getModelItem().getDescription() )
119 				&& getModelItem().getSettings().getBoolean( UISettings.SHOW_DESCRIPTIONS ) )
120 		{
121 			testCaseListInspectorPanel.setCurrentInspector( "Description" );
122 		}
123 
124 		return inspectorPanel.getComponent();
125 	}
126 
127 	private JComponent buildRunLog()
128 	{
129 		testRunLog = new JTestRunLog( getModelItem().getSettings() );
130 		return testRunLog;
131 	}
132 
133 	protected JTestSuiteTestCaseList getTestCaseList()
134 	{
135 		return testCaseList;
136 	}
137 
138 	@Override
139 	public void addNotify()
140 	{
141 		super.addNotify();
142 		getModelItem().addTestSuiteListener( testSuiteListener );
143 	}
144 
145 	@Override
146 	public void removeNotify()
147 	{
148 		super.removeNotify();
149 		getModelItem().removeTestSuiteListener( testSuiteListener );
150 	}
151 
152 	private JComponent buildToolbar()
153 	{
154 		cancelAction.setEnabled( false );
155 		runAction.setEnabled( getModelItem().getTestCaseCount() > 0 );
156 
157 		JXToolBar toolbar = UISupport.createToolbar();
158 
159 		addToolbarActions( toolbar );
160 		toolbar.addGlue();
161 		toolbar.add( UISupport.createToolbarButton( new ShowOnlineHelpAction( HelpUrls.TESTSUITE_HELP_URL ) ) );
162 
163 		progressBar = new JProgressBar( 0, getModelItem().getTestCaseCount() );
164 		JPanel progressPanel = UISupport.createProgressBarPanel( progressBar, 10, false );
165 
166 		JPanel panel = new JPanel( new BorderLayout() );
167 
168 		panel.add( toolbar, BorderLayout.PAGE_START );
169 		panel.add( progressPanel, BorderLayout.CENTER );
170 
171 		return panel;
172 	}
173 
174 	protected void addToolbarActions( JXToolBar toolbar )
175 	{
176 		toolbar.add( UISupport.createToolbarButton( runAction ) );
177 		toolbar.add( UISupport.createToolbarButton( cancelAction ) );
178 
179 		toolbar.addRelatedGap();
180 
181 		ButtonGroup buttonGroup = new ButtonGroup();
182 
183 		sequentialButton = new JToggleButton( UISupport.createImageIcon( "/sequential.gif" ), true );
184 		sequentialButton.setToolTipText( "The selected TestCases are run in sequence" );
185 		sequentialButton.setPreferredSize( UISupport.getPreferredButtonSize() );
186 		sequentialButton.setSelected( getModelItem().getRunType() == TestSuiteRunType.SEQUENTIAL );
187 		sequentialButton.addActionListener( new ActionListener()
188 		{
189 
190 			public void actionPerformed( ActionEvent e )
191 			{
192 				getModelItem().setRunType( TestSuiteRunType.SEQUENTIAL );
193 			}
194 		} );
195 
196 		buttonGroup.add( sequentialButton );
197 
198 		parallellButton = new JToggleButton( UISupport.createImageIcon( "/parallell.gif" ) );
199 		parallellButton.setToolTipText( "The selected TestCases are run in parallel" );
200 		parallellButton.setPreferredSize( UISupport.getPreferredButtonSize() );
201 		parallellButton.setSelected( getModelItem().getRunType() == TestSuiteRunType.PARALLEL );
202 		parallellButton.addActionListener( new ActionListener()
203 		{
204 
205 			public void actionPerformed( ActionEvent e )
206 			{
207 				getModelItem().setRunType( TestSuiteRunType.PARALLEL );
208 			}
209 		} );
210 
211 		buttonGroup.add( parallellButton );
212 
213 		toolbar.addUnrelatedGap();
214 		toolbar.add( sequentialButton );
215 		toolbar.addRelatedGap();
216 		toolbar.add( parallellButton );
217 	}
218 
219 	private JComponent buildTabs()
220 	{
221 		JTabbedPane tabs = new JTabbedPane( JTabbedPane.TOP );
222 		testCaseListInspectorPanel = JInspectorPanelFactory.build( buildTestCaseList( getModelItem() ) );
223 
224 		tabs.addTab( "TestCases", testCaseListInspectorPanel.getComponent() );
225 
226 		addTabs( tabs, testCaseListInspectorPanel );
227 		tabs.setTabLayoutPolicy( JTabbedPane.SCROLL_TAB_LAYOUT );
228 
229 		return UISupport.createTabPanel( tabs, true );
230 	}
231 
232 	protected void addTabs( JTabbedPane tabs, JInspectorPanel inspectorPanel )
233 	{
234 		inspectorPanel.addInspector( new JFocusableComponentInspector<JPanel>( buildDescriptionPanel(), descriptionArea,
235 				"Description", "Description for this TestSuite", true ) );
236 		inspectorPanel.addInspector( new JComponentInspector<JComponent>( buildPropertiesPanel(), "Properties",
237 				"TestSuite level properties", true ) );
238 		inspectorPanel.addInspector( new GroovyEditorInspector( buildSetupScriptPanel(), "Setup Script",
239 				"Script to run before running TestSuite" ) );
240 		inspectorPanel.addInspector( new GroovyEditorInspector( buildTearDownScriptPanel(), "TearDown Script",
241 				"Script to run after running TestSuite" ) );
242 	}
243 
244 	protected GroovyEditorComponent buildTearDownScriptPanel()
245 	{
246 		tearDownGroovyEditor = new GroovyEditorComponent( new TearDownScriptGroovyEditorModel(), null );
247 		return tearDownGroovyEditor;
248 	}
249 
250 	protected GroovyEditorComponent buildSetupScriptPanel()
251 	{
252 		setupGroovyEditor = new GroovyEditorComponent( new SetupScriptGroovyEditorModel(), null );
253 		return setupGroovyEditor;
254 	}
255 
256 	private JComponent buildPropertiesPanel()
257 	{
258 		JPanel panel = new JPanel( new BorderLayout() );
259 		propertiesTable = createPropertyHolderTable();
260 		panel.add( new JScrollPane( propertiesTable ), BorderLayout.CENTER );
261 		return panel;
262 	}
263 
264 	protected PropertyHolderTable createPropertyHolderTable()
265 	{
266 		return new PropertyHolderTable( getModelItem() );
267 	}
268 
269 	private JPanel buildDescriptionPanel()
270 	{
271 		JPanel panel = new JPanel( new BorderLayout() );
272 		descriptionArea = new JUndoableTextArea( getModelItem().getDescription() );
273 		descriptionArea.getDocument().addDocumentListener( new DocumentListenerAdapter()
274 		{
275 			public void update( Document document )
276 			{
277 				getModelItem().setDescription( descriptionArea.getText() );
278 			}
279 		} );
280 
281 		panel.setBorder( BorderFactory.createEmptyBorder( 2, 2, 2, 2 ) );
282 		panel.add( new JScrollPane( descriptionArea ), BorderLayout.CENTER );
283 		UISupport.addTitledBorder( panel, "TestSuite Description" );
284 
285 		return panel;
286 	}
287 
288 	protected JComponent buildTestCaseList( WsdlTestSuite testSuite )
289 	{
290 		testCaseList = new JTestSuiteTestCaseList( testSuite );
291 
292 		JPanel p = new JPanel( new BorderLayout() );
293 
294 		p.add( buildTestCaseListToolbar(), BorderLayout.NORTH );
295 		p.add( new JScrollPane( testCaseList ), BorderLayout.CENTER );
296 
297 		return p;
298 	}
299 
300 	private Component buildTestCaseListToolbar()
301 	{
302 		JXToolBar toolbar = UISupport.createToolbar();
303 		toolbar.add( UISupport.createToolbarButton( SwingActionDelegate.createDelegate(
304 				AddNewTestCaseAction.SOAPUI_ACTION_ID, getModelItem(), null, "/testCase.gif" ) ) );
305 		toolbar.addGlue();
306 		toolbar.add( UISupport.createToolbarButton( new ShowOnlineHelpAction( HelpUrls.TESTSUITEEDITOR_HELP_URL ) ) );
307 		return toolbar;
308 	}
309 
310 	public boolean onClose( boolean canCancel )
311 	{
312 		propertiesTable.release();
313 		inspectorPanel.release();
314 		testCaseListInspectorPanel.release();
315 
316 		setupGroovyEditor.getEditor().release();
317 		tearDownGroovyEditor.getEditor().release();
318 
319 		testRunLog.release();
320 
321 		return super.release();
322 	}
323 
324 	public JComponent getComponent()
325 	{
326 		return this;
327 	}
328 
329 	public boolean dependsOn( ModelItem modelItem )
330 	{
331 		return modelItem == getModelItem() || modelItem == getModelItem().getProject();
332 	}
333 
334 	protected void runTestSuite()
335 	{
336 		testSuiteRunner = getModelItem().run( new StringToObjectMap(), true );
337 
338 		// new Thread( testSuiteRunner, getModelItem().getName() +
339 		// " TestSuiteRunner" ).start();
340 	}
341 
342 	protected void beforeRun()
343 	{
344 		runAction.setEnabled( false );
345 		cancelAction.setEnabled( testSuiteRunner != null );
346 		testCaseList.setEnabled( false );
347 		progressBar.setForeground( Color.GREEN.darker() );
348 	}
349 
350 	protected void afterRun( WsdlTestSuiteRunner testSuiteRunner )
351 	{
352 		runAction.setEnabled( true );
353 		cancelAction.setEnabled( false );
354 		testCaseList.setEnabled( true );
355 
356 		progressBar.setString( String.valueOf( testSuiteRunner.getStatus() ) );
357 		progressBar.setForeground( testSuiteRunner.isFailed() ? Color.RED : Color.GREEN.darker() );
358 	}
359 
360 	private final class InternalTestSuiteListener extends TestSuiteListenerAdapter
361 	{
362 		public void testCaseAdded( TestCase testCase )
363 		{
364 			runAction.setEnabled( getModelItem().getTestCaseCount() > 0 );
365 		}
366 
367 		public void testCaseRemoved( TestCase testCase )
368 		{
369 			runAction.setEnabled( getModelItem().getTestCaseCount() > 0 );
370 		}
371 	}
372 
373 	private class RunAction extends AbstractAction
374 	{
375 		public RunAction()
376 		{
377 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run_testcase.gif" ) );
378 			putValue( Action.SHORT_DESCRIPTION, "Runs the selected TestCases" );
379 		}
380 
381 		public void actionPerformed( ActionEvent e )
382 		{
383 			runTestSuite();
384 		}
385 	}
386 
387 	private class CancelAction extends AbstractAction
388 	{
389 		public CancelAction()
390 		{
391 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/stop_testcase.gif" ) );
392 			putValue( Action.SHORT_DESCRIPTION, "Cancels ongoing TestCase runs" );
393 		}
394 
395 		public void actionPerformed( ActionEvent e )
396 		{
397 			testSuiteRunner.cancel( "Cancelled from UI" );
398 		}
399 	}
400 
401 	private class SetupScriptGroovyEditorModel extends AbstractGroovyEditorModel
402 	{
403 		public SetupScriptGroovyEditorModel()
404 		{
405 			super( new String[] { "log", "runner", "context", "testSuite" }, WsdlTestSuiteDesktopPanel.this.getModelItem(), "Setup" );
406 		}
407 
408 		public String getScript()
409 		{
410 			return  WsdlTestSuiteDesktopPanel.this.getModelItem().getSetupScript();
411 		}
412 
413 		public void setScript( String text )
414 		{
415 			 WsdlTestSuiteDesktopPanel.this.getModelItem().setSetupScript( text );
416 		}
417 
418 		@Override
419 		public Action createRunAction()
420 		{
421 			return new AbstractAction()
422 			{
423 
424 				public void actionPerformed( ActionEvent e )
425 				{
426 					try
427 					{
428 						MockTestSuiteRunner mockRunner = new MockTestSuiteRunner(  WsdlTestSuiteDesktopPanel.this.getModelItem() );
429 						 WsdlTestSuiteDesktopPanel.this.getModelItem().runSetupScript( ( TestSuiteRunContext )mockRunner.getRunContext(), mockRunner );
430 					}
431 					catch( Exception e1 )
432 					{
433 						UISupport.showErrorMessage( e1 );
434 					}
435 				}
436 			};
437 		}
438 	}
439 
440 	private class TearDownScriptGroovyEditorModel extends AbstractGroovyEditorModel
441 	{
442 		public TearDownScriptGroovyEditorModel()
443 		{
444 			super( new String[] { "log", "runner", "context", "testSuite" },  WsdlTestSuiteDesktopPanel.this.getModelItem(), "TearDown" );
445 		}
446 
447 		public String getScript()
448 		{
449 			return  WsdlTestSuiteDesktopPanel.this.getModelItem().getTearDownScript();
450 		}
451 
452 		public void setScript( String text )
453 		{
454 			 WsdlTestSuiteDesktopPanel.this.getModelItem().setTearDownScript( text );
455 		}
456 
457 		@Override
458 		public Action createRunAction()
459 		{
460 			return new AbstractAction()
461 			{
462 
463 				public void actionPerformed( ActionEvent e )
464 				{
465 					try
466 					{
467 						MockTestSuiteRunner mockRunner = new MockTestSuiteRunner(  WsdlTestSuiteDesktopPanel.this.getModelItem() );
468 						 WsdlTestSuiteDesktopPanel.this.getModelItem().runTearDownScript( ( TestSuiteRunContext )mockRunner.getRunContext(), mockRunner );
469 					}
470 					catch( Exception e1 )
471 					{
472 						UISupport.showErrorMessage( e1 );
473 					}
474 				}
475 			};
476 		}
477 	}
478 
479 	private class InternalTestSuiteRunListener implements TestSuiteRunListener
480 	{
481 		private TestRunLogTestRunListener runLogListener;
482 		private int finishCount;
483 
484 		public void afterRun( TestSuiteRunner testRunner, TestSuiteRunContext runContext )
485 		{
486 			WsdlTestSuiteDesktopPanel.this.afterRun( ( WsdlTestSuiteRunner )testRunner );
487 		}
488 
489 		public void afterTestCase( TestSuiteRunner testRunner, TestSuiteRunContext runContext,
490 				TestCaseRunner testCaseRunner )
491 		{
492 			progressBar.setValue( ++finishCount );
493 
494 			if( getModelItem().getRunType() == TestSuiteRunType.SEQUENTIAL )
495 				testCaseRunner.getTestCase().removeTestRunListener( runLogListener );
496 		}
497 
498 		public void beforeRun( TestSuiteRunner testRunner, TestSuiteRunContext runContext )
499 		{
500 			WsdlTestSuiteDesktopPanel.this.beforeRun();
501 
502 			testCaseList.reset();
503 
504 			progressBar.setMaximum( getModelItem().getTestCaseCount() );
505 			progressBar.setValue( 0 );
506 			progressBar.setString( "" );
507 			finishCount = 0;
508 
509 			if( runLogListener == null )
510 				runLogListener = new TestRunLogTestRunListener( testRunLog, false );
511 
512 			testRunLog.clear();
513 
514 			if( getModelItem().getRunType() == TestSuiteRunType.PARALLEL )
515 				testRunLog.addText( "<log disabled during parallell execution>" );
516 		}
517 
518 		public void beforeTestCase( TestSuiteRunner testRunner, TestSuiteRunContext runContext, TestCase testCase )
519 		{
520 			if( getModelItem().getRunType() == TestSuiteRunType.SEQUENTIAL )
521 			{
522 				progressBar.setString( "Running " + testCase.getName() );
523 				testCase.addTestRunListener( runLogListener );
524 			}
525 			else
526 			{
527 				progressBar.setString( "Starting " + testCase.getName() );
528 			}
529 		}
530 	}
531 }