001: // Copyright © 2002-2005 Canoo Engineering AG, Switzerland.
002: package com.canoo.webtest.steps.verify;
003:
004: import org.jaxen.JaxenException;
005: import org.jaxen.XPath;
006:
007: import com.canoo.webtest.engine.StepFailedException;
008: import com.canoo.webtest.engine.xpath.XPathHelper;
009: import com.gargoylesoftware.htmlunit.Page;
010:
011: /**
012: * <p>A webtest verify step that evaluates XPath expressions.</p>
013: *
014: * <p>This step can either simply verify that an xpath is true, or that it matches something in particular. In keeping
015: * with XSLT parlance, the <i>test</i> attribute chooses the first mode and the <i>select</i> attribute chooses the
016: * second. If the <i>select</i> attribute exists, a <i>value</i> attribute must also exist which contains the expected
017: * value.</p>
018: *
019: * @author <a href="balld@webslingerz.com">Donald Ball</a>, Dierk König, Carsten Seibert
020: * @author Marc Guillemot
021: * @since Oct 2002
022: * @webtest.step
023: * category="Core"
024: * name="verifyXPath"
025: * alias="verifyxpath"
026: * description="This step verifies that an <key>XPATH</key> expression is true or has a certain value. Useful for <key>XML</key> and <key>HTML</key> pages."
027: */
028:
029: public class VerifyXPath extends AbstractVerifyTextStep {
030: private String fXpath;
031:
032: {
033: setOptionalText(true);
034: setOptionalPreviousPage(true);
035: }
036:
037: /**
038: * @param text
039: * @webtest.parameter
040: * required="no"
041: * description="The expected text value of the xpath evaluation.
042: * If omitted the step checks that the result is not the boolean false and not empty."
043: */
044: public void setText(String text) {
045: super .setText(text);
046: }
047:
048: public String getXpath() {
049: return fXpath;
050: }
051:
052: /**
053: * @webtest.parameter
054: * required="true"
055: * description="Specifies the <key>XPATH</key> expression to evaluate."
056: */
057: public void setXpath(final String xpath) {
058: fXpath = xpath;
059: }
060:
061: protected void verifyParameters() {
062: super .verifyParameters();
063: nullParamCheck(fXpath, "xpath");
064: }
065:
066: public void doExecute() throws JaxenException {
067: final Page currentResponse = getContext().getCurrentResponse();
068:
069: final XPathHelper xpathHelper = getContext().getXPathHelper();
070: final XPath xpath = xpathHelper.getXPath(currentResponse,
071: getXpath());
072: final Object document = xpathHelper
073: .getDocument(currentResponse);
074:
075: verifyXPath(xpath, document);
076: }
077:
078: protected boolean isComparingPathAndValue() {
079: return getText() != null;
080: }
081:
082: protected void verifyXPath(final XPath xpath, final Object document)
083: throws JaxenException, StepFailedException {
084: if (isComparingPathAndValue()) {
085: final String actualValue = xpath.stringValueOf(document);
086: if (!verifyText(actualValue)) {
087: throw new StepFailedException(
088: "Wrong result for xpath >" + fXpath + "<",
089: getText(), actualValue, this );
090: }
091: } else {
092: final Object singleNode = xpath.selectSingleNode(document);
093: if (singleNode == null) {
094: throw new StepFailedException("xpath test: " + fXpath
095: + " matched no nodes", this );
096: } else if (Boolean.FALSE.equals(singleNode)) {
097: throw new StepFailedException("xpath test: " + fXpath
098: + " evaluates to false", this);
099: }
100: }
101: }
102: }
|