View Javadoc

1   /*
2    *  soapui, copyright (C) 2005 Ole Matzura / eviware.com 
3    *
4    *  SoapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of the GNU Lesser General Public License as published by the Free Software Foundation; 
6    *  either version 2.1 of the License, or (at your option) any later version.
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.awt.event.MouseAdapter;
20  import java.awt.event.MouseEvent;
21  import java.beans.PropertyChangeEvent;
22  import java.beans.PropertyChangeListener;
23  import java.text.SimpleDateFormat;
24  import java.util.ArrayList;
25  import java.util.Arrays;
26  import java.util.Date;
27  import java.util.HashSet;
28  import java.util.List;
29  import java.util.Set;
30  
31  import javax.swing.AbstractAction;
32  import javax.swing.AbstractListModel;
33  import javax.swing.Action;
34  import javax.swing.BorderFactory;
35  import javax.swing.JButton;
36  import javax.swing.JComponent;
37  import javax.swing.JInternalFrame;
38  import javax.swing.JLabel;
39  import javax.swing.JList;
40  import javax.swing.JMenu;
41  import javax.swing.JOptionPane;
42  import javax.swing.JPanel;
43  import javax.swing.JPopupMenu;
44  import javax.swing.JProgressBar;
45  import javax.swing.JScrollPane;
46  import javax.swing.JSplitPane;
47  import javax.swing.JTabbedPane;
48  import javax.swing.ListCellRenderer;
49  import javax.swing.ListSelectionModel;
50  import javax.swing.event.PopupMenuEvent;
51  import javax.swing.event.PopupMenuListener;
52  
53  import com.eviware.soapui.SoapUI;
54  import com.eviware.soapui.impl.wsdl.WsdlTestCase;
55  import com.eviware.soapui.impl.wsdl.WsdlTestStep;
56  import com.eviware.soapui.impl.wsdl.teststeps.WsdlAssertion;
57  import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequest;
58  import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep;
59  import com.eviware.soapui.model.DesktopPanel;
60  import com.eviware.soapui.model.ModelItem;
61  import com.eviware.soapui.model.support.TestRunListenerAdapter;
62  import com.eviware.soapui.model.support.TestSuiteListenerAdapter;
63  import com.eviware.soapui.model.testsuite.TestRunner;
64  import com.eviware.soapui.model.testsuite.TestStep;
65  import com.eviware.soapui.support.UISupport;
66  import com.jgoodies.forms.builder.ButtonBarBuilder;
67  
68  /***
69   * WsdlTestCase desktop panel
70   * 
71   * @author Ole.Matzura
72   */
73  
74  public class WsdlTestCaseDesktopPanel extends JPanel implements DesktopPanel
75  {
76  	private JTabbedPane tabbedPane;
77     private final WsdlTestCase testCase;
78     private JProgressBar progressBar;
79     private TestStepListModel testStepListModel;
80     private JList testStepList;
81     private JList testLogList;
82     private LogListModel logListModel;
83     private InternalTestRunListener testRunListener = new InternalTestRunListener();
84  	private JButton runButton;
85  	private JPopupMenu testListPopup;
86  	private MoveStepDownAction moveStepDownAction;
87  	private MoveStepUpAction moveStepUpAction;
88  	private JButton cancelButton;
89     private TestRunner runner;
90  	private JButton setEndpointButton;
91  	private JMenu insertStepMenu;
92  
93     public WsdlTestCaseDesktopPanel(WsdlTestCase testCase)
94     {
95        super(new BorderLayout());
96        this.testCase = testCase;
97        
98        testCase.addTestRunListener( testRunListener );
99        buildUI();
100       setPreferredSize( new Dimension( 250, 500 ));
101    }
102 
103 	private void buildUI()
104    {
105 	   JPanel panel = new JPanel( new BorderLayout() );
106 	   
107       panel.add( buildToolbar(), BorderLayout.PAGE_START );
108       panel.add( buildRunnerBar(), BorderLayout.CENTER );
109       
110       add( panel, BorderLayout.NORTH );
111       
112       JSplitPane splitPane = UISupport.createVerticalSplit();
113       JScrollPane scrollPane = new JScrollPane( buildTestStepList() );
114       scrollPane.setBorder( BorderFactory.createTitledBorder( BorderFactory.createEmptyBorder(), "Test Steps"));
115 		splitPane.setTopComponent( scrollPane);
116       splitPane.setBottomComponent( buildTestLog() );
117       splitPane.setDividerLocation( 0.5 );
118       splitPane.setDividerLocation( 200 );
119 
120       add( splitPane, BorderLayout.CENTER );
121       add( new JLabel( "--"), BorderLayout.PAGE_END );
122    }
123 
124    private Component buildTestLog()
125    {
126    	logListModel = new LogListModel();
127    	testLogList = new JList( logListModel );
128    	testLogList.setCellRenderer( new TestLogCellRenderer() );
129       
130       JScrollPane scrollPane = new JScrollPane( testLogList );
131       scrollPane.setBorder( BorderFactory.createTitledBorder( BorderFactory.createEmptyBorder(), "Test Log"));
132 		return scrollPane;
133    }
134 
135    private Component buildTestStepList()
136    {
137       testStepListModel = new TestStepListModel();
138       testStepList = new JList( testStepListModel );
139       testStepList.setCellRenderer( new TestStepCellRenderer() );
140       testStepList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
141       
142       testStepList.addMouseListener( new StepListMouseListener() );
143       testListPopup = new JPopupMenu();
144       
145       testListPopup.addSeparator();
146       insertStepMenu = new JMenu( "Insert step");
147 		insertStepMenu.add( new InsertTransferValuesStepAction() );
148 
149       testListPopup.add( insertStepMenu );
150       testListPopup.addSeparator();
151       moveStepDownAction = new MoveStepDownAction();
152 		testListPopup.add( moveStepDownAction );
153       moveStepUpAction = new MoveStepUpAction();
154 		testListPopup.add( moveStepUpAction );
155       
156       testListPopup.addPopupMenuListener( new StepListPopupMenuListener(testCase));
157       testStepList.setComponentPopupMenu( testListPopup );
158       
159       return testStepList;
160    }
161 
162    private Component buildToolbar()
163    {
164    	ButtonBarBuilder builder = new ButtonBarBuilder();
165       runButton = new JButton( new RunTestCaseAction());
166       runButton.setPreferredSize( new Dimension(24, 24 ));
167       cancelButton = new JButton( new CancelRunTestCaseAction() );
168       cancelButton.setPreferredSize( new Dimension(24, 24 ));
169       cancelButton.setEnabled( false );
170       setEndpointButton = new JButton( new SetEndpointAction());
171       setEndpointButton.setPreferredSize( new Dimension(24, 24 ));
172 
173       builder.addFixed( runButton );
174       builder.addRelatedGap();
175       builder.addFixed( cancelButton );
176       builder.addGlue();
177       builder.addFixed( setEndpointButton );
178       
179       builder.setBorder( BorderFactory.createEmptyBorder( 5, 5, 5, 5 ));
180       
181       return builder.getPanel();
182    }
183 
184    private Component buildRunnerBar()
185    {
186       progressBar = new JProgressBar( 0, testCase.getTestStepCount() );
187       progressBar.setValue( 0 );
188       progressBar.setStringPainted( true );
189       progressBar.setBorder( BorderFactory.createEmptyBorder( 10, 10, 10, 10 ));
190       
191       return progressBar;
192    }
193    
194    private final class StepListPopupMenuListener implements PopupMenuListener
195 	{
196 		private StepListPopupMenuListener(WsdlTestCase case1)
197 		{
198 			super();
199 		}
200 
201 		public void popupMenuWillBecomeVisible(PopupMenuEvent e)
202 		{
203 		   while( testListPopup.getComponentCount() > 5 ) 
204 		      testListPopup.remove( 0 );
205 		   
206 		   int ix = testStepList.getSelectedIndex();
207 		   
208 		   if( ix == -1 ) 
209 		   {
210 		   	insertStepMenu.setEnabled( false );
211 		   	moveStepDownAction.setEnabled( false );
212 		   	moveStepUpAction.setEnabled( false );
213 		   	return;
214 		   }
215 		   
216 		   insertStepMenu.setEnabled( true );
217 		   moveStepUpAction.setEnabled( ix > 0 );
218 		   moveStepDownAction.setEnabled( ix > -1 && ix < testCase.getTestStepCount()-1 );
219 		   
220 		   TestStep testStep = (TestStep) testCase.getTestStepAt( ix );
221 		   Action[] actions = testStep.getActions();
222 		   
223 		   for (int i = 0; i < actions.length; i++)
224 		   {
225 		      testListPopup.insert( actions[i],i );
226 		   }
227 		}
228 
229 		public void popupMenuWillBecomeInvisible(PopupMenuEvent e)
230 		{
231 		   // TODO Auto-generated method stub
232 		   
233 		}
234 
235 		public void popupMenuCanceled(PopupMenuEvent e)
236 		{
237 		   // TODO Auto-generated method stub
238 		   
239 		}
240 	}
241 
242 	private final class StepListMouseListener extends MouseAdapter
243 	{
244 		public void mouseClicked(MouseEvent e)
245 		{
246 		   if( e.getClickCount() < 2 ) return;
247 		   ModelItem modelItem = (ModelItem) testStepList.getSelectedValue();
248 		   if( modelItem == null ) return;
249 		    
250 		   JInternalFrame frame = SoapUI.getInstance().showTab( testCase );
251 		    
252 		   JInternalFrame requestFrame = SoapUI.getInstance().showTab( modelItem );
253 		   if( requestFrame != null )
254 			{
255 				requestFrame.reshape(frame.getX() + frame.getWidth(), frame.getY(),
256 								requestFrame.getWidth(), requestFrame.getHeight());
257 			}
258 		 }
259 	}
260 
261 	private class TestStepCellRenderer extends JLabel implements ListCellRenderer 
262    {
263       public Component getListCellRendererComponent(
264         JList list,
265         Object value,           
266         int index,               
267         boolean isSelected,      
268         boolean cellHasFocus)    
269       {
270           WsdlTestStep testStep = (WsdlTestStep) value;
271              setText( testStep.getName() );
272           
273           setIcon( testStep.getIcon() );
274           
275           if (isSelected) 
276           {
277              setBackground(list.getSelectionBackground());
278              setForeground(list.getSelectionForeground());
279           }
280           else 
281           {
282              setBackground(list.getBackground());
283              setForeground(list.getForeground());
284           }
285           
286           setEnabled(list.isEnabled());
287           setFont(list.getFont());
288           setOpaque(true);
289           setBorder( BorderFactory.createEmptyBorder(3, 3, 3, 3));
290           
291           
292           return this;
293       }
294   }
295    
296    private class TestStepListModel extends AbstractListModel implements PropertyChangeListener
297    {
298       private TestStepListTestSuiteListener testStepListTestSuiteListener = new TestStepListTestSuiteListener();
299 
300 		public TestStepListModel()
301       {
302       	for( int c = 0; c < getSize(); c++ )
303       		testCase.getTestStepAt( c ).addPropertyChangeListener( this );
304       	
305 			testCase.getTestSuite().addTestSuiteListener( testStepListTestSuiteListener );
306       }
307       
308       public int getSize()
309       {
310          return testCase.getTestStepCount();
311       }
312 
313       public Object getElementAt(int index)
314       {
315          return testCase.getTestStepAt( index );
316       }
317 
318 		public void propertyChange(PropertyChangeEvent arg0)
319 		{
320 		   int ix = testCase.getIndexOfTestStep( (TestStep)arg0.getSource() );
321 		   if( ix == -1 ) return;
322 		   
323 		   fireContentsChanged( this, ix, ix );
324 		}
325 		
326 		public void release()
327 		{
328 			testCase.getTestSuite().removeTestSuiteListener( testStepListTestSuiteListener );
329 			
330 			for( int c = 0; c < getSize(); c++ )
331       		testCase.getTestStepAt( c ).removePropertyChangeListener( this );
332 		}
333 		
334 		private class TestStepListTestSuiteListener extends TestSuiteListenerAdapter
335 		{
336 			public void testStepAdded(TestStep testStep, int ix)
337 			{
338 			   testStep.addPropertyChangeListener( TestStepListModel.this );
339 			   fireIntervalAdded( TestStepListModel.this, ix, ix );
340 			}
341 
342 			public void testStepRemoved(TestStep testStep, int ix)
343 			{
344 				testStep.removePropertyChangeListener( TestStepListModel.this );
345 			   fireIntervalRemoved( TestStepListModel.this, ix, ix );
346 			}
347 		}
348    }
349 
350    public class InternalTestRunListener extends TestRunListenerAdapter 
351    {
352 		private long stepStart;
353 		private long testStartTime;
354 		private SimpleDateFormat dateFormat;
355 
356 		public InternalTestRunListener()
357 		{
358 			dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
359 		}
360 
361 		public boolean beforeRun(TestRunner testRunner) 
362 		{
363 			runButton.setEnabled( false );
364 			cancelButton.setEnabled( true );
365 			testStepList.setEnabled( false );
366 			testStepList.setSelectedIndex( -1 );
367 			progressBar.getModel().setMaximum( testRunner.getTestCase().getTestStepCount() );
368 			logListModel.clear();
369 			
370 			for( int c = 0; c < testCase.getTestStepCount(); c++ )
371 			{
372 				testCase.getTestStepAt( c ).prepare( testRunner );
373 			}				
374 			
375 			testStartTime = System.currentTimeMillis();
376 			logListModel.addText( "Test started at " + dateFormat.format( new Date( testStartTime )) );
377 			return true;
378 		}
379 
380 		public boolean beforeStep(TestRunner testRunner) 
381 		{
382 			TestStep testStep = testRunner.getCurrentStep();
383 			testStepList.setSelectedValue( testStep, true );
384 			progressBar.setString( testStep.getName() );
385 			progressBar.setValue( testRunner.getCurrentStepIndex() );
386 			
387 			stepStart = System.currentTimeMillis();
388 			return true;
389 		}
390 		
391 		public void afterRun(TestRunner testRunner) 
392 		{
393 			long endTime = System.currentTimeMillis();
394 			
395 			progressBar.setValue( testRunner.getCurrentStepIndex() );
396 		   runButton.setEnabled( true );	
397 			cancelButton.setEnabled( false );
398 			testStepList.setEnabled( true );
399 			
400 			if( testRunner.getStatus() == TestRunner.Status.CANCELED )
401 				logListModel.addText( "Test canceled, time taken = " + (endTime-testStartTime));
402 			else
403 				logListModel.addText( "Test finished, time taken = " + (endTime-testStartTime));
404 			runner = null;
405 		}
406 
407 		public boolean afterStep(TestRunner testRunner) 
408 		{
409 			TestStep testStep = testRunner.getCurrentStep();
410 			logListModel.addTestStep( "Step " + (1+testRunner.getCurrentStepIndex()) + " : " +
411 					testStep.getName() + " took " + (System.currentTimeMillis()-stepStart) + " ms", testStep );
412 			
413 			if( testStep instanceof WsdlTestRequestStep )
414 			{
415 				WsdlTestRequest testRequest = ((WsdlTestRequestStep)testStep).getTestRequest();
416 				for( int c = 0; c < testRequest.getAssertionCount(); c++ )
417 				{
418 					WsdlAssertion assertion = testRequest.getAssertionAt( c );
419 					if( assertion.getStatus() == WsdlAssertion.AssertionStatus.FAILED )
420 					{
421 						logListModel.addAssertion( assertion );
422 					}
423 				}
424 			}
425 			
426 			return true;
427 		}
428 	}
429    
430    private class LogListModel extends AbstractListModel
431    {
432    	private List<Object> items = new ArrayList<Object>();
433    	
434    	public void addText( String msg )
435    	{
436    		items.add( msg );
437    		fireIntervalAdded( this, items.size()-1, items.size() );
438    	}
439    	
440    	public void addTestStep( String msg, TestStep testStep )
441    	{
442    		items.add( new TestStepLogItem( testStep, msg ));
443    		fireIntervalAdded( this, items.size()-1, items.size() );
444    	}
445    	
446    	public void addAssertion( WsdlAssertion assertion )
447    	{
448    		int sz = items.size();
449    		items.add( assertion );
450    		items.addAll( Arrays.asList(assertion.getErrors()) );
451    		
452    		fireIntervalAdded( this, sz, items.size() );
453    	}
454    	
455    	public void clear()
456    	{
457    		int sz = getSize();
458    		items.clear();
459    		fireIntervalRemoved( this, 0, sz );
460    	}
461    	
462 		public int getSize()
463 		{
464 			return items.size();
465 		}
466 
467 		public Object getElementAt(int arg0)
468 		{
469 			return items.get( arg0 );
470 		}}
471 
472    private class TestLogCellRenderer extends JLabel implements ListCellRenderer 
473    {
474       public Component getListCellRendererComponent(
475         JList list,
476         Object value,           
477         int index,               
478         boolean isSelected,      
479         boolean cellHasFocus)    
480       {
481       	 setIcon( null );
482       	 
483           if( value instanceof String )
484           {
485          	 setText( value.toString() );
486           }
487           else if( value instanceof WsdlAssertion )
488           {
489          	 WsdlAssertion assertion = (WsdlAssertion) value;
490          	 setIcon( assertion.getIcon() );
491          	 setText( assertion.getName() + "; " + assertion.getStatus().toString() );
492           }
493           else if( value instanceof AssertionError )
494           {
495          	 setText( " -> " + ((AssertionError)value).toString() );
496           }
497           else if( value instanceof TestStepLogItem )
498           {
499          	 TestStepLogItem logItem = (TestStepLogItem) value;
500          	 setIcon( null );
501          	 setText( logItem.getMsg() );
502           }
503           
504           if (isSelected) 
505           {
506              setBackground(list.getSelectionBackground());
507              setForeground(list.getSelectionForeground());
508           }
509           else 
510           {
511              setBackground(list.getBackground());
512              setForeground(list.getForeground());
513           }
514           
515           setEnabled(list.isEnabled());
516           setFont(list.getFont());
517           setOpaque(true);
518           setBorder( BorderFactory.createEmptyBorder(3, 3, 3, 3));
519           
520           
521           return this;
522       }
523    }
524    
525    private class TestStepLogItem
526    {
527    	private final TestStep testStep;
528 		private final String msg;
529 
530 		public TestStepLogItem( TestStep testStep, String msg )
531    	{
532 			this.testStep = testStep;
533 			this.msg = msg;
534 		}
535 
536 		public String getMsg()
537 		{
538 			return msg;
539 		}
540 
541 		public TestStep getTestStep()
542 		{
543 			return testStep;
544 		}
545    }
546 
547    private class MoveStepDownAction extends AbstractAction
548    {
549    	public MoveStepDownAction()
550    	{
551    		super( "Move down" );
552    	}
553    	
554 		public void actionPerformed(ActionEvent e)
555 		{
556 			int ix = testStepList.getSelectedIndex();
557 			if( ix == -1 || ix >= testCase.getTestStepCount()-1 ) return;
558 			
559 			testCase.moveStep( ix, 1 );
560 		}
561    }
562 
563    private class MoveStepUpAction extends AbstractAction
564    {
565    	public MoveStepUpAction()
566    	{
567    		super( "Move up" );
568    	}
569 
570 		public void actionPerformed(ActionEvent e)
571 		{
572 			int ix = testStepList.getSelectedIndex();
573 			if( ix < 1 ) return;
574 			
575 			testCase.moveStep( ix, -1 );
576 		}
577    }
578    
579    public class RunTestCaseAction extends AbstractAction
580    {
581 		public RunTestCaseAction()
582       {
583          putValue( Action.SMALL_ICON, SoapUI.createImageIcon( "/run_testcase.gif"));
584          putValue( Action.SHORT_DESCRIPTION, "Runs this testcase" );
585       }
586 
587 		public void actionPerformed(ActionEvent e)
588 		{
589          runner = testCase.run();
590 		}
591    }
592 
593    public class CancelRunTestCaseAction extends AbstractAction
594    {
595 		public CancelRunTestCaseAction()
596       {
597          putValue( Action.SMALL_ICON, SoapUI.createImageIcon( "/stop_testcase.gif"));
598          putValue( Action.SHORT_DESCRIPTION, "Stops running this testcase" );
599       }
600       
601 		public void actionPerformed(ActionEvent e)
602 		{
603       	if( runner != null )
604       		runner.cancel();
605       }
606    }
607    
608    public class SetEndpointAction extends AbstractAction
609    {
610 		public SetEndpointAction()
611       {
612          putValue( Action.SMALL_ICON, SoapUI.createImageIcon( "/set_endpoint.gif"));
613          putValue( Action.SHORT_DESCRIPTION, "Sets the endpoint for all requests in this testcase" );
614       }
615       
616 		public void actionPerformed(ActionEvent e)
617 		{
618 			Set<String> endpointSet = new HashSet<String>();
619 			
620 			for( int c = 0; c < testCase.getTestStepCount(); c++ )
621 	   	{
622 	   		TestStep step = testCase.getTestStepAt( c );
623 	   		if( step instanceof WsdlTestRequestStep )
624 	   		{
625 	   			WsdlTestRequestStep requestStep = (WsdlTestRequestStep) step;
626 	   			String [] endpoints = requestStep.getTestRequest().getOperation().getInterface().getEndpoints();
627 	   			for( int i = 0; i < endpoints.length; i++ )
628 	   			{
629 	   				endpointSet.add( endpoints[i] );
630 	   			}
631 	   		}
632 	   	}
633 			
634 			String selected = (String) JOptionPane.showInputDialog( SoapUI.getInstance().getFrame(), 
635 					"Select endpoint to set for all requests", "Set endpoint", 
636 					JOptionPane.QUESTION_MESSAGE, null, endpointSet.toArray(), null );
637 			
638 			if( selected == null ) return;
639 			
640 			for( int c = 0; c < testCase.getTestStepCount(); c++ )
641       	{
642       		TestStep step = testCase.getTestStepAt( c );
643       		if( step instanceof WsdlTestRequestStep )
644       		{
645       			WsdlTestRequestStep requestStep = (WsdlTestRequestStep) step;
646       			requestStep.getTestRequest().setEndpoint( selected );
647       		}
648       	}
649       }
650    }
651 
652    public class InsertTransferValuesStepAction extends AbstractAction
653 	{
654    	public InsertTransferValuesStepAction()
655 		{
656    		super( "Transfer Reponse->Request values" );
657 		}
658    	
659 		public void actionPerformed(ActionEvent e)
660 		{
661 			int ix = testStepList.getSelectedIndex();
662 			testCase.addTransferResponseValuesStep( ix );
663 		}
664 
665 	}
666    
667    public ModelItem getModelItem()
668 	{
669 		return testCase;
670 	}
671 
672 	public boolean onClose()
673 	{
674 		if( runner != null && runner.getStatus() == TestRunner.Status.RUNNING )
675 		{
676 			int retval = JOptionPane.showConfirmDialog( UISupport.getMainFrame(), "Cancel running TestCase?", 
677 					"Cancel Run", JOptionPane.YES_NO_CANCEL_OPTION );
678 			
679 			if( retval == JOptionPane.CANCEL_OPTION) return false;
680 			if( retval == JOptionPane.YES_OPTION )
681 			{
682 				runner.cancel();
683 			}
684 		}
685 		
686       testCase.removeTestRunListener( testRunListener );
687       testStepListModel.release();
688 
689       return true;
690 	}
691 
692 	public JComponent getComponent()
693 	{
694 		return this;
695 	}
696 }