0001: /*
0002: * Copyright (c) 2002-2008 Gargoyle Software Inc. All rights reserved.
0003: *
0004: * Redistribution and use in source and binary forms, with or without
0005: * modification, are permitted provided that the following conditions are met:
0006: *
0007: * 1. Redistributions of source code must retain the above copyright notice,
0008: * this list of conditions and the following disclaimer.
0009: * 2. Redistributions in binary form must reproduce the above copyright notice,
0010: * this list of conditions and the following disclaimer in the documentation
0011: * and/or other materials provided with the distribution.
0012: * 3. The end-user documentation included with the redistribution, if any, must
0013: * include the following acknowledgment:
0014: *
0015: * "This product includes software developed by Gargoyle Software Inc.
0016: * (http://www.GargoyleSoftware.com/)."
0017: *
0018: * Alternately, this acknowledgment may appear in the software itself, if
0019: * and wherever such third-party acknowledgments normally appear.
0020: * 4. The name "Gargoyle Software" must not be used to endorse or promote
0021: * products derived from this software without prior written permission.
0022: * For written permission, please contact info@GargoyleSoftware.com.
0023: * 5. Products derived from this software may not be called "HtmlUnit", nor may
0024: * "HtmlUnit" appear in their name, without prior written permission of
0025: * Gargoyle Software Inc.
0026: *
0027: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
0028: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
0029: * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
0030: * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
0031: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0032: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
0033: * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
0034: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
0035: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
0036: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0037: */
0038: package com.gargoylesoftware.htmlunit.javascript;
0039:
0040: import java.net.URL;
0041: import java.util.ArrayList;
0042: import java.util.Collections;
0043: import java.util.HashMap;
0044: import java.util.List;
0045: import java.util.Map;
0046:
0047: import org.apache.commons.httpclient.NameValuePair;
0048: import org.mozilla.javascript.Context;
0049: import org.mozilla.javascript.Script;
0050: import org.mozilla.javascript.Scriptable;
0051:
0052: import com.gargoylesoftware.htmlunit.BrowserVersion;
0053: import com.gargoylesoftware.htmlunit.CollectingAlertHandler;
0054: import com.gargoylesoftware.htmlunit.MockWebConnection;
0055: import com.gargoylesoftware.htmlunit.ScriptException;
0056: import com.gargoylesoftware.htmlunit.SubmitMethod;
0057: import com.gargoylesoftware.htmlunit.WebClient;
0058: import com.gargoylesoftware.htmlunit.WebRequestSettings;
0059: import com.gargoylesoftware.htmlunit.WebTestCase;
0060: import com.gargoylesoftware.htmlunit.html.ClickableElement;
0061: import com.gargoylesoftware.htmlunit.html.DomNode;
0062: import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
0063: import com.gargoylesoftware.htmlunit.html.HtmlButtonInput;
0064: import com.gargoylesoftware.htmlunit.html.HtmlForm;
0065: import com.gargoylesoftware.htmlunit.html.HtmlFrame;
0066: import com.gargoylesoftware.htmlunit.html.HtmlPage;
0067: import com.gargoylesoftware.htmlunit.html.HtmlScript;
0068: import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
0069: import com.gargoylesoftware.htmlunit.html.HtmlTextInput;
0070:
0071: /**
0072: * Tests for the {@link JavaScriptEngine}.
0073: *
0074: * @version $Revision: 2132 $
0075: * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
0076: * @author Noboru Sinohara
0077: * @author Darrell DeBoer
0078: * @author <a href="mailto:bcurren@esomnie.com">Ben Curren</a>
0079: * @author Marc Guillemot
0080: * @author Chris Erskine
0081: * @author David K. Taylor
0082: * @author Ahmed Ashour
0083: */
0084: public class JavaScriptEngineTest extends WebTestCase {
0085:
0086: /**
0087: * Create an instance
0088: * @param name The name of the test
0089: */
0090: public JavaScriptEngineTest(final String name) {
0091: super (name);
0092: }
0093:
0094: /**
0095: * @throws Exception if the test fails
0096: */
0097: public void testSetJavascriptEnabled_false() throws Exception {
0098: final WebClient client = new WebClient();
0099: client.setJavaScriptEnabled(false);
0100: final MockWebConnection webConnection = new MockWebConnection(
0101: client);
0102:
0103: final String content = "<html><head><title>foo</title><script>\n"
0104: + "document.form1.textfield1='blue'"
0105: + "</script></head><body>\n"
0106: + "<p>hello world</p>\n"
0107: + "<form name='form1'>\n"
0108: + " <input type='text' name='textfield1' id='textfield1' value='foo' />\n"
0109: + " <input type='text' name='textfield2' id='textfield2'/>\n"
0110: + "</form>\n" + "</body></html>";
0111:
0112: webConnection.setDefaultResponse(content);
0113: client.setWebConnection(webConnection);
0114:
0115: final HtmlPage page = (HtmlPage) client.getPage(URL_GARGOYLE);
0116:
0117: final HtmlTextInput textInput = (HtmlTextInput) page
0118: .getHtmlElementById("textfield1");
0119: assertEquals("foo", textInput.getValueAttribute());
0120: }
0121:
0122: /**
0123: * Regression test for bug
0124: * https://sourceforge.net/tracker/?func=detail&atid=448266&aid=1609944&group_id=47038
0125: * @throws Exception if the test fails
0126: */
0127: public void testOnloadJavascriptFunction() throws Exception {
0128: final String content = "<html><head><title>foo</title><script>\n"
0129: + "function onload() {alert('foo');}"
0130: + "</script></head><body>\n" + "</body></html>";
0131:
0132: final String[] expectedAlerts = { "foo" };
0133: createTestPageForRealBrowserIfNeeded(content, expectedAlerts);
0134:
0135: final List collectedAlerts = new ArrayList();
0136: loadPage(BrowserVersion.FIREFOX_2, content, collectedAlerts);
0137:
0138: assertEquals(expectedAlerts, collectedAlerts);
0139: }
0140:
0141: /**
0142: * Try to set the value of a text input field.
0143: * @throws Exception if the test fails
0144: */
0145: public void testSetInputValue() throws Exception {
0146: final String content = "<html><head><title>foo</title><script>\n"
0147: + "function doTest() {\n"
0148: + " document.form1.textfield1.value='blue'"
0149: + "}\n"
0150: + "</script></head><body onload='doTest()'>\n"
0151: + "<p>hello world</p>\n"
0152: + "<form name='form1'>\n"
0153: + " <input type='text' name='textfield1' id='textfield1' value='foo' />\n"
0154: + " <input type='text' name='textfield2' id='textfield2'/>\n"
0155: + "</form>\n" + "</body></html>";
0156: final List collectedAlerts = null;
0157: final HtmlPage page = loadPage(content, collectedAlerts);
0158:
0159: final HtmlTextInput textInput = (HtmlTextInput) page
0160: .getHtmlElementById("textfield1");
0161: assertEquals("blue", textInput.getValueAttribute());
0162: }
0163:
0164: /**
0165: * @throws Exception if the test fails
0166: */
0167: public void testAlert() throws Exception {
0168: final String content = "<html><head><title>foo</title><script>\n"
0169: + "alert('foo')\n"
0170: + "</script></head><body>\n"
0171: + "<p>hello world</p>\n"
0172: + "<form name='form1'>\n"
0173: + " <input type='text' name='textfield1' id='textfield1' value='foo' />\n"
0174: + " <input type='text' name='textfield2' id='textfield2'/>\n"
0175: + "</form>\n" + "</body></html>";
0176: final List collectedAlerts = new ArrayList();
0177: final HtmlPage page = loadPage(content, collectedAlerts);
0178: assertEquals("foo", page.getTitleText());
0179:
0180: final String[] expectedAlerts = { "foo" };
0181: assertEquals(expectedAlerts, collectedAlerts);
0182: }
0183:
0184: /**
0185: * Checks that a dynamically compiled function works in the scope of its birth
0186: * @throws Exception if the test fails
0187: */
0188: public void testScopeOfNewFunction() throws Exception {
0189: final String content = "<html><head><script>\n"
0190: + "var f = new Function('alert(\"foo\")');\n"
0191: + "f();\n" + "</script></head><body>\n"
0192: + "</body></html>";
0193: final String[] expectedAlerts = { "foo" };
0194: createTestPageForRealBrowserIfNeeded(content, expectedAlerts);
0195:
0196: final List collectedAlerts = new ArrayList();
0197: loadPage(content, collectedAlerts);
0198:
0199: assertEquals(expectedAlerts, collectedAlerts);
0200: }
0201:
0202: /**
0203: * @throws Exception if the test fails
0204: */
0205: public void testScopeOfNestedNewFunction() throws Exception {
0206: final String[] expectedAlerts = { "foo" };
0207: final String content = "<html><head>\n"
0208: + "<script>\n"
0209: + "var foo = 'foo';\n"
0210: + "var f1 = new Function('f = new Function(\"alert(foo)\"); f()');\n"
0211: + "f1();\n" + "</script>\n" + "</head>\n" + "<body>\n"
0212: + "</body></html>";
0213: createTestPageForRealBrowserIfNeeded(content, expectedAlerts);
0214: final List collectedAlerts = new ArrayList();
0215: loadPage(content, collectedAlerts);
0216:
0217: assertEquals(expectedAlerts, collectedAlerts);
0218: }
0219:
0220: /**
0221: * Checks that a dynamically compiled function works in the scope of its birth
0222: * and not the other window
0223: * @throws Exception if the test fails
0224: */
0225: public void testScopeOfNewFunctionCalledFormOtherWindow()
0226: throws Exception {
0227: final String firstContent = "<html><head>\n" + "<script>\n"
0228: + "var foo = 'foo';\n"
0229: + "var test = new Function('alert(foo);');\n"
0230: + "</script>\n" + "</head>\n"
0231: + "<body onload='test()'>\n"
0232: + " <iframe src='page2.html'/>\n" + "</body>\n"
0233: + "</html>";
0234:
0235: final String secondContent = "<html><head><script>\n"
0236: + "var foo = 'foo2';\n" + "parent.test();\n"
0237: + "var f = parent.test;\n" + "f();\n"
0238: + "</script></head></html>";
0239:
0240: final WebClient client = new WebClient();
0241: final MockWebConnection webConnection = new MockWebConnection(
0242: client);
0243: webConnection.setDefaultResponse(secondContent);
0244: webConnection.setResponse(URL_FIRST, firstContent);
0245: client.setWebConnection(webConnection);
0246:
0247: final String[] expectedAlerts = { "foo", "foo", "foo" };
0248:
0249: final List collectedAlerts = new ArrayList();
0250: client.setAlertHandler(new CollectingAlertHandler(
0251: collectedAlerts));
0252: client.getPage(URL_FIRST);
0253:
0254: assertEquals(expectedAlerts, collectedAlerts);
0255: }
0256:
0257: /**
0258: * If a reference has been hold on a page and the page is not
0259: * anymore the one contained in "its" window, javascript execution should
0260: * work... a bit
0261: * @throws Exception if the test fails
0262: */
0263: public void testScopeInInactivePage() throws Exception {
0264: final String firstContent = "<html><head>\n"
0265: + "<script>\n"
0266: + "var foo = 'foo';\n"
0267: + "</script>\n"
0268: + "</head>\n"
0269: + "<body>\n"
0270: + " <a href='page2.html'>to page 2</a>\n"
0271: + " <div id='testdiv' onclick='alert(foo)'>foo</div>\n"
0272: + "</body>\n" + "</html>";
0273:
0274: final WebClient client = new WebClient();
0275: final MockWebConnection webConnection = new MockWebConnection(
0276: client);
0277: webConnection.setDefaultResponse("<html></html>");
0278: webConnection.setResponse(URL_FIRST, firstContent);
0279: client.setWebConnection(webConnection);
0280:
0281: final String[] expectedAlerts = { "foo" };
0282:
0283: final List collectedAlerts = new ArrayList();
0284: client.setAlertHandler(new CollectingAlertHandler(
0285: collectedAlerts));
0286: final HtmlPage page = (HtmlPage) client.getPage(URL_FIRST);
0287: final ClickableElement div = ((ClickableElement) page
0288: .getHtmlElementById("testdiv"));
0289:
0290: ((HtmlAnchor) page.getAnchors().get(0)).click();
0291: // ignore response, and click in the page again
0292: div.click();
0293:
0294: assertEquals(expectedAlerts, collectedAlerts);
0295: }
0296:
0297: /**
0298: * @throws Exception if the test fails
0299: */
0300: public void testExternalScript() throws Exception {
0301: final WebClient client = new WebClient();
0302: final MockWebConnection webConnection = new MockWebConnection(
0303: client);
0304:
0305: final String htmlContent = "<html><head><title>foo</title><script src='/foo.js' id='script1'/>\n"
0306: + "</head><body>\n"
0307: + "<p>hello world</p>\n"
0308: + "<form name='form1'>\n"
0309: + " <input type='text' name='textfield1' id='textfield1' value='foo' />\n"
0310: + " <input type='text' name='textfield2' id='textfield2'/>\n"
0311: + "</form>\n" + "</body></html>";
0312:
0313: final String jsContent = "alert('got here');\n";
0314:
0315: webConnection.setResponse(URL_GARGOYLE, htmlContent);
0316: webConnection.setResponse(new URL(
0317: "http://www.gargoylesoftware.com/foo.js"), jsContent,
0318: "text/javascript");
0319: client.setWebConnection(webConnection);
0320:
0321: final String[] expectedAlerts = { "got here" };
0322: final List collectedAlerts = new ArrayList();
0323: client.setAlertHandler(new CollectingAlertHandler(
0324: collectedAlerts));
0325:
0326: final HtmlPage page = (HtmlPage) client.getPage(URL_GARGOYLE);
0327: final HtmlScript htmlScript = (HtmlScript) page
0328: .getHtmlElementById("script1");
0329: assertNotNull(htmlScript);
0330: assertEquals(expectedAlerts, collectedAlerts);
0331: }
0332:
0333: /**
0334: * Test that the url of the page containing the script is contained in the exception's message
0335: * @throws Exception if the test fails
0336: */
0337: public void testScriptErrorContainsPageUrl() throws Exception {
0338: // embedded script
0339: final String content1 = "<html><head><script>a.foo</script>\n"
0340: + "</head><body>\n" + "</body></html>";
0341:
0342: try {
0343: loadPage(content1);
0344: } catch (final Exception e) {
0345: assertTrue(e.getMessage().indexOf(URL_GARGOYLE.toString()) > -1);
0346: }
0347:
0348: // external script
0349: final WebClient client = new WebClient();
0350: final MockWebConnection webConnection = new MockWebConnection(
0351: client);
0352:
0353: final String content2 = "<html><head><title>foo</title><script src='/foo.js'/>\n"
0354: + "</head><body>\n" + "</body></html>";
0355:
0356: final String jsContent = "a.foo = 213;\n";
0357:
0358: webConnection.setResponse(URL_GARGOYLE, content2);
0359: final URL urlScript = new URL(
0360: "http://www.gargoylesoftware.com/foo.js");
0361: webConnection.setResponse(urlScript, jsContent,
0362: "text/javascript");
0363: client.setWebConnection(webConnection);
0364:
0365: try {
0366: client.getPage(URL_GARGOYLE);
0367: } catch (final Exception e) {
0368: assertTrue(e.getMessage(), e.getMessage().indexOf(
0369: urlScript.toString()) > -1);
0370: }
0371: }
0372:
0373: /**
0374: * @throws Exception if the test fails
0375: */
0376: public void testExternalScriptEncoding() throws Exception {
0377: final WebClient client = new WebClient();
0378: final MockWebConnection webConnection = new MockWebConnection(
0379: client);
0380: /*
0381: * this page has meta element , and script tag has no charset attribute
0382: */
0383: final String htmlContent = "<html><head>\n"
0384: + "<meta http-equiv='content-type' content='text/html; charset=Shift_JIS'>\n"
0385: + "<title>foo</title>\n"
0386: + "<script src='/foo.js' id='script1'/>\n"
0387: + "</head><body>\n"
0388: + "<p>hello world</p>\n"
0389: + "<form name='form1'>\n"
0390: + " <input type='text' name='textfield1' id='textfield1' value='foo' />\n"
0391: + " <input type='text' name='textfield2' id='textfield2'/>\n"
0392: + "</form>\n" + "</body></html>";
0393:
0394: /*
0395: * this page has no meta element , and script tag has charset attribute
0396: */
0397: final String htmlContent2 = "<html><head>\n"
0398: + "<title>foo</title>\n"
0399: + "<script src='/foo2.js' charset='Shift_JIS' id='script2'/>\n"
0400: + "</head><body>\n"
0401: + "<p>hello world</p>\n"
0402: + "<form name='form1'>\n"
0403: + " <input type='text' name='textfield1' id='textfield1' value='foo' />\n"
0404: + " <input type='text' name='textfield2' id='textfield2'/>\n"
0405: + "</form>\n" + "</body></html>";
0406:
0407: /*
0408: * the corresponding SJIS char of '\u8868' has '\' in second byte.
0409: * if encoding is misspecificated,
0410: * this cause 'unterminated string reteral error'
0411: */
0412: final String jsContent = "alert('\u8868');\n";
0413:
0414: webConnection.setResponse(URL_GARGOYLE, htmlContent);
0415:
0416: webConnection
0417: .setResponse(new URL(
0418: "http://www.gargoylesoftware.com/hidden"),
0419: htmlContent2);
0420:
0421: webConnection.setResponse(new URL(
0422: "http://www.gargoylesoftware.com/foo.js"),
0423: // make SJIS bytes as responsebody
0424: new String(jsContent.getBytes("SJIS"), "8859_1"),
0425: "text/javascript");
0426:
0427: /*
0428: * foo2.js is same with foo.js
0429: */
0430: webConnection.setResponse(new URL(
0431: "http://www.gargoylesoftware.com/foo2.js"),
0432: // make SJIS bytes as responsebody
0433: new String(jsContent.getBytes("SJIS"), "8859_1"),
0434: "text/javascript");
0435:
0436: client.setWebConnection(webConnection);
0437:
0438: final String[] expectedAlerts = { "\u8868" };
0439: final List collectedAlerts = new ArrayList();
0440: client.setAlertHandler(new CollectingAlertHandler(
0441: collectedAlerts));
0442:
0443: /*
0444: * detect encoding from meta tag
0445: */
0446: final HtmlPage page = (HtmlPage) client.getPage(URL_GARGOYLE);
0447: final HtmlScript htmlScript = (HtmlScript) page
0448: .getHtmlElementById("script1");
0449:
0450: assertNotNull(htmlScript);
0451: assertEquals(expectedAlerts, collectedAlerts);
0452:
0453: /*
0454: * detect encoding from charset attribute of script tag
0455: */
0456: collectedAlerts.clear();
0457: final HtmlPage page2 = (HtmlPage) client
0458: .getPage("http://www.gargoylesoftware.com/hidden");
0459: final HtmlScript htmlScript2 = (HtmlScript) page2
0460: .getHtmlElementById("script2");
0461:
0462: assertNotNull(htmlScript2);
0463: assertEquals(expectedAlerts, collectedAlerts);
0464: }
0465:
0466: /**
0467: * Set value on input expects a string. If you pass in a value that isn't a string
0468: * this used to blow up.
0469: * @throws Exception if the test fails
0470: */
0471: public void testSetValuesThatAreNotStrings() throws Exception {
0472: final String content = "<html><head><title>foo</title><script>\n"
0473: + "function doTest() {\n"
0474: + " document.form1.textfield1.value=1;\n"
0475: + " alert(document.form1.textfield1.value)\n"
0476: + "}\n"
0477: + "</script></head><body onload='doTest()'>\n"
0478: + "<p>hello world</p>\n"
0479: + "<form name='form1'>\n"
0480: + " <input type='text' name='textfield1' id='textfield1' value='foo' />\n"
0481: + " <input type='text' name='textfield2' id='textfield2'/>\n"
0482: + "</form>\n" + "</body></html>";
0483: final List collectedAlerts = new ArrayList();
0484: final HtmlPage page = loadPage(content, collectedAlerts);
0485: assertEquals("foo", page.getTitleText());
0486:
0487: final String[] expectedAlerts = { "1" };
0488: assertEquals(expectedAlerts, collectedAlerts);
0489: }
0490:
0491: /**
0492: * @throws Exception if the test fails
0493: */
0494: public void testReferencingVariablesFromOneScriptToAnother_Regression()
0495: throws Exception {
0496: final WebClient client = new WebClient();
0497: final MockWebConnection webConnection = new MockWebConnection(
0498: client);
0499:
0500: final String htmlContent = "<html><head><title>foo</title><script src='./test.js'></script>\n"
0501: + "<script>var testLocalVariable = new Array();</script>\n"
0502: + "</head><body onload='testNestedMethod();' >\n"
0503: + "<form name='form1' method='POST' action='../foo' >\n"
0504: + " <input type='submit' value='Login' name='loginButton'>\n"
0505: + "</form></body></html>";
0506:
0507: final String jsContent = "function testNestedMethod() {\n"
0508: + " if (testLocalVariable == null)\n"
0509: + " testLocalVariable = 'foo';\n" + "} ";
0510:
0511: webConnection.setResponse(URL_FIRST, htmlContent);
0512: webConnection.setResponse(new URL("http://first/test.js"),
0513: jsContent, "text/javascript");
0514: client.setWebConnection(webConnection);
0515:
0516: final HtmlPage page = (HtmlPage) client.getPage(URL_FIRST);
0517: assertEquals("foo", page.getTitleText());
0518:
0519: }
0520:
0521: /**
0522: * @throws Exception if the test fails
0523: */
0524: public void testJavaScriptUrl() throws Exception {
0525: final String htmlContent = "<html><head><script language='javascript'>\n"
0526: + "var f1 = '<html><head><title>frame1</title></head><body><h1>frame1</h1></body></html>';\n"
0527: + "var f2 = '<html><head><title>frame2</title></head><body><h1>frame2</h1></body></html>';\n"
0528: + "</script></head>\n"
0529: + "<frameset border='0' frameborder='0' framespacing='0' rows='100,*'>\n"
0530: + " <frame id='frame1' src='javascript:parent.f1'/>\n"
0531: + " <frame id='frame2' src='javascript:parent.f2'/>\n"
0532: + "</frameset></html>";
0533:
0534: createTestPageForRealBrowserIfNeeded(htmlContent,
0535: Collections.EMPTY_LIST);
0536: final HtmlPage page = loadPage(htmlContent);
0537:
0538: final HtmlPage page1 = (HtmlPage) ((HtmlFrame) page
0539: .getHtmlElementById("frame1")).getEnclosedPage();
0540: final HtmlPage page2 = (HtmlPage) ((HtmlFrame) page
0541: .getHtmlElementById("frame2")).getEnclosedPage();
0542:
0543: assertNotNull("page1", page1);
0544: assertNotNull("page2", page2);
0545:
0546: assertEquals("frame1", page1.getTitleText());
0547: assertEquals("frame2", page2.getTitleText());
0548: }
0549:
0550: /**
0551: * @throws Exception if the test fails
0552: */
0553: public void testJavaScriptWrappedInHtmlComments() throws Exception {
0554: final String htmlContent = "<html><head><title>foo</title><script language='javascript'><!--\n"
0555: + "function doTest() {\n"
0556: + "}\n"
0557: + "-->\n</script></head>\n"
0558: + "<body onload='doTest()'></body></html>";
0559: final HtmlPage page = loadPage(htmlContent);
0560: assertEquals("foo", page.getTitleText());
0561: }
0562:
0563: /**
0564: * @throws Exception if the test fails
0565: */
0566: public void testJavaScriptWrappedInHtmlComments2() throws Exception {
0567: final String content = "<html><head>\n" + "<script><!-- \n"
0568: + " alert('1')\n" + "--></script>\n" + "</head>\n"
0569: + "<body>\n" + "</body></html>";
0570:
0571: final String[] expectedAlerts = { "1" };
0572: final List collectedAlerts = new ArrayList();
0573: loadPage(content, collectedAlerts);
0574: assertEquals(expectedAlerts, collectedAlerts);
0575: }
0576:
0577: /**
0578: * @throws Exception if the test fails
0579: */
0580: public void testJavaScriptWrappedInHtmlComments_commentOnOpeningLine()
0581: throws Exception {
0582: final String htmlContent = "<html><head><title>foo</title><script language='javascript'><!-- Some comment here\n"
0583: + "function doTest() {\n"
0584: + "}\n"
0585: + "-->\n</script></head>\n"
0586: + "<body onload='doTest()'></body></html>";
0587:
0588: final HtmlPage page = loadPage(htmlContent);
0589: assertEquals("foo", page.getTitleText());
0590: }
0591:
0592: /**
0593: * Regression test for bug 1714762
0594: * @throws Exception if the test fails
0595: */
0596: public void testJavaScriptWrappedInHtmlComments_commentNotClosed()
0597: throws Exception {
0598: final String html = "<html><head><title>foo</title>\n"
0599: + "<script language='javascript'><!-- alert(1);</script>\n"
0600: + "<script language='javascript'><!-- </script>\n"
0601: + "</head>\n" + "<body></body></html>";
0602:
0603: final String[] expectedAlerts = {};
0604: createTestPageForRealBrowserIfNeeded(html, expectedAlerts);
0605:
0606: final List collectedAlerts = new ArrayList();
0607: loadPage(html, collectedAlerts);
0608:
0609: assertEquals(expectedAlerts, collectedAlerts);
0610: }
0611:
0612: /**
0613: * @throws Exception If the test fails.
0614: */
0615: public void testJavaScriptWrappedInHtmlComments_allOnOneLine()
0616: throws Exception {
0617: final String content = "<html>\n"
0618: + " <head>\n"
0619: + " <title>test</title>\n"
0620: + " <script>var test;</script>\n"
0621: + " <!-- var test should be undefined since it's on first line -->\n"
0622: + " <!-- but there should be no index out of bounds exception -->\n"
0623: + " <script> <!-- test = 'abc'; // --> </script>\n"
0624: + " </head>\n" + " <body onload='alert(test)'>\n"
0625: + " </body>\n" + "</html>";
0626: final List collectedAlerts = new ArrayList();
0627: loadPage(content, collectedAlerts);
0628: final String[] expectedAlerts = { "undefined" };
0629: assertEquals(expectedAlerts, collectedAlerts);
0630: }
0631:
0632: /**
0633: * @throws Exception if the test fails
0634: */
0635: public void testEventHandlerWithComment() throws Exception {
0636: final String content = "<html><body onLoad='alert(\"test\"); // xxx'></body></html>";
0637: final String[] expectedAlerts = { "test" };
0638: final List collectedAlerts = new ArrayList();
0639: loadPage(content, collectedAlerts);
0640: assertEquals(expectedAlerts, collectedAlerts);
0641: }
0642:
0643: /**
0644: * When using the syntax this.something in an onclick handler, "this" must represent
0645: * the object being clicked, not the window. Regression test.
0646: * @throws Exception if the test fails
0647: */
0648: public void testThisDotInOnClick() throws Exception {
0649: final String htmlContent = "<html><head><title>First</title><script>function foo(message){alert(message);}</script><body>\n"
0650: + "<form name='form1'><input type='submit' name='button1' onClick='foo(this.name)'></form>\n"
0651: + "</body></html>";
0652:
0653: final List collectedAlerts = new ArrayList();
0654: final HtmlPage page = loadPage(htmlContent, collectedAlerts);
0655: assertEquals("First", page.getTitleText());
0656:
0657: ((HtmlSubmitInput) page.getFormByName("form1").getInputByName(
0658: "button1")).click();
0659:
0660: final String[] expectedAlerts = { "button1" };
0661: assertEquals(expectedAlerts, collectedAlerts);
0662: }
0663:
0664: /**
0665: * @throws Exception if the test fails
0666: */
0667: public void testFunctionDefinedInExternalFile_CalledFromInlineScript()
0668: throws Exception {
0669: final WebClient client = new WebClient();
0670: final MockWebConnection webConnection = new MockWebConnection(
0671: client);
0672:
0673: final String htmlContent = "<html><head><title>foo</title><script src='./test.js'></script>\n"
0674: + "</head><body>\n"
0675: + " <script>externalMethod()</script>\n"
0676: + "</body></html>";
0677:
0678: final String jsContent = "function externalMethod() {\n"
0679: + " alert('Got to external method');\n" + "} ";
0680:
0681: webConnection.setResponse(new URL("http://first/index.html"),
0682: htmlContent);
0683: webConnection.setResponse(new URL("http://first/test.js"),
0684: jsContent, "text/javascript");
0685: client.setWebConnection(webConnection);
0686:
0687: final List collectedAlerts = new ArrayList();
0688: client.setAlertHandler(new CollectingAlertHandler(
0689: collectedAlerts));
0690:
0691: final HtmlPage page = (HtmlPage) client
0692: .getPage("http://first/index.html");
0693: assertEquals("foo", page.getTitleText());
0694: assertEquals(new String[] { "Got to external method" },
0695: collectedAlerts);
0696: }
0697:
0698: /**
0699: * Regression test for https://sourceforge.net/tracker/?func=detail&atid=448266&aid=1552746&group_id=47038
0700: * @throws Exception if the test fails
0701: */
0702: public void testExternalScriptWithNewLineBeforeClosingScriptTag()
0703: throws Exception {
0704: final WebClient client = new WebClient();
0705: final MockWebConnection webConnection = new MockWebConnection(
0706: client);
0707:
0708: final String htmlContent = "<html><head><title>foo</title>\n"
0709: + "</head><body>\n"
0710: + "<script src='test.js'>\n</script>\n" // \n between opening and closing tag is important
0711: + "</body></html>";
0712:
0713: final String jsContent = "function externalMethod() {\n"
0714: + " alert('Got to external method');\n" + "} \n"
0715: + "externalMethod();\n";
0716:
0717: webConnection.setResponse(URL_FIRST, htmlContent);
0718: webConnection.setDefaultResponse(jsContent, 200, "OK",
0719: "text/javascript");
0720: client.setWebConnection(webConnection);
0721:
0722: final List collectedAlerts = new ArrayList();
0723: client.setAlertHandler(new CollectingAlertHandler(
0724: collectedAlerts));
0725:
0726: client.getPage(URL_FIRST);
0727: assertEquals(new String[] { "Got to external method" },
0728: collectedAlerts);
0729: }
0730:
0731: /**
0732: * Test case for bug 707134. Currently I am unable to reproduce the problem.
0733: * @throws Exception if the test fails
0734: */
0735: public void testFunctionDefinedInSameFile() throws Exception {
0736: final String htmlContent = "<html><head><title>First</title><script>\n"
0737: + "function showFoo(foo) {\n"
0738: + " alert('Foo is: |' + foo + '|');\n"
0739: + "}\n"
0740: + "</script>\n"
0741: + "</head><body><form name='form1'>\n"
0742: + "<input name='text1' type='text'>\n"
0743: + "<input name='button1' type='button' onclick='showFoo(document.form1.text1.value);'>\n"
0744: + "</form></body></html>";
0745:
0746: final List collectedAlerts = new ArrayList();
0747:
0748: final HtmlPage page = loadPage(htmlContent, collectedAlerts);
0749: assertEquals("First", page.getTitleText());
0750:
0751: final HtmlForm form = page.getFormByName("form1");
0752: final HtmlTextInput textInput = (HtmlTextInput) form
0753: .getInputByName("text1");
0754: textInput.setValueAttribute("flintstone");
0755:
0756: final HtmlButtonInput button = (HtmlButtonInput) form
0757: .getInputByName("button1");
0758: assertEquals(Collections.EMPTY_LIST, collectedAlerts);
0759:
0760: button.click();
0761:
0762: assertEquals(new String[] { "Foo is: |flintstone|" },
0763: collectedAlerts);
0764: }
0765:
0766: /**
0767: * Test that the javascript engine gets called correctly for variable access.
0768: * @throws Exception If the test fails
0769: */
0770: public void testJavaScriptEngineCallsForVariableAccess()
0771: throws Exception {
0772: final WebClient client = new WebClient();
0773: final MockWebConnection webConnection = new MockWebConnection(
0774: client);
0775:
0776: final List collectedAlerts = new ArrayList();
0777: client.setAlertHandler(new CollectingAlertHandler(
0778: collectedAlerts));
0779:
0780: final String content = "<html><head><title>foo</title><script>\n"
0781: + "myDate = 'foo';\n"
0782: + "function doUnqualifiedVariableAccess() {\n"
0783: + " alert('unqualified: ' + myDate);\n"
0784: + "}\n"
0785: + "function doQualifiedVariableAccess() {\n"
0786: + " alert('qualified: ' + window.myDate);\n"
0787: + "}\n"
0788: + "</script></head><body>\n"
0789: + "<p>hello world</p>\n"
0790: + "<a id='unqualified' onclick='doUnqualifiedVariableAccess();'>unqualified</a>\n"
0791: + "<a id='qualified' onclick='doQualifiedVariableAccess();'>qualified</a>\n"
0792: + "</body></html>";
0793:
0794: webConnection.setDefaultResponse(content);
0795: client.setWebConnection(webConnection);
0796: final CountingJavaScriptEngine countingJavaScriptEngine = new CountingJavaScriptEngine(
0797: client);
0798: client.setJavaScriptEngine(countingJavaScriptEngine);
0799:
0800: final HtmlPage page = (HtmlPage) client.getPage(URL_GARGOYLE);
0801:
0802: assertEquals(1, countingJavaScriptEngine.getExecutionCount());
0803: assertEquals(0, countingJavaScriptEngine.getCallCount());
0804:
0805: ((HtmlAnchor) page.getHtmlElementById("unqualified")).click();
0806: assertEquals(1, countingJavaScriptEngine.getExecutionCount());
0807: assertEquals(1, countingJavaScriptEngine.getCallCount());
0808:
0809: ((HtmlAnchor) page.getHtmlElementById("qualified")).click();
0810: assertEquals(1, countingJavaScriptEngine.getExecutionCount());
0811: assertEquals(2, countingJavaScriptEngine.getCallCount());
0812:
0813: final String[] expectedAlerts = { "unqualified: foo",
0814: "qualified: foo" };
0815: assertEquals(expectedAlerts, collectedAlerts);
0816: }
0817:
0818: /**
0819: * ActiveX related exceptions that do not require a map
0820: * @throws Exception If the test fails
0821: */
0822: public void testActiveXObjectNoMap() throws Exception {
0823: try {
0824: loadPage(getJavaScriptContent("new ActiveXObject()"));
0825: fail("An exception should be thrown for zero argument constructor.");
0826: } catch (final ScriptException e) {
0827: // Success
0828: }
0829:
0830: try {
0831: loadPage(getJavaScriptContent("new ActiveXObject(1, '2', '3')"));
0832: fail("An exception should be thrown for a three argument constructor.");
0833: } catch (final ScriptException e) {
0834: // Success
0835: }
0836:
0837: try {
0838: loadPage(getJavaScriptContent("new ActiveXObject(a)"));
0839: fail("An exception should be thrown for an undefined parameter in the constructor.");
0840: } catch (final ScriptException e) {
0841: // Success
0842: }
0843:
0844: try {
0845: loadPage(getJavaScriptContent("new ActiveXObject(10)"));
0846: fail("An exception should be thrown for an integer parameter in the constructor.");
0847: } catch (final ScriptException e) {
0848: // Success
0849: }
0850:
0851: try {
0852: loadPage(getJavaScriptContent("new ActiveXObject('UnknownObject')"));
0853: fail("An exception should be thrown for a null map.");
0854: } catch (final ScriptException e) {
0855: // Success
0856: }
0857: }
0858:
0859: /**
0860: * Test that Java objects placed in the active x map can be instantiated and used within
0861: * javascript using the IE specific ActiveXObject constructor.
0862: * @throws Exception If the test fails
0863: */
0864: public void testActiveXObjectWithMap() throws Exception {
0865: final Map activexToJavaMapping = new HashMap();
0866: activexToJavaMapping
0867: .put("MockActiveXObject",
0868: "com.gargoylesoftware.htmlunit.javascript.MockActiveXObject");
0869: activexToJavaMapping
0870: .put("FakeObject",
0871: "com.gargoylesoftware.htmlunit.javascript.NoSuchObject");
0872: activexToJavaMapping.put("BadObject", new Object());
0873:
0874: final WebClient client = new WebClient();
0875: final MockWebConnection webConnection = new MockWebConnection(
0876: client);
0877: client.setWebConnection(webConnection);
0878: client.setActiveXObjectMap(activexToJavaMapping);
0879: final List collectedAlerts = new ArrayList();
0880: client.setAlertHandler(new CollectingAlertHandler(
0881: collectedAlerts));
0882:
0883: webConnection
0884: .setDefaultResponse(getJavaScriptContent("new ActiveXObject('UnknownObject')"));
0885: try {
0886: client.getPage("http://www.yahoo.com");
0887: fail("An exception should be thrown for non existent object in the map.");
0888: } catch (final ScriptException e) {
0889: // Success
0890: }
0891:
0892: webConnection
0893: .setDefaultResponse(getJavaScriptContent("new ActiveXObject('BadObject', 'server')"));
0894: try {
0895: client.getPage("http://www.yahoo.com");
0896: fail("An exception should be thrown for an invalid object in the map.");
0897: } catch (final ScriptException e) {
0898: // Success
0899: }
0900:
0901: // Test for a non existent class in the map
0902: webConnection
0903: .setDefaultResponse(getJavaScriptContent("new ActiveXObject('FakeObject')"));
0904: try {
0905: client.getPage("http://www.yahoo.com");
0906: fail("An exception should be thrown for a non existent object in the map.");
0907: } catch (final ScriptException e) {
0908: // Success
0909: }
0910:
0911: assertEquals("should no alerts yet", Collections.EMPTY_LIST,
0912: collectedAlerts);
0913:
0914: // Try a valid object in the map
0915: webConnection
0916: .setDefaultResponse(getJavaScriptContent("var t = new ActiveXObject('MockActiveXObject'); alert(t.MESSAGE);\n"));
0917: client.getPage("http://www.yahoo.com");
0918: assertEquals("The active x object did not bind to the object.",
0919: new String[] { MockActiveXObject.MESSAGE },
0920: collectedAlerts);
0921:
0922: collectedAlerts.clear();
0923:
0924: webConnection
0925: .setDefaultResponse(getJavaScriptContent("var t = new ActiveXObject('MockActiveXObject', 'server'); alert(t.GetMessage());\n"));
0926: client.getPage("http://www.yahoo.com");
0927: assertEquals("The active x object did not bind to the object.",
0928: new String[] { new MockActiveXObject().GetMessage() },
0929: collectedAlerts);
0930: }
0931:
0932: private String getJavaScriptContent(final String javascript) {
0933: return "<html><head><title>foo</title><script>\n"
0934: + javascript
0935: + "</script></head><body>\n"
0936: + "<p>hello world</p>\n"
0937: + "<form name='form1'>\n"
0938: + " <input type='text' name='textfield1' id='textfield1' value='foo' />\n"
0939: + " <input type='text' name='textfield2' id='textfield2'/>\n"
0940: + "</form>\n" + "</body></html>";
0941: }
0942:
0943: /**
0944: * Check that wrong javascript just causes its context to fail but not the whole page.
0945: * @throws Exception If something goes wrong.
0946: */
0947: public void testScriptErrorIsolated() throws Exception {
0948: final String content = "<html>\n" + "<head>\n"
0949: + "<script>alert(1);</script>\n"
0950: + "<script>alert(2</script>\n"
0951: + "<script>alert(3);</script>\n" + "</head>\n"
0952: + "<body onload='alert(4);notExisting()'>\n"
0953: + "<button onclick='alert(5)'>click me</button>\n"
0954: + "</body>\n" + "</html>";
0955:
0956: final String[] expectedAlerts = { "1", "3", "4" };
0957: createTestPageForRealBrowserIfNeeded(content, expectedAlerts);
0958:
0959: final WebClient client = new WebClient();
0960: final MockWebConnection webConnection = new MockWebConnection(
0961: client);
0962: webConnection.setDefaultResponse(content);
0963: client.setWebConnection(webConnection);
0964: final List collectedAlerts = new ArrayList();
0965: client.setAlertHandler(new CollectingAlertHandler(
0966: collectedAlerts));
0967:
0968: // first test with script exceptions thrown
0969: try {
0970: client.getPage(URL_FIRST);
0971: fail("Should have thrown a script error");
0972: } catch (final Exception e) {
0973: // nothing
0974: }
0975: assertEquals(new String[] { "1" }, collectedAlerts);
0976: collectedAlerts.clear();
0977:
0978: // and with script exception not thrown
0979: client.setThrowExceptionOnScriptError(false);
0980: client.getPage(URL_FIRST);
0981:
0982: assertEquals(expectedAlerts, collectedAlerts);
0983: }
0984:
0985: /**
0986: * Test that prototype changes are made in the right scope.
0987: * Problem reported by Bruce Faulnker in the dev mailing list.
0988: * This is due to a Rhino bug:
0989: * https://bugzilla.mozilla.org/show_bug.cgi?id=374918
0990: * @throws Exception If something goes wrong.
0991: */
0992: public void testPrototypeScope() throws Exception {
0993: final String content1 = "<html><head>\n" + "<script>\n"
0994: + "window.open('second.html', 'secondWindow');\n"
0995: + "</script>\n" + "</head><body></body></html>";
0996:
0997: final String content2 = "<html><head>\n" + "<script>\n"
0998: + "alert('in page 2');\n"
0999: + "String.prototype.foo = function()\n" + "{\n"
1000: + " alert('in foo');\n" + "};\n"
1001: + "var testString = 'some string';\n"
1002: + "testString.foo();\n" + "</script>\n"
1003: + "</head><body></body></html>";
1004:
1005: final String[] expectedAlerts = { "in page 2", "in foo" };
1006:
1007: final WebClient client = new WebClient();
1008: final MockWebConnection webConnection = new MockWebConnection(
1009: client);
1010: webConnection.setDefaultResponse(content2);
1011: webConnection.setResponse(URL_FIRST, content1);
1012: client.setWebConnection(webConnection);
1013:
1014: final List collectedAlerts = new ArrayList();
1015: client.setAlertHandler(new CollectingAlertHandler(
1016: collectedAlerts));
1017:
1018: client.getPage(URL_FIRST);
1019: assertEquals(expectedAlerts, collectedAlerts);
1020: }
1021:
1022: /**
1023: * @throws Exception If the test fails
1024: */
1025: public void testTimeout() throws Exception {
1026: final long timeout = 2000;
1027: final long oldTimeout = JavaScriptEngine.getTimeout();
1028: JavaScriptEngine.setTimeout(timeout);
1029:
1030: try {
1031: final WebClient client = new WebClient();
1032: client.setThrowExceptionOnScriptError(false);
1033:
1034: final String content = "<html><body><script>while(1) {}</script></body></html>";
1035: final MockWebConnection webConnection = new MockWebConnection(
1036: client);
1037: webConnection.setDefaultResponse(content);
1038: client.setWebConnection(webConnection);
1039:
1040: final Exception[] exceptions = { null };
1041: final Thread runner = new Thread() {
1042: public void run() {
1043: try {
1044: client.getPage(URL_FIRST);
1045: } catch (final Exception e) {
1046: exceptions[0] = e;
1047: }
1048: }
1049: };
1050:
1051: runner.start();
1052:
1053: runner.join(timeout * 2);
1054: if (runner.isAlive()) {
1055: runner.interrupt();
1056: fail("Script was still running after timeout");
1057: }
1058: assertNull(exceptions[0]);
1059: } finally {
1060: JavaScriptEngine.setTimeout(oldTimeout);
1061: }
1062: }
1063:
1064: private static final class CountingJavaScriptEngine extends
1065: JavaScriptEngine {
1066: private static final long serialVersionUID = 7010508171587446215L;
1067: private int scriptExecutionCount_ = 0;
1068: private int scriptCallCount_ = 0;
1069: private int scriptCompileCount_ = 0;
1070: private int scriptExecuteScriptCount_ = 0;
1071:
1072: /**
1073: * Create an instance
1074: * @param client the WebClient
1075: */
1076: protected CountingJavaScriptEngine(final WebClient client) {
1077: super (client);
1078: }
1079:
1080: /** @inheritDoc ScriptEngine#execute(HtmlPage,String,String,int) */
1081: public Object execute(final HtmlPage htmlPage,
1082: final String sourceCode, final String sourceName,
1083: final int startLine) {
1084: scriptExecutionCount_++;
1085: return super .execute(htmlPage, sourceCode, sourceName,
1086: startLine);
1087: }
1088:
1089: /** @inheritDoc ScriptEngine#execute(HtmlPage,Script) */
1090: public Object execute(final HtmlPage htmlPage,
1091: final Script script) {
1092: scriptExecuteScriptCount_++;
1093: return super .execute(htmlPage, script);
1094: }
1095:
1096: /** @inheritDoc ScriptEngine#compile(HtmlPage,String,String,int) */
1097: public Script compile(final HtmlPage htmlPage,
1098: final String sourceCode, final String sourceName,
1099: final int startLine) {
1100: scriptCompileCount_++;
1101: return super .compile(htmlPage, sourceCode, sourceName,
1102: startLine);
1103: }
1104:
1105: /** @inheritDoc ScriptEngine#callFunction(HtmlPage,Object,Object,Object[],HtmlElement) */
1106: public Object callFunction(final HtmlPage htmlPage,
1107: final Object javaScriptFunction,
1108: final Object this Object, final Object[] args,
1109: final DomNode htmlElementScope) {
1110: scriptCallCount_++;
1111: return super .callFunction(htmlPage, javaScriptFunction,
1112: this Object, args, htmlElementScope);
1113: }
1114:
1115: /** @return The number of times that this engine has called functions */
1116: public int getCallCount() {
1117: return scriptCallCount_;
1118: }
1119:
1120: /** @return The number of times that this engine has executed code */
1121: public int getExecutionCount() {
1122: return scriptExecutionCount_;
1123: }
1124:
1125: /** @return The number of times that this engine has compiled code */
1126: public int getCompileCount() {
1127: return scriptCompileCount_;
1128: }
1129:
1130: /** @return The number of times that this engine has executed a compiled script */
1131: public int getExecuteScriptCount() {
1132: return scriptExecuteScriptCount_;
1133: }
1134: }
1135:
1136: /**
1137: * @throws Exception If the test fails
1138: */
1139: public void testCommentNoDoubleSlashIE() throws Exception {
1140: final String content = "<html><head>\n"
1141: + "<script><!-- alert(1);\n" + " alert(2);\n"
1142: + "alert(3) --></script>\n" + "</head>\n" + "<body>\n"
1143: + "</body></html>";
1144:
1145: final String[] expectedAlert = { "2" };
1146: final List collectedAlerts = new ArrayList();
1147: loadPage(content, collectedAlerts);
1148: assertEquals(expectedAlert, collectedAlerts);
1149: }
1150:
1151: /**
1152: * @throws Exception If the test fails
1153: */
1154: public void testCommentNoDoubleSlashFF() throws Exception {
1155: final String content = "<html><head>\n"
1156: + "<script><!-- alert(1);\n" + " alert(2);\n"
1157: + "alert(3) -->\n</script>\n" + "</head>\n"
1158: + "<body>\n" + "</body></html>";
1159:
1160: final List collectedAlerts = new ArrayList();
1161: try {
1162: loadPage(BrowserVersion.FIREFOX_2, content, collectedAlerts);
1163: fail();
1164: } catch (final ScriptException e) {
1165: assertEquals(4, e.getFailingLineNumber());
1166: }
1167: }
1168:
1169: /**
1170: * @throws Exception If the test fails
1171: */
1172: public void testComment() throws Exception {
1173: testComment(BrowserVersion.INTERNET_EXPLORER_6_0);
1174: testComment(BrowserVersion.FIREFOX_2);
1175: }
1176:
1177: /**
1178: * @throws Exception If the test fails
1179: */
1180: private void testComment(final BrowserVersion browserVersion)
1181: throws Exception {
1182: final String content = "<html><head>\n"
1183: + "<script><!-- alert(1);\n" + " alert(2);\n"
1184: + "alert(3)//--></script>\n" + "</head>\n" + "<body>\n"
1185: + "</body></html>";
1186:
1187: final String[] expectedAlert = { "2", "3" };
1188: final List collectedAlerts = new ArrayList();
1189: loadPage(content, collectedAlerts);
1190: assertEquals(expectedAlert, collectedAlerts);
1191: }
1192:
1193: /**
1194: * @throws Exception If the test fails
1195: */
1196: public void testRegExpSupport() throws Exception {
1197: final String html = "<html>\n"
1198: + " <head>\n"
1199: + " <title>test</title>\n"
1200: + " <script id='a'>\n"
1201: + " var s = new String('rstlne-rstlne-rstlne');\n"
1202: + " alert (s);\n"
1203: + " s = s.replace('e', 'o');\n"
1204: + " alert (s);\n"
1205: + " s = s.replace(/o/, 'a');\n"
1206: + " alert (s);\n"
1207: + " s = s.replace(new RegExp('a'), 'e');\n"
1208: + " alert (s);\n"
1209: + " s = s.replace(new RegExp('e', 'g'), 'i');\n"
1210: + " alert (s);\n"
1211: + " s = s.replace(/i/g, 'a');\n"
1212: + " alert (s);\n" + " </script>\n"
1213: + " </head>\n" + " <body>abc</body>\n" + "</html>";
1214:
1215: final List collectedAlerts = new ArrayList();
1216: loadPage(html, collectedAlerts);
1217:
1218: final String[] expectedAlerts = { "rstlne-rstlne-rstlne",
1219: "rstlno-rstlne-rstlne", "rstlna-rstlne-rstlne",
1220: "rstlne-rstlne-rstlne", "rstlni-rstlni-rstlni",
1221: "rstlna-rstlna-rstlna" };
1222:
1223: assertEquals(expectedAlerts, collectedAlerts);
1224: }
1225:
1226: /**
1227: * Test for Rhino bug https://bugzilla.mozilla.org/show_bug.cgi?id=374918
1228: * Once this bug is fixed, {@link StringPrimitivePrototypeBugFixer} can be completely removed
1229: * as well as this unit test.
1230: * Correct string primitive prototype resolution within HtmlUnit is tested
1231: * by {@link #testPrototypeScope()}
1232: */
1233: public void testStringPrimitivePrototypeScopeRhino() {
1234: if (notYetImplemented()) {
1235: return;
1236: }
1237: final Context cx = Context.enter();
1238: final Scriptable scope1 = cx.initStandardObjects();
1239: final Scriptable scope2 = cx.initStandardObjects();
1240: final String str2 = "function f() { String.prototype.foo = 'from 2'; \n"
1241: + "var s1 = new String('s1');\n"
1242: + "if (s1.foo != 'from 2') throw 's1 got: ' + s1.foo;\n" // works
1243: + "var s2 = 's2';\n"
1244: + "if (s2.foo != 'from 2') throw 's2 got: ' + s2.foo;\n" // fails
1245: + "}";
1246: cx.evaluateString(scope2, str2, "source2", 1, null);
1247:
1248: scope1.put("scope2", scope1, scope2);
1249:
1250: final String str1 = "String.prototype.foo = 'from 1'; scope2.f()";
1251: cx.evaluateString(scope1, str1, "source1", 1, null);
1252:
1253: Context.exit();
1254: }
1255:
1256: /**
1257: * Test ECMA reserved keywords... that are accepted by "normal" browsers
1258: * @throws Exception if the test fails
1259: */
1260: public void testECMAReservedKeywords() throws Exception {
1261: final String content = "<html><head><title>foo</title><script>\n"
1262: + "var o = {float: 123};"
1263: + "alert(o.float);"
1264: + "</script></head><body>\n" + "</body></html>";
1265:
1266: final String[] expectedAlerts = { "123" };
1267: createTestPageForRealBrowserIfNeeded(content, expectedAlerts);
1268: final List collectedAlerts = new ArrayList();
1269: loadPage(content, collectedAlerts);
1270:
1271: assertEquals(expectedAlerts, collectedAlerts);
1272: }
1273:
1274: /**
1275: * Test that compiled script are cached.
1276: * @throws Exception if the test fails
1277: */
1278: public void testCompiledScriptCached() throws Exception {
1279: final String content1 = "<html><head><title>foo</title>\n"
1280: + "<script src='script.js'></script>"
1281: + "</head><body>\n"
1282: + "<a href='page2.html'>to page 2</a>"
1283: + "</body></html>";
1284: final String content2 = "<html><head><title>page 2</title>\n"
1285: + "<script src='script.js'></script>\n"
1286: + "</head><body>\n" + "</body></html>";
1287: final String script = "alert(document.title)";
1288:
1289: final WebClient client = new WebClient();
1290: final MockWebConnection connection = new MockWebConnection(
1291: client);
1292: client.setWebConnection(connection);
1293: connection.setResponse(URL_FIRST, content1);
1294: connection.setResponse(new URL(URL_FIRST, "page2.html"),
1295: content2);
1296:
1297: final List headersAllowingCache = new ArrayList();
1298: headersAllowingCache.add(new NameValuePair("Last-Modified",
1299: "Sun, 15 Jul 2007 20:46:27 GMT"));
1300: connection.setResponse(new URL(URL_FIRST, "script.js"), script,
1301: 200, "ok", "text/javascript", headersAllowingCache);
1302:
1303: final CountingJavaScriptEngine countingJavaScriptEngine = new CountingJavaScriptEngine(
1304: client);
1305: client.setJavaScriptEngine(countingJavaScriptEngine);
1306:
1307: final List collectedAlerts = new ArrayList();
1308: client.setAlertHandler(new CollectingAlertHandler(
1309: collectedAlerts));
1310: final HtmlPage page1 = (HtmlPage) client.getPage(URL_FIRST);
1311: assertEquals(new String[] { "foo" }, collectedAlerts);
1312: assertEquals(1, countingJavaScriptEngine
1313: .getExecuteScriptCount());
1314: assertEquals(1, countingJavaScriptEngine.getCompileCount());
1315:
1316: collectedAlerts.clear();
1317: ((ClickableElement) page1.getAnchors().get(0)).click();
1318: assertEquals(new String[] { "page 2" }, collectedAlerts);
1319: assertEquals(2, countingJavaScriptEngine
1320: .getExecuteScriptCount());
1321: assertEquals(1, countingJavaScriptEngine.getCompileCount());
1322: }
1323:
1324: /**
1325: * Test that code in script tags is executed on page load. Try different combinations
1326: * of the script tag except for the case where a remote javascript page is loaded. That
1327: * one will be tested separately.
1328: * @throws Exception If something goes wrong.
1329: */
1330: public void testScriptTags_AllLocalContent() throws Exception {
1331: final String content = "<html>\n"
1332: + "<head><title>foo</title>\n"
1333: + "<script>One</script>\n" // no language specified - assume javascript
1334: + "<script language='javascript'>Two</script>\n"
1335: + "<script type='text/javascript'>Three</script>\n"
1336: + "<script type='text/perl'>Four</script>\n" // type is unsupported language
1337: + "</head>\n" + "<body>\n" + "<p>hello world</p>\n"
1338: + "</body></html>";
1339: final List collectedScripts = new ArrayList();
1340: loadPageAndCollectScripts(content, collectedScripts);
1341:
1342: // NO MORE: The last expected is the dummy stub that is needed to initialize the javascript engine
1343: final String[] expectedScripts = { "One", "Two", "Three" };
1344:
1345: assertEquals(expectedScripts, collectedScripts);
1346: }
1347:
1348: private HtmlPage loadPageAndCollectScripts(final String html,
1349: final List collectedScripts) throws Exception {
1350:
1351: final WebClient client = new WebClient();
1352: client.setJavaScriptEngine(new JavaScriptEngine(client) {
1353: private static final long serialVersionUID = -3069321085262318962L;
1354:
1355: public Object execute(final HtmlPage htmlPage,
1356: final String sourceCode, final String sourceName,
1357: final int startLine) {
1358: collectedScripts.add(sourceCode);
1359: return null;
1360: }
1361:
1362: public Object callFunction(final HtmlPage htmlPage,
1363: final Object javaScriptFunction,
1364: final Object this Object, final Object[] args,
1365: final DomNode htmlElement) {
1366: return null;
1367: }
1368:
1369: public boolean isScriptRunning() {
1370: return false;
1371: }
1372: });
1373:
1374: final MockWebConnection webConnection = new MockWebConnection(
1375: client);
1376:
1377: webConnection.setDefaultResponse(html);
1378: client.setWebConnection(webConnection);
1379:
1380: final HtmlPage page = (HtmlPage) client
1381: .getPage(new WebRequestSettings(URL_GARGOYLE,
1382: SubmitMethod.POST));
1383: return page;
1384: }
1385: }
|