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.testcase;
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.text.SimpleDateFormat;
20  import java.util.Date;
21  
22  import javax.swing.AbstractAction;
23  import javax.swing.Action;
24  import javax.swing.BorderFactory;
25  import javax.swing.Box;
26  import javax.swing.JButton;
27  import javax.swing.JLabel;
28  import javax.swing.JPanel;
29  import javax.swing.JProgressBar;
30  import javax.swing.JScrollPane;
31  import javax.swing.JSplitPane;
32  import javax.swing.JTabbedPane;
33  import javax.swing.JTextArea;
34  import javax.swing.JToggleButton;
35  import javax.swing.JToolBar;
36  import javax.swing.SwingUtilities;
37  import javax.swing.text.Document;
38  
39  import com.eviware.soapui.SoapUI;
40  import com.eviware.soapui.impl.wsdl.actions.support.ShowOnlineHelpAction;
41  import com.eviware.soapui.impl.wsdl.actions.testcase.TestCaseOptionsAction;
42  import com.eviware.soapui.impl.wsdl.panels.support.ProgressBarAdapter;
43  import com.eviware.soapui.impl.wsdl.panels.testcase.actions.SetCredentialsAction;
44  import com.eviware.soapui.impl.wsdl.panels.testcase.actions.SetEndpointAction;
45  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
46  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
47  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCaseRunner;
48  import com.eviware.soapui.model.ModelItem;
49  import com.eviware.soapui.model.support.PropertiesMap;
50  import com.eviware.soapui.model.support.TestRunListenerAdapter;
51  import com.eviware.soapui.model.testsuite.LoadTestRunner;
52  import com.eviware.soapui.model.testsuite.TestRunContext;
53  import com.eviware.soapui.model.testsuite.TestRunner;
54  import com.eviware.soapui.model.testsuite.TestStep;
55  import com.eviware.soapui.model.testsuite.TestStepResult;
56  import com.eviware.soapui.monitor.support.TestMonitorListenerAdapter;
57  import com.eviware.soapui.support.DocumentListenerAdapter;
58  import com.eviware.soapui.support.UISupport;
59  import com.eviware.soapui.support.action.swing.SwingActionDelegate;
60  import com.eviware.soapui.support.components.JUndoableTextArea;
61  import com.eviware.soapui.support.swing.ComponentBag;
62  import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
63  
64  /***
65   * WsdlTestCase desktop panel
66   * 
67   * @author Ole.Matzura
68   */
69  
70  public class WsdlTestCaseDesktopPanel extends ModelItemDesktopPanel<WsdlTestCase>
71  {
72  	private JProgressBar progressBar;
73  	private TestStepList testStepList;
74  	private InternalTestRunListener testRunListener = new InternalTestRunListener();
75  	private JButton runButton;
76  	private JButton cancelButton;
77  	private TestRunner runner;
78  	private JButton setEndpointButton;
79  	private JButton setCredentialsButton;
80  	private JButton optionsButton;
81  	private ComponentBag stateDependantComponents = new ComponentBag();
82  	private TestCaseLog testCaseLog;
83  	private JToggleButton loopButton;
84  	@SuppressWarnings( "unused" )
85  	private ProgressBarAdapter progressBarAdapter;
86  	private InternalTestMonitorListener testMonitorListener;
87  	public boolean canceled;
88  	private JTextArea descriptionArea;
89  
90  	public WsdlTestCaseDesktopPanel( WsdlTestCase testCase )
91  	{
92  		super( testCase );
93  
94  		buildUI();
95  
96  		setPreferredSize( new Dimension( 250, 500 ) );
97  		setRunningState();
98  
99  		testCase.addTestRunListener( testRunListener );
100 		progressBarAdapter = new ProgressBarAdapter( progressBar, testCase );
101 		testMonitorListener = new InternalTestMonitorListener();
102 
103 		SoapUI.getTestMonitor().addTestMonitorListener( testMonitorListener );
104 	}
105 
106 	/***
107 	 * There are three states: - enabled, no testcases or testschedules running -
108 	 * enabled, standalone testcase running - disabled, testschedule is running
109 	 */
110 
111 	private void setRunningState()
112 	{
113 		stateDependantComponents.setEnabled( !SoapUI.getTestMonitor().hasRunningLoadTest( getModelItem() ) );
114 	}
115 
116 	private void buildUI()
117 	{
118 		JPanel panel = new JPanel( new BorderLayout() );
119 
120 		panel.add( buildToolbar(), BorderLayout.PAGE_START );
121 		panel.add( buildRunnerBar(), BorderLayout.CENTER );
122 
123 		add( panel, BorderLayout.NORTH );
124 
125 		JSplitPane splitPane = UISupport.createVerticalSplit();
126 		splitPane.setTopComponent( buildTestStepList() );
127 		splitPane.setBottomComponent( buildTestLog() );
128 		splitPane.setDividerLocation( 0.7 );
129 		splitPane.setDividerLocation( 250 );
130 
131 		add( splitPane, BorderLayout.CENTER );
132 		add( new JLabel( "--" ), BorderLayout.PAGE_END );
133 	}
134 
135 	protected TestStepList getTestStepList()
136 	{
137 		return testStepList;
138 	}
139 
140 	private Component buildTestLog()
141 	{
142 		testCaseLog = new TestCaseLog();
143 		stateDependantComponents.add( testCaseLog );
144 		return testCaseLog;
145 	}
146 
147 	private Component buildTestStepList()
148 	{
149 		testStepList = new TestStepList( getModelItem() );
150 		stateDependantComponents.add( testStepList );
151 
152 		JTabbedPane tabs = new JTabbedPane( JTabbedPane.TOP );
153 		tabs.addTab( "Test Steps", new JScrollPane( testStepList ) );
154 		tabs.addTab( "Description", buildDescriptionPanel() );
155 
156 		// tabs.addTab( "Test Properties", new JPanel() );
157 
158 		return UISupport.createTabPanel( tabs, false );
159 	}
160 
161 	private Component buildDescriptionPanel()
162 	{
163 		JPanel panel = new JPanel( new BorderLayout() );
164 		descriptionArea = new JUndoableTextArea( getModelItem().getDescription() );
165 		descriptionArea.getDocument().addDocumentListener( new DocumentListenerAdapter()
166 		{
167 			public void update( Document document )
168 			{
169 				getModelItem().setDescription( descriptionArea.getText() );
170 			}
171 		} );
172 
173 		panel.setBorder( BorderFactory.createEmptyBorder( 2, 2, 2, 2 ) );
174 		panel.add( new JScrollPane( descriptionArea ), BorderLayout.CENTER );
175 
176 		return panel;
177 	}
178 
179 	private Component buildToolbar()
180 	{
181 		JToolBar toolbar = UISupport.createToolbar();
182 
183 		runButton = UISupport.createToolbarButton( new RunTestCaseAction() );
184 		optionsButton = UISupport.createToolbarButton( SwingActionDelegate.createDelegate(
185 					TestCaseOptionsAction.SOAPUI_ACTION_ID, getModelItem(), null, "/options.gif" ) );
186 		optionsButton.setText( null );
187 		cancelButton = UISupport.createToolbarButton( new CancelRunTestCaseAction(), false );
188 
189 		loopButton = new JToggleButton( UISupport.createImageIcon( "/loop.gif" ) );
190 		loopButton.setPreferredSize( UISupport.getPreferredButtonSize() );
191 		loopButton.setToolTipText( "Loop TestCase continuously" );
192 
193 		setCredentialsButton = UISupport.createToolbarButton( new SetCredentialsAction( getModelItem() ) );
194 		setEndpointButton = UISupport.createToolbarButton( new SetEndpointAction( getModelItem() ) );
195 
196 		stateDependantComponents.add( runButton );
197 		stateDependantComponents.add( optionsButton );
198 		stateDependantComponents.add( cancelButton );
199 		stateDependantComponents.add( setCredentialsButton );
200 		stateDependantComponents.add( setEndpointButton );
201 
202 		addToolbarActions( toolbar );
203 		
204 		toolbar.add( Box.createHorizontalGlue() );
205 		toolbar.add( UISupport.createToolbarButton( new ShowOnlineHelpAction( HelpUrls.TESTCASEEDITOR_HELP_URL ) ) );
206 
207 		return toolbar;
208 	}
209 
210 	protected void addToolbarActions( JToolBar toolbar )
211 	{
212 		toolbar.add( runButton );
213 		toolbar.add( cancelButton );
214 		toolbar.add( loopButton );
215 		toolbar.add( setCredentialsButton );
216 		toolbar.add( setEndpointButton );
217 		toolbar.add( optionsButton );
218 	}
219 
220 	private Component buildRunnerBar()
221 	{
222 		progressBar = new JProgressBar( 0, getModelItem().getTestStepCount() );
223 		return UISupport.createProgressBarPanel( progressBar, 10, false );
224 	}
225 
226 	private final class InternalTestMonitorListener extends TestMonitorListenerAdapter
227 	{
228 		public void loadTestStarted( LoadTestRunner runner )
229 		{
230 			setRunningState();
231 		}
232 
233 		public void loadTestFinished( LoadTestRunner runner )
234 		{
235 			setRunningState();
236 		}
237 	}
238 
239 	public class InternalTestRunListener extends TestRunListenerAdapter
240 	{
241 		private SimpleDateFormat dateFormat;
242 
243 		public InternalTestRunListener()
244 		{
245 			dateFormat = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss.SSS" );
246 		}
247 
248 		public void beforeRun( TestRunner testRunner, TestRunContext runContext )
249 		{
250 			if( SoapUI.getTestMonitor().hasRunningLoadTest( getModelItem() ) )
251 				return;
252 
253 			runButton.setEnabled( false );
254 			cancelButton.setEnabled( true );
255 			testStepList.setEnabled( false );
256 			testStepList.setSelectedIndex( -1 );
257 			testCaseLog.clear();
258 
259 			testCaseLog.addText( "Test started at " + dateFormat.format( new Date() ) );
260 		}
261 
262 		public void beforeStep( TestRunner testRunner, TestRunContext runContext )
263 		{
264 			if( SoapUI.getTestMonitor().hasRunningLoadTest( getModelItem() ) )
265 				return;
266 
267 			TestStep testStep = runContext.getCurrentStep();
268 			testStepList.setSelectedValue( testStep, true );
269 		}
270 
271 		public void afterRun( TestRunner testRunner, TestRunContext runContext )
272 		{
273 			if( SoapUI.getTestMonitor().hasRunningLoadTest( getModelItem() ) )
274 				return;
275 
276 			WsdlTestCaseRunner wsdlRunner = ( WsdlTestCaseRunner ) testRunner;
277 
278 			if( testRunner.getStatus() == TestRunner.Status.CANCELED )
279 				testCaseLog.addText( "Test canceled [" + testRunner.getReason() + "], time taken = "
280 							+ wsdlRunner.getTimeTaken() );
281 			else if( testRunner.getStatus() == TestRunner.Status.FAILED )
282 				testCaseLog.addText( "Test failed [" + wsdlRunner.getError() + "], time taken = "
283 							+ wsdlRunner.getTimeTaken() );
284 			else 
285 				testCaseLog.addText( "Test finished with status [" + testRunner.getStatus() + "], time taken = " + wsdlRunner.getTimeTaken() );
286 
287 			runner = null;
288 
289 			JToggleButton loopButton = ( JToggleButton ) runContext.getProperty( "loopButton" );
290 			if( loopButton != null && loopButton.isSelected() && testRunner.getStatus() == TestRunner.Status.FINISHED )
291 			{
292 				SwingUtilities.invokeLater( new Runnable()
293 				{
294 					public void run()
295 					{
296 						runTestCase();
297 					}
298 				} );
299 			}
300 			else
301 			{
302 				WsdlTestCaseDesktopPanel.this.afterRun();
303 			}
304 		}
305 
306 		public void afterStep( TestRunner testRunner, TestRunContext runContext, TestStepResult stepResult )
307 		{
308 			if( SoapUI.getTestMonitor().hasRunningLoadTest( getModelItem() ) )
309 				return;
310 
311 			testCaseLog.addTestStepResult( stepResult );
312 		}
313 	}
314 
315 	protected void runTestCase()
316 	{
317 		if( canceled )
318 		{
319 			// make sure state is correct
320 			runButton.setEnabled( true );
321 			cancelButton.setEnabled( false );
322 			testStepList.setEnabled( true );
323 			return;
324 		}
325 
326 		PropertiesMap properties = new PropertiesMap();
327 		properties.put( "loopButton", loopButton );
328 		runner = getModelItem().run( properties, true );
329 	}
330 
331 	public class RunTestCaseAction extends AbstractAction
332 	{
333 		public RunTestCaseAction()
334 		{
335 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run_testcase.gif" ) );
336 			putValue( Action.SHORT_DESCRIPTION, "Runs this testcase" );
337 		}
338 
339 		public void actionPerformed( ActionEvent e )
340 		{
341 			canceled = false;
342 			runTestCase();
343 		}
344 	}
345 
346 	public class CancelRunTestCaseAction extends AbstractAction
347 	{
348 		public CancelRunTestCaseAction()
349 		{
350 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/stop_testcase.gif" ) );
351 			putValue( Action.SHORT_DESCRIPTION, "Stops running this testcase" );
352 		}
353 
354 		public void actionPerformed( ActionEvent e )
355 		{
356 			if( runner != null )
357 				runner.cancel( "canceled in UI" );
358 
359 			canceled = true;
360 		}
361 	}
362 
363 	public boolean onClose( boolean canCancel )
364 	{
365 		if( canCancel )
366 		{
367 			if( runner != null && runner.getStatus() == TestRunner.Status.RUNNING )
368 			{
369 				Boolean retval = UISupport.confirmOrCancel( "Cancel running TestCase?", "Cancel Run" );
370 
371 				if( retval == null )
372 					return false;
373 				if( retval.booleanValue() )
374 				{
375 					runner.cancel( null );
376 				}
377 			}
378 		}
379 		else
380 		{
381 			if( runner != null && runner.getStatus() == TestRunner.Status.RUNNING )
382 			{
383 				runner.cancel( null );
384 			}
385 		}
386 
387 		SoapUI.getTestMonitor().removeTestMonitorListener( testMonitorListener );
388 		getModelItem().removeTestRunListener( testRunListener );
389 		testStepList.release();
390 		progressBarAdapter.release();
391 		
392 		return release();
393 	}
394 
395 	public boolean dependsOn( ModelItem modelItem )
396 	{
397 		return modelItem == getModelItem() || modelItem == getModelItem().getTestSuite()
398 					|| modelItem == getModelItem().getTestSuite().getProject();
399 	}
400 
401 	public String getDescription()
402 	{
403 		return "TestCase: [" + getModelItem().getName() + "]";
404 	}
405 
406 	protected void afterRun()
407 	{
408 		runButton.setEnabled( true );
409 		cancelButton.setEnabled( false );
410 		testStepList.setEnabled( true );
411 	}
412 }