/* * SoapUI, Copyright (C) 2004-2016 SmartBear Software * * Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent * versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * * http://ec.europa.eu/idabc/eupl * * Unless required by applicable law or agreed to in writing, software distributed under the Licence is * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the Licence for the specific language governing permissions and limitations * under the Licence. */ package com.eviware.soapui.impl.wsdl.teststeps.assertions.basic; import com.eviware.soapui.config.TestAssertionConfig; import com.eviware.soapui.impl.wsdl.teststeps.WsdlMessageAssertion; import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep; import com.eviware.soapui.model.TestModelItem; import com.eviware.soapui.model.TestPropertyHolder; import com.eviware.soapui.model.iface.MessageExchange; import com.eviware.soapui.model.iface.SubmitContext; import com.eviware.soapui.model.propertyexpansion.PropertyExpansion; import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils; import com.eviware.soapui.model.support.XPathReference; import com.eviware.soapui.model.support.XPathReferenceContainer; import com.eviware.soapui.model.support.XPathReferenceImpl; import com.eviware.soapui.model.testsuite.Assertable; import com.eviware.soapui.model.testsuite.AssertionError; import com.eviware.soapui.model.testsuite.AssertionException; import com.eviware.soapui.model.testsuite.RequestAssertion; import com.eviware.soapui.model.testsuite.ResponseAssertion; import com.eviware.soapui.model.testsuite.TestProperty; import com.eviware.soapui.support.StringUtils; import com.eviware.soapui.support.Tools; import com.eviware.soapui.support.components.JXToolBar; import com.eviware.soapui.support.types.StringList; import com.eviware.soapui.support.xml.XmlObjectConfigurationBuilder; import com.eviware.soapui.support.xml.XmlObjectConfigurationReader; import com.eviware.soapui.support.xml.XmlUtils; import org.apache.xmlbeans.XmlObject; import org.custommonkey.xmlunit.Diff; import org.custommonkey.xmlunit.Difference; import org.custommonkey.xmlunit.DifferenceEngine; import org.custommonkey.xmlunit.DifferenceListener; import org.w3c.dom.Node; import javax.swing.JTextArea; import java.util.ArrayList; import java.util.List; public abstract class AbstractXmlContainsAssertion extends WsdlMessageAssertion implements RequestAssertion, ResponseAssertion, XPathReferenceContainer{ protected String expectedContent; protected String path; protected boolean allowWildcards; protected boolean ignoreNamespaceDifferences; protected boolean ignoreComments; protected AssertionConfigurationDialog configurationDialog; protected AbstractXmlContainsAssertion(TestAssertionConfig assertionConfig, Assertable modelItem, boolean cloneable, boolean configurable, boolean multiple, boolean requiresResponseContent) { super(assertionConfig, modelItem, cloneable, configurable, multiple, requiresResponseContent); XmlObjectConfigurationReader reader = new XmlObjectConfigurationReader(getConfiguration()); path = reader.readString("path", null); expectedContent = reader.readString("content", null); allowWildcards = reader.readBoolean("allowWildcards", false); ignoreNamespaceDifferences = reader.readBoolean("ignoreNamspaceDifferences", false); ignoreComments = reader.readBoolean("ignoreComments", false); } public String getExpectedContent() { return expectedContent; } public void setExpectedContent(String expectedContent) { setExpectedContent(expectedContent, true); } protected void setExpectedContent(String expectedContent, boolean save) { this.expectedContent = expectedContent; if (save) { setConfiguration(createConfiguration()); } } /** * @deprecated */ @Deprecated public void setContent(String content) { setExpectedContent(content); } public String getPath() { return path; } public void setPath(String path) { this.path = path; setConfiguration(createConfiguration()); } public boolean isAllowWildcards() { return allowWildcards; } public void setAllowWildcards(boolean allowWildcards) { this.allowWildcards = allowWildcards; setConfiguration(createConfiguration()); } public boolean isIgnoreNamespaceDifferences() { return ignoreNamespaceDifferences; } public void setIgnoreNamespaceDifferences(boolean ignoreNamespaceDifferences) { this.ignoreNamespaceDifferences = ignoreNamespaceDifferences; setConfiguration(createConfiguration()); } public boolean isIgnoreComments() { return ignoreComments; } public void setIgnoreComments(boolean ignoreComments) { this.ignoreComments = ignoreComments; setConfiguration(createConfiguration()); } public XmlObject createConfiguration() { XmlObjectConfigurationBuilder builder = new XmlObjectConfigurationBuilder(); addConfigurationValues(builder); return builder.finish(); } protected void addConfigurationValues(XmlObjectConfigurationBuilder builder) { builder.add("path", path); builder.add("content", expectedContent); builder.add("allowWildcards", allowWildcards); builder.add("ignoreNamspaceDifferences", ignoreNamespaceDifferences); builder.add("ignoreComments", ignoreComments); } protected JTextArea getPathArea() { return configurationDialog == null ? null : configurationDialog.getPathArea(); } protected JTextArea getContentArea() { return configurationDialog == null ? null : configurationDialog.getContentArea(); } @Override public boolean configure() { if (configurationDialog == null) { configurationDialog = new AssertionConfigurationDialog(getAssertion()); } return configurationDialog.configure(); } protected AbstractXmlContainsAssertion getAssertion() { return this; } @Override protected String internalAssertResponse(MessageExchange messageExchange, SubmitContext context) throws AssertionException { if (!messageExchange.hasResponse()) { return "Missing Response"; } else { return assertContent(messageExchange.getResponseContentAsXml(), context, "Response"); } } public abstract String assertContent(String response, SubmitContext context, String type) throws AssertionException; protected String internalAssertProperty(TestPropertyHolder source, String propertyName, MessageExchange messageExchange, SubmitContext context) throws AssertionException { if (!XmlUtils.seemsToBeXml(source.getPropertyValue(propertyName))) { throw new AssertionException(new AssertionError("Property '" + propertyName + "' has value which is not xml!")); } return assertContent(source.getPropertyValue(propertyName), context, propertyName); } @Override protected String internalAssertRequest(MessageExchange messageExchange, SubmitContext context) throws AssertionException { if (!messageExchange.hasRequest(true)) { return "Missing Request"; } else { return assertContent(messageExchange.getRequestContent(), context, "Request"); } } @Override public PropertyExpansion[] getPropertyExpansions() { List<PropertyExpansion> result = new ArrayList<PropertyExpansion>(); result.addAll(PropertyExpansionUtils.extractPropertyExpansions(getAssertable().getModelItem(), this, "expectedContent")); result.addAll(PropertyExpansionUtils.extractPropertyExpansions(getAssertable().getModelItem(), this, "path")); return result.toArray(new PropertyExpansion[result.size()]); } public String getPathAreaTitle() { return "Specify " + getQueryType() + " expression and expected result"; } public String getPathAreaDescription() { return "declare namespaces with <code>declare namespace <prefix>='<namespace>';</code>"; } public String getPathAreaToolTipText() { return "Specifies the " + getQueryType() + " expression to select from the message for validation"; } public String getPathAreaBorderTitle() { return getQueryType() + " Expression"; } public String getContentAreaToolTipText() { return "Specifies the expected result of the " + getQueryType() + " expression"; } public String getConfigurationDialogTitle() { return getQueryType() + " Match Configuration"; } public String getContentAreaBorderTitle() { return "Expected Result"; } public boolean canAssertXmlContent() { return true; } protected void addMatchEditorActions(JXToolBar toolbar) { configurationDialog.addMatchEditorActions(toolbar); } protected void addPathEditorActions(JXToolBar toolbar) { configurationDialog.addDeclareNamespaceButton(toolbar); } public abstract void selectFromCurrent(); protected abstract String getQueryType(); public XPathReference[] getXPathReferences() { List<XPathReference> result = new ArrayList<XPathReference>(); if (StringUtils.hasContent(getPath())) { TestModelItem testStep = getAssertable().getTestStep(); TestProperty property = testStep instanceof WsdlTestRequestStep ? testStep.getProperty("Response") : testStep.getProperty("Request"); result.add(new XPathReferenceImpl(getQueryType() + " for " + getName() + " " + getQueryType() + "ContainsAssertion in " + testStep.getName(), property, this, "path")); } return result.toArray(new XPathReference[result.size()]); } protected final class InternalDifferenceListener implements DifferenceListener { private StringList nodesToRemove = new StringList(); public int differenceFound(Difference diff) { if (allowWildcards && (diff.getId() == DifferenceEngine.TEXT_VALUE.getId() || diff.getId() == DifferenceEngine.ATTR_VALUE.getId())) { if (Tools.isSimilar(diff.getControlNodeDetail().getValue(), diff.getTestNodeDetail().getValue(), '*')) { addToNodesToRemove(diff); return Diff.RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL; } } else if (allowWildcards && diff.getId() == DifferenceEngine.NODE_TYPE.getId()) { if (Tools.isSimilar(diff.getControlNodeDetail().getNode().getNodeValue(), diff.getTestNodeDetail().getNode().getNodeValue(), '*')) { addToNodesToRemove(diff); return Diff.RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL; } } else if (ignoreNamespaceDifferences && diff.getId() == DifferenceEngine.NAMESPACE_PREFIX_ID) { return Diff.RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL; } return Diff.RETURN_ACCEPT_DIFFERENCE; } private void addToNodesToRemove(Difference diff) { Node node = diff.getTestNodeDetail().getNode(); String xp = XmlUtils.createAbsoluteXPath(node.getNodeType() == Node.ATTRIBUTE_NODE ? node : node .getParentNode()); nodesToRemove.add(xp); } public void skippedComparison(Node arg0, Node arg1) { } public StringList getNodesToRemove() { return nodesToRemove; } } }