001: // Copyright © 2002-2007 Canoo Engineering AG, Switzerland.
002: package com.canoo.webtest.steps.verify;
003:
004: import java.util.List;
005: import org.jaxen.Context;
006: import org.jaxen.Function;
007: import org.jaxen.FunctionCallException;
008: import org.jaxen.JaxenException;
009: import org.jaxen.UnresolvableException;
010:
011: import com.canoo.webtest.engine.xpath.XPathHelper;
012: import com.canoo.webtest.steps.BaseStepTestCase;
013: import com.canoo.webtest.steps.Step;
014:
015: /**
016: * Unit tests for {@link VerifyXPath}.
017: * @author <a href="balld@webslingerZ.com">Donald Ball</a>, Carsten Seibert, Dierk König
018: * @author Marc Guillemot, Paul King
019: */
020: public class VerifyXPathTest extends BaseStepTestCase {
021: private VerifyXPath fStep;
022:
023: protected void setUp() throws Exception {
024: super .setUp();
025: fStep = (VerifyXPath) getStep();
026: }
027:
028: protected Step createStep() {
029: return new VerifyXPath();
030: }
031:
032: public void testRejectsNullXpath() {
033: assertStepRejectsNullParam("xpath", getExecuteStepTestBlock());
034: }
035:
036: public void testHandleHtmlPage() throws Exception {
037: getContext()
038: .setDefaultResponse(
039: "<html><head></head><body><h1>hello</h1></body></html>");
040: fStep.setXpath("/html/body/h1");
041: executeStep(fStep);
042: }
043:
044: public void testHandleXmlPage() throws Exception {
045: getContext().setDefaultResponse(
046: "<xml><body><h1>hello</h1></body></xml>", "text/xml");
047: fStep.setXpath("/xml/body/h1");
048: executeStep(fStep);
049: }
050:
051: /**
052: * Tests an xpath check on an XmlPage containing an badly formed xml document
053: * @throws Exception if the test fails
054: */
055: public void testHandleInvalidXmlPage() throws Exception {
056: getContext().setDefaultResponse("<xml type='foo & fii'></xml>",
057: "text/xml");
058: fStep.setXpath("/xml");
059:
060: assertFailOnExecute(fStep, "", "");
061: }
062:
063: public void testHandleMissingPage() throws Exception {
064: fStep.setXpath("'valeur'='value'");
065: fStep.setText("false");
066: executeStep(fStep);
067: fStep.setXpath("/not/here");
068: assertFailOnExecute(fStep, "", "");
069: }
070:
071: public void testHandleUnknownPage() throws JaxenException {
072: getContext().setDefaultResponse("hello", "text/plain");
073: fStep.setXpath("/html/head/title");
074: assertFailOnExecute(fStep, "", "");
075: }
076:
077: public void testLocateI18nText() throws Exception {
078: final String htmlContent = "<html><body><h1>你</h1></body></html>";
079: getContext().setDefaultResponse(htmlContent);
080:
081: fStep.setXpath("/html/body/h1");
082: fStep.setText("你");
083: assertFailOnExecute(fStep, "Numeric entity not found", "");
084: fStep.setText("\u4f60");
085: executeStep(fStep);
086: }
087:
088: public void testLocateI18nNamedEntitiesText() throws Exception {
089: final String htmlContent = "<html><body><h1>ü</h1></body></html>";
090: getContext().setDefaultResponse(htmlContent);
091:
092: fStep.setXpath("/html/body/h1");
093: fStep.setText("ü");
094: assertFailOnExecute(fStep, "Named entity not found", "");
095: fStep.setText("\u00fc");
096: executeStep(fStep);
097: }
098:
099: public void testExistingXPathExpression() throws Exception {
100: defineSampleDocumentAsCurrent();
101: fStep.setXpath("/html/head/title");
102: executeStep(fStep);
103: }
104:
105: public void testNonExistingXPathExpression() throws Exception {
106: defineSampleDocumentAsCurrent();
107: fStep.setXpath("/not/here");
108: assertFailOnExecute(fStep, "", "");
109: }
110:
111: public void testNodeValueOK() throws Exception {
112: defineSampleDocumentAsCurrent();
113: fStep.setXpath("/html/head/title");
114: fStep.setText("foo");
115: executeStep(fStep);
116: }
117:
118: public void testNodeValueNotOK() throws Exception {
119: defineSampleDocumentAsCurrent();
120: fStep.setXpath("/html/head/title");
121: fStep.setText("bar");
122: assertFailOnExecute(fStep, "", "");
123: }
124:
125: /**
126: * Test use of variable, function and namespaces contexts
127: * @throws Exception if the test fails
128: */
129: public void testContext() throws Exception {
130: defineSampleDocumentAsCurrent();
131:
132: final XPathHelper xpathHelper = fStep.getContext()
133: .getXPathHelper();
134: xpathHelper.getVariableContext().setVariableValue("foo", "123");
135: fStep.setXpath("$foo");
136: fStep.setText("123");
137: executeStep(fStep);
138:
139: final Function reverse = new Function() {
140: public Object call(final Context context, final List args)
141: throws FunctionCallException {
142: final StringBuffer sb = new StringBuffer();
143: final String arg = (String) args.get(0);
144: for (int i = arg.length() - 1; i >= 0; --i)
145: sb.append(arg.charAt(i));
146: return sb.toString();
147: }
148: };
149: // function without context
150: fStep.setXpath("myReverse('abcdef')");
151: fStep.setText("fedcba");
152: assertThrowOnExecute(fStep, "", "", UnresolvableException.class);
153:
154: xpathHelper.getFunctionContext().registerFunction(null,
155: "myReverse", reverse);
156: executeStep(fStep);
157:
158: // function with context
159: fStep.setXpath("wt:myReverse2('abcdef')");
160: fStep.setText("fedcba");
161: assertThrowOnExecute(fStep, "", "", UnresolvableException.class);
162: xpathHelper.getFunctionContext().registerFunction(
163: "webtest/xpath", "myReverse2", reverse);
164: assertThrowOnExecute(fStep, "", "", UnresolvableException.class);
165: xpathHelper.getNamespaceContext().addNamespace("wt",
166: "webtest/xpath");
167: executeStep(fStep);
168: }
169:
170: /**
171: * Xpath evaluating to boolean true without text should pass
172: * @throws Exception if the test fails
173: */
174: public void testBooleanValueNoTextTrue() throws Exception {
175: defineSampleDocumentAsCurrent();
176: fStep.setXpath("1 > 0");
177: executeStep(fStep);
178: }
179:
180: /**
181: * Xpath evaluating to boolean true with text "true" should pass
182: * @throws Exception if the test fails
183: */
184: public void testBooleanValueTextTrue() throws Exception {
185: defineSampleDocumentAsCurrent();
186: fStep.setXpath("1 > 0");
187: fStep.setText("true");
188: executeStep(fStep);
189: }
190:
191: /**
192: * Xpath evaluating to boolean false without text should fail
193: * @throws Exception if the test fails
194: */
195: public void testBooleanValueNoTextFalse() throws Exception {
196: defineSampleDocumentAsCurrent();
197: fStep.setXpath("1 < 0");
198: assertFailOnExecute(fStep, "", "");
199: }
200:
201: /**
202: * Xpath evaluating to boolean false with text "false" should pass
203: * @throws Exception if the test fails
204: */
205: public void testBooleanValueTextFalse() throws Exception {
206: defineSampleDocumentAsCurrent();
207: fStep.setXpath("1 < 0");
208: fStep.setText("false");
209: executeStep(fStep);
210: }
211:
212: public void testMissingSelectValue() throws Exception {
213: final VerifyXPath step = new VerifyXPath();
214: step.setXpath("/bla");
215: assertFalse(step.isComparingPathAndValue());
216: step.setText("bla");
217: assertTrue(step.isComparingPathAndValue());
218: }
219:
220: private void defineSampleDocumentAsCurrent() throws Exception {
221: final String htmlDocument = "<html><head><title>foo</title></head><body>foobar</body></html>";
222: getContext().setDefaultResponse(htmlDocument);
223: }
224:
225: /**
226: * Test that text is trimmed
227: * @throws Exception if the test fails
228: */
229: public void testBlankBeforeElementContent() throws Exception {
230: final String document = "<html><body>" + "<table>"
231: + "<tr><td>1.1</td><td>1.2</td><td>1.3</td></tr>"
232: + "<tr><td> 2.1</td><td>2.2</td><td>2.3</td></tr>"
233: + "</table>" + "</body></html>";
234: getContext().setDefaultResponse(document);
235: fStep.setXpath("//tr[td='2.1']/td[3]");
236: fStep.setText("2.3");
237: executeStep(fStep);
238: }
239:
240: /**
241: * Test for WT-253: automatically extract namespaces from extract the xml
242: * @throws Exception if the test fails
243: */
244: public void testXPathNamespaces() throws Exception {
245: final String xml = "<?xml version=\"1.0\"?>\n"
246: + "<SOAP-ENV:Envelope\n"
247: + " xmlns:SOAP-ENV=\"http://webtest.canoo.com/soap/envelope/\"\n"
248: + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" >\n"
249: + " <SOAP-ENV:Body>\n"
250: + " <calculateFibonacci \n"
251: + " type=\"xsi:positiveInteger\">10</calculateFibonacci>\n"
252: + " </SOAP-ENV:Body>\n" + "</SOAP-ENV:Envelope>";
253:
254: getContext().setDefaultResponse(xml, "text/xml");
255: fStep.setXpath("//SOAP-ENV:Body/calculateFibonacci/text()");
256: fStep.setText("10");
257: executeStep(fStep);
258:
259: // check that WebTest goodies are still available
260: fStep
261: .setXpath("wt:cleanText(//SOAP-ENV:Body/calculateFibonacci)");
262: fStep.setText("10");
263: executeStep(fStep);
264: }
265: }
|