View Javadoc

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