1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.teststeps.assertions.basic;
14
15 import com.eviware.soapui.SoapUI;
16 import com.eviware.soapui.config.TestAssertionConfig;
17 import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
18 import com.eviware.soapui.impl.wsdl.WsdlInterface;
19 import com.eviware.soapui.impl.wsdl.support.HelpUrls;
20 import com.eviware.soapui.impl.wsdl.support.assertions.AssertedXPathImpl;
21 import com.eviware.soapui.impl.wsdl.support.assertions.AssertedXPathsContainer;
22 import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext;
23 import com.eviware.soapui.impl.wsdl.teststeps.WsdlMessageAssertion;
24 import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep;
25 import com.eviware.soapui.impl.wsdl.teststeps.assertions.AbstractTestAssertionFactory;
26 import com.eviware.soapui.model.TestModelItem;
27 import com.eviware.soapui.model.iface.MessageExchange;
28 import com.eviware.soapui.model.iface.SubmitContext;
29 import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
30 import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
31 import com.eviware.soapui.model.support.XPathReference;
32 import com.eviware.soapui.model.support.XPathReferenceContainer;
33 import com.eviware.soapui.model.support.XPathReferenceImpl;
34 import com.eviware.soapui.model.testsuite.*;
35 import com.eviware.soapui.model.testsuite.AssertionError;
36 import com.eviware.soapui.support.StringUtils;
37 import com.eviware.soapui.support.UISupport;
38 import com.eviware.soapui.support.components.JUndoableTextArea;
39 import com.eviware.soapui.support.components.JXToolBar;
40 import com.eviware.soapui.support.types.StringList;
41 import com.eviware.soapui.support.xml.XmlObjectConfigurationBuilder;
42 import com.eviware.soapui.support.xml.XmlObjectConfigurationReader;
43 import com.eviware.soapui.support.xml.XmlUtils;
44 import com.jgoodies.forms.builder.ButtonBarBuilder;
45 import junit.framework.ComparisonFailure;
46 import org.apache.log4j.Logger;
47 import org.apache.xmlbeans.XmlAnySimpleType;
48 import org.apache.xmlbeans.XmlCursor;
49 import org.apache.xmlbeans.XmlObject;
50 import org.apache.xmlbeans.XmlOptions;
51 import org.custommonkey.xmlunit.*;
52 import org.w3c.dom.Attr;
53 import org.w3c.dom.Element;
54 import org.w3c.dom.Node;
55
56 import javax.swing.*;
57 import java.awt.*;
58 import java.awt.event.ActionEvent;
59 import java.awt.event.WindowAdapter;
60 import java.awt.event.WindowEvent;
61 import java.util.ArrayList;
62 import java.util.List;
63
64 /***
65 * Assertion that matches a specified XPath expression and its expected result
66 * against the associated WsdlTestRequests response message
67 *
68 * @author Ole.Matzura
69 */
70
71 public class XPathContainsAssertion extends WsdlMessageAssertion implements RequestAssertion, ResponseAssertion, XPathReferenceContainer
72 {
73 private final static Logger log = Logger.getLogger( XPathContainsAssertion.class );
74 private String expectedContent;
75 private String path;
76 private JDialog configurationDialog;
77 private JTextArea pathArea;
78 private JTextArea contentArea;
79 private boolean configureResult;
80 private boolean allowWildcards;
81 private boolean ignoreNamspaceDifferences;
82
83 public static final String ID = "XPath Match";
84 public static final String LABEL = "XPath Match";
85 private JCheckBox allowWildcardsCheckBox;
86 private JCheckBox ignoreNamspaceDifferencesCheckBox;
87
88 public XPathContainsAssertion( TestAssertionConfig assertionConfig, Assertable assertable )
89 {
90 super( assertionConfig, assertable, true, true, true, true );
91
92 XmlObjectConfigurationReader reader = new XmlObjectConfigurationReader( getConfiguration() );
93 path = reader.readString( "path", null );
94 expectedContent = reader.readString( "content", null );
95 allowWildcards = reader.readBoolean( "allowWildcards", false );
96 ignoreNamspaceDifferences = reader.readBoolean( "ignoreNamspaceDifferences", false );
97 }
98
99 public String getExpectedContent()
100 {
101 return expectedContent;
102 }
103
104 public void setExpectedContent( String expectedContent )
105 {
106 this.expectedContent = expectedContent;
107 setConfiguration( createConfiguration() );
108 }
109
110 /***
111 * @deprecated
112 */
113
114 @Deprecated
115 public void setContent( String content )
116 {
117 setExpectedContent( content );
118 }
119
120 public String getPath()
121 {
122 return path;
123 }
124
125 public void setPath( String path )
126 {
127 this.path = path;
128 setConfiguration( createConfiguration() );
129 }
130
131 public boolean isAllowWildcards()
132 {
133 return allowWildcards;
134 }
135
136 public void setAllowWildcards( boolean allowWildcards )
137 {
138 this.allowWildcards = allowWildcards;
139 }
140
141 public boolean isIgnoreNamspaceDifferences()
142 {
143 return ignoreNamspaceDifferences;
144 }
145
146 public void setIgnoreNamspaceDifferences( boolean ignoreNamspaceDifferences )
147 {
148 this.ignoreNamspaceDifferences = ignoreNamspaceDifferences;
149 }
150
151 @Override
152 protected String internalAssertResponse( MessageExchange messageExchange, SubmitContext context )
153 throws AssertionException
154 {
155 if( !messageExchange.hasResponse() )
156 return "Missing Response";
157 else
158 return assertContent( messageExchange.getResponseContentAsXml(), context, "Response" );
159 }
160
161 public String assertContent( String response, SubmitContext context, String type ) throws AssertionException
162 {
163 try
164 {
165 if( path == null )
166 return "Missing path for XPath assertion";
167 if( expectedContent == null )
168 return "Missing content for XPath assertion";
169
170 XmlObject xml = XmlObject.Factory.parse( response );
171 String expandedPath = PropertyExpansionUtils.expandProperties( context, path );
172 XmlObject[] items = xml.selectPath( expandedPath );
173 AssertedXPathsContainer assertedXPathsContainer = (AssertedXPathsContainer)
174 context.getProperty( AssertedXPathsContainer.ASSERTEDXPATHSCONTAINER_PROPERTY );
175
176 XmlObject contentObj = null;
177 String expandedContent = PropertyExpansionUtils.expandProperties( context, expectedContent );
178
179
180
181 if( !expandedPath.endsWith( "text()" ) )
182 {
183 try
184 {
185 contentObj = XmlObject.Factory.parse( expandedContent );
186 }
187 catch( Exception e )
188 {
189
190
191
192 }
193 }
194
195 if( items.length == 0 )
196 throw new Exception( "Missing content for xpath [" + path + "] in " + type );
197
198 XmlOptions options = new XmlOptions();
199 options.setSavePrettyPrint();
200 options.setSaveOuter();
201
202 for( int c = 0; c < items.length; c++ )
203 {
204 try
205 {
206 AssertedXPathImpl assertedXPathImpl = null;
207 if( assertedXPathsContainer != null )
208 {
209 String xpath = XmlUtils.createAbsoluteXPath( items[c].getDomNode() );
210 if( xpath != null )
211 {
212 XmlObject xmlObj = items[c];
213
214 assertedXPathImpl = new AssertedXPathImpl( this, xpath, xmlObj );
215 assertedXPathsContainer.addAssertedXPath( assertedXPathImpl );
216 }
217 }
218
219 if( contentObj == null )
220 {
221 if( items[c] instanceof XmlAnySimpleType )
222 {
223 String value = ((XmlAnySimpleType) items[c]).getStringValue();
224 String expandedValue = PropertyExpansionUtils.expandProperties( context, value );
225 XMLAssert.assertEquals( expandedContent, expandedValue );
226 }
227 else
228 {
229 Node domNode = items[c].getDomNode();
230 if( domNode.getNodeType() == Node.ELEMENT_NODE )
231 {
232 String expandedValue = PropertyExpansionUtils.expandProperties( context, XmlUtils
233 .getElementText( (Element) domNode ) );
234 XMLAssert.assertEquals( expandedContent, expandedValue );
235 }
236 else
237 {
238 String expandedValue = PropertyExpansionUtils.expandProperties( context, domNode
239 .getNodeValue() );
240 XMLAssert.assertEquals( expandedContent, expandedValue );
241 }
242 }
243 }
244 else
245 {
246 compareValues( contentObj.xmlText( options ), items[c].xmlText( options ), items[c] );
247 }
248
249 break;
250 }
251 catch( Throwable e )
252 {
253 if( c == items.length - 1 )
254 throw e;
255 }
256 }
257 }
258 catch( Throwable e )
259 {
260 String msg = "";
261
262 if( e instanceof ComparisonFailure )
263 {
264 ComparisonFailure cf = (ComparisonFailure) e;
265 String expected = cf.getExpected();
266 String actual = cf.getActual();
267
268
269
270
271
272
273
274 msg = "XPathContains comparison failed, expecting [" + expected + "], actual was [" + actual + "]";
275 }
276 else
277 {
278 msg = "XPathContains assertion failed for path [" + path + "] : " + e.getClass().getSimpleName() + ":"
279 + e.getMessage();
280 }
281
282 throw new AssertionException( new AssertionError( msg ) );
283 }
284
285 return type + " matches content for [" + path + "]";
286 }
287
288 private void compareValues( String expandedContent, String expandedValue, XmlObject object ) throws Exception
289 {
290 Diff diff = new Diff( expandedContent, expandedValue );
291 InternalDifferenceListener internalDifferenceListener = new InternalDifferenceListener();
292 diff.overrideDifferenceListener( internalDifferenceListener );
293
294 if( !diff.identical() )
295 throw new Exception( diff.toString() );
296
297 StringList nodesToRemove = internalDifferenceListener.getNodesToRemove();
298
299 if( !nodesToRemove.isEmpty() )
300 {
301 for( String node : nodesToRemove )
302 {
303 if( node == null )
304 continue;
305
306 int ix = node.indexOf( "\n/" );
307 if( ix != -1 )
308 node = node.substring( 0, ix + 1 ) + "/" + node.substring( ix + 1 );
309 else if( node.startsWith( "/" ) )
310 node = "/" + node;
311
312 XmlObject[] paths = object.selectPath( node );
313 if( paths.length > 0 )
314 {
315 Node domNode = paths[0].getDomNode();
316 if( domNode.getNodeType() == Node.ATTRIBUTE_NODE )
317 ((Attr) domNode).getOwnerElement().removeAttributeNode( (Attr) domNode );
318 else
319 domNode.getParentNode().removeChild( domNode );
320
321 object.set( object.copy() );
322 }
323 }
324 }
325 }
326
327 @Override
328 public boolean configure()
329 {
330 if( configurationDialog == null )
331 buildConfigurationDialog();
332
333 pathArea.setText( path );
334 contentArea.setText( expectedContent );
335 allowWildcardsCheckBox.setSelected( allowWildcards );
336
337 UISupport.showDialog( configurationDialog );
338 return configureResult;
339 }
340
341 protected void buildConfigurationDialog()
342 {
343 configurationDialog = new JDialog( UISupport.getMainFrame() );
344 configurationDialog.setTitle( "XPath Match configuration" );
345 configurationDialog.addWindowListener( new WindowAdapter()
346 {
347 @Override
348 public void windowOpened( WindowEvent event )
349 {
350 SwingUtilities.invokeLater( new Runnable()
351 {
352 public void run()
353 {
354 pathArea.requestFocusInWindow();
355 }
356 } );
357 }
358 } );
359
360 JPanel contentPanel = new JPanel( new BorderLayout() );
361 contentPanel.add( UISupport.buildDescription( "Specify xpath expression and expected result",
362 "declare namespaces with <code>declare namespace <prefix>='<namespace>';</code>", null ),
363 BorderLayout.NORTH );
364
365 JSplitPane splitPane = UISupport.createVerticalSplit();
366
367 pathArea = new JUndoableTextArea();
368 pathArea.setToolTipText( "Specifies the XPath expression to select from the message for validation" );
369
370 JPanel pathPanel = new JPanel( new BorderLayout() );
371 JXToolBar pathToolbar = UISupport.createToolbar();
372 addPathEditorActions( pathToolbar );
373
374 pathPanel.add( pathToolbar, BorderLayout.NORTH );
375 pathPanel.add( new JScrollPane( pathArea ), BorderLayout.CENTER );
376
377 splitPane.setTopComponent( UISupport.addTitledBorder( pathPanel, "XPath Expression" ) );
378
379 contentArea = new JUndoableTextArea();
380 contentArea.setToolTipText( "Specifies the expected result of the XPath expression" );
381
382 JPanel matchPanel = new JPanel( new BorderLayout() );
383 JXToolBar contentToolbar = UISupport.createToolbar();
384 addMatchEditorActions( contentToolbar );
385
386 matchPanel.add( contentToolbar, BorderLayout.NORTH );
387 matchPanel.add( new JScrollPane( contentArea ), BorderLayout.CENTER );
388
389 splitPane.setBottomComponent( UISupport.addTitledBorder( matchPanel, "Expected Result" ) );
390 splitPane.setDividerLocation( 150 );
391 splitPane.setBorder( BorderFactory.createEmptyBorder( 0, 1, 0, 1 ) );
392
393 contentPanel.add( splitPane, BorderLayout.CENTER );
394
395 ButtonBarBuilder builder = new ButtonBarBuilder();
396
397 ShowOnlineHelpAction showOnlineHelpAction = new ShowOnlineHelpAction( HelpUrls.XPATHASSERTIONEDITOR_HELP_URL );
398 builder.addFixed( UISupport.createToolbarButton( showOnlineHelpAction ) );
399 builder.addGlue();
400
401 JButton okButton = new JButton( new OkAction() );
402 builder.addFixed( okButton );
403 builder.addRelatedGap();
404 builder.addFixed( new JButton( new CancelAction() ) );
405
406 builder.setBorder( BorderFactory.createEmptyBorder( 1, 5, 5, 5 ) );
407
408 contentPanel.add( builder.getPanel(), BorderLayout.SOUTH );
409
410 configurationDialog.setContentPane( contentPanel );
411 configurationDialog.setSize( 600, 500 );
412 configurationDialog.setModal( true );
413 UISupport.initDialogActions( configurationDialog, showOnlineHelpAction, okButton );
414 }
415
416 protected void addPathEditorActions( JXToolBar toolbar )
417 {
418 toolbar.addFixed( new JButton( new DeclareNamespacesFromCurrentAction() ) );
419 }
420
421 protected void addMatchEditorActions( JXToolBar toolbar )
422 {
423 toolbar.addFixed( new JButton( new SelectFromCurrentAction() ) );
424 toolbar.addRelatedGap();
425 toolbar.addFixed( new JButton( new TestPathAction() ) );
426 allowWildcardsCheckBox = new JCheckBox( "Allow Wildcards" );
427
428 Dimension dim = new Dimension( 100, 20 );
429
430 allowWildcardsCheckBox.setSize( dim );
431 allowWildcardsCheckBox.setPreferredSize( dim );
432
433 allowWildcardsCheckBox.setOpaque( false );
434 toolbar.addRelatedGap();
435 toolbar.addFixed( allowWildcardsCheckBox );
436
437 Dimension largerDim = new Dimension( 200, 20 );
438 ignoreNamspaceDifferencesCheckBox = new JCheckBox( "Ignore namespace prefixes" );
439 ignoreNamspaceDifferencesCheckBox.setSize( largerDim );
440 ignoreNamspaceDifferencesCheckBox.setPreferredSize( largerDim );
441 ignoreNamspaceDifferencesCheckBox.setOpaque( false );
442 toolbar.addRelatedGap();
443 toolbar.addFixed( ignoreNamspaceDifferencesCheckBox );
444 }
445
446 public XmlObject createConfiguration()
447 {
448 XmlObjectConfigurationBuilder builder = new XmlObjectConfigurationBuilder();
449 builder.add( "path", path );
450 builder.add( "content", expectedContent );
451 builder.add( "allowWildcards", allowWildcards );
452 builder.add( "ignoreNamspaceDifferences", ignoreNamspaceDifferences );
453 return builder.finish();
454 }
455
456 public void selectFromCurrent()
457 {
458 XmlCursor cursor = null;
459
460 try
461 {
462 XmlOptions options = new XmlOptions();
463 options.setSavePrettyPrint();
464 options.setSaveOuter();
465 options.setSaveAggressiveNamespaces();
466
467 String assertableContent = getAssertable().getAssertableContent();
468 if( assertableContent == null || assertableContent.trim().length() == 0 )
469 {
470 UISupport.showErrorMessage( "Missing content to select from" );
471 return;
472 }
473
474 XmlObject xml = XmlObject.Factory.parse( assertableContent );
475
476 String txt = pathArea == null || !pathArea.isVisible() ? getPath() : pathArea.getSelectedText();
477 if( txt == null )
478 txt = pathArea == null ? "" : pathArea.getText();
479
480 WsdlTestRunContext context = new WsdlTestRunContext( (TestStep) getAssertable().getModelItem() );
481
482 String expandedPath = PropertyExpansionUtils.expandProperties( context, txt.trim() );
483
484 if( contentArea != null && contentArea.isVisible() )
485 contentArea.setText( "" );
486
487 cursor = xml.newCursor();
488 cursor.selectPath( expandedPath );
489 if( !cursor.toNextSelection() )
490 {
491 UISupport.showErrorMessage( "No match in current response" );
492 }
493 else if( cursor.hasNextSelection() )
494 {
495 UISupport.showErrorMessage( "More than one match in current response" );
496 }
497 else
498 {
499 Node domNode = cursor.getDomNode();
500 String stringValue = null;
501
502 if( domNode.getNodeType() == Node.ATTRIBUTE_NODE || domNode.getNodeType() == Node.TEXT_NODE )
503 {
504 stringValue = domNode.getNodeValue();
505 }
506 else if( cursor.getObject() instanceof XmlAnySimpleType )
507 {
508 stringValue = ((XmlAnySimpleType) cursor.getObject()).getStringValue();
509 }
510 else
511 {
512 if( domNode.getNodeType() == Node.ELEMENT_NODE )
513 {
514 Element elm = (Element) domNode;
515 if( elm.getChildNodes().getLength() == 1 && elm.getAttributes().getLength() == 0 )
516 stringValue = XmlUtils.getElementText( elm );
517 else
518 stringValue = cursor.getObject().xmlText( options );
519 }
520 else
521 {
522 stringValue = domNode.getNodeValue();
523 }
524 }
525
526 if( contentArea != null && contentArea.isVisible() )
527 contentArea.setText( stringValue );
528 else
529 setExpectedContent( stringValue );
530 }
531 }
532 catch( Throwable e )
533 {
534 UISupport.showErrorMessage( e.toString() );
535 SoapUI.logError( e );
536 }
537 finally
538 {
539 if( cursor != null )
540 cursor.dispose();
541 }
542 }
543
544 private final class InternalDifferenceListener implements DifferenceListener
545 {
546 private StringList nodesToRemove = new StringList();
547
548 public int differenceFound( Difference diff )
549 {
550 if( allowWildcards
551 && (diff.getId() == DifferenceEngine.TEXT_VALUE.getId() || diff.getId() == DifferenceEngine.ATTR_VALUE.getId()) )
552 {
553 if( diff.getControlNodeDetail().getValue().equals( "*" ) )
554 {
555 Node node = diff.getTestNodeDetail().getNode();
556 String xp = XmlUtils.createAbsoluteXPath( node.getNodeType() == Node.ATTRIBUTE_NODE ? node : node.getParentNode() );
557 nodesToRemove.add( xp );
558 return Diff.RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
559 }
560 }
561 else if( ignoreNamspaceDifferences && diff.getId() == DifferenceEngine.NAMESPACE_PREFIX_ID )
562 {
563 return Diff.RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
564 }
565
566 return Diff.RETURN_ACCEPT_DIFFERENCE;
567 }
568
569 public void skippedComparison( Node arg0, Node arg1 )
570 {
571
572 }
573
574 public StringList getNodesToRemove()
575 {
576 return nodesToRemove;
577 }
578 }
579
580 public class OkAction extends AbstractAction
581 {
582 public OkAction()
583 {
584 super( "Save" );
585 }
586
587 public void actionPerformed( ActionEvent arg0 )
588 {
589 setPath( pathArea.getText().trim() );
590 setExpectedContent( contentArea.getText() );
591 setAllowWildcards( allowWildcardsCheckBox.isSelected() );
592 setIgnoreNamspaceDifferences( ignoreNamspaceDifferencesCheckBox.isSelected() );
593 setConfiguration( createConfiguration() );
594 configureResult = true;
595 configurationDialog.setVisible( false );
596 }
597 }
598
599 public class CancelAction extends AbstractAction
600 {
601 public CancelAction()
602 {
603 super( "Cancel" );
604 }
605
606 public void actionPerformed( ActionEvent arg0 )
607 {
608 configureResult = false;
609 configurationDialog.setVisible( false );
610 }
611 }
612
613 public class DeclareNamespacesFromCurrentAction extends AbstractAction
614 {
615 public DeclareNamespacesFromCurrentAction()
616 {
617 super( "Declare" );
618 putValue( Action.SHORT_DESCRIPTION, "Add namespace declaration from current message to XPath expression" );
619 }
620
621 public void actionPerformed( ActionEvent arg0 )
622 {
623 try
624 {
625 String content = getAssertable().getAssertableContent();
626 if( content != null && content.trim().length() > 0 )
627 {
628 pathArea.setText( XmlUtils.declareXPathNamespaces( content ) + pathArea.getText() );
629 }
630 else if( UISupport.confirm( "Declare namespaces from schema instead?", "Missing Response" ) )
631 {
632 pathArea.setText( XmlUtils.declareXPathNamespaces( (WsdlInterface) getAssertable().getInterface() )
633 + pathArea.getText() );
634 }
635 }
636 catch( Exception e )
637 {
638 log.error( e.getMessage() );
639 }
640 }
641 }
642
643 public class TestPathAction extends AbstractAction
644 {
645 public TestPathAction()
646 {
647 super( "Test" );
648 putValue( Action.SHORT_DESCRIPTION,
649 "Tests the XPath expression for the current message against the Expected Content field" );
650 }
651
652 public void actionPerformed( ActionEvent arg0 )
653 {
654 String oldPath = getPath();
655 String oldContent = getExpectedContent();
656 boolean oldAllowWildcards = isAllowWildcards();
657
658 setPath( pathArea.getText().trim() );
659 setExpectedContent( contentArea.getText() );
660 setAllowWildcards( allowWildcardsCheckBox.isSelected() );
661 setIgnoreNamspaceDifferences( ignoreNamspaceDifferencesCheckBox.isSelected() );
662
663 try
664 {
665 String msg = assertContent( getAssertable().getAssertableContent(), new WsdlTestRunContext( (TestStep) getAssertable()
666 .getModelItem() ), "Response" );
667 UISupport.showInfoMessage( msg, "Success" );
668 }
669 catch( AssertionException e )
670 {
671 UISupport.showErrorMessage( e.getMessage() );
672 }
673
674 setPath( oldPath );
675 setExpectedContent( oldContent );
676 setAllowWildcards( oldAllowWildcards );
677 }
678 }
679
680 public class SelectFromCurrentAction extends AbstractAction
681 {
682 public SelectFromCurrentAction()
683 {
684 super( "Select from current" );
685 putValue( Action.SHORT_DESCRIPTION,
686 "Selects the XPath expression from the current message into the Expected Content field" );
687 }
688
689 public void actionPerformed( ActionEvent arg0 )
690 {
691 selectFromCurrent();
692 }
693 }
694
695 @Override
696 protected String internalAssertRequest( MessageExchange messageExchange, SubmitContext context )
697 throws AssertionException
698 {
699 if( !messageExchange.hasRequest( true ) )
700 return "Missing Request";
701 else
702 return assertContent( messageExchange.getRequestContent(), context, "Request" );
703 }
704
705 public JTextArea getContentArea()
706 {
707 return contentArea;
708 }
709
710 public JTextArea getPathArea()
711 {
712 return pathArea;
713 }
714
715 @Override
716 public PropertyExpansion[] getPropertyExpansions()
717 {
718 List<PropertyExpansion> result = new ArrayList<PropertyExpansion>();
719
720 result.addAll( PropertyExpansionUtils.extractPropertyExpansions( getAssertable().getModelItem(), this, "expectedContent" ) );
721 result.addAll( PropertyExpansionUtils.extractPropertyExpansions( getAssertable().getModelItem(), this, "path" ) );
722
723 return result.toArray( new PropertyExpansion[result.size()] );
724 }
725
726 public XPathReference[] getXPathReferences()
727 {
728 List<XPathReference> result = new ArrayList<XPathReference>();
729
730 if( StringUtils.hasContent( getPath() ) )
731 {
732 TestModelItem testStep = (TestModelItem) getAssertable().getModelItem();
733 TestProperty property = testStep instanceof WsdlTestRequestStep ? testStep.getProperty( "Response" ) : testStep.getProperty( "Request" );
734 result.add( new XPathReferenceImpl( "XPath for " + getName() + " XPathContainsAssertion in " + testStep.getName(), property, this, "path" ) );
735 }
736
737 return result.toArray( new XPathReference[result.size()] );
738 }
739
740 public static class Factory extends AbstractTestAssertionFactory
741 {
742 public Factory()
743 {
744 super( XPathContainsAssertion.ID, XPathContainsAssertion.LABEL, XPathContainsAssertion.class );
745 }
746 }
747 }