001: /*
002: * Copyright (c) 2002-2008 Gargoyle Software Inc. All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * 1. Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: * 2. Redistributions in binary form must reproduce the above copyright notice,
010: * this list of conditions and the following disclaimer in the documentation
011: * and/or other materials provided with the distribution.
012: * 3. The end-user documentation included with the redistribution, if any, must
013: * include the following acknowledgment:
014: *
015: * "This product includes software developed by Gargoyle Software Inc.
016: * (http://www.GargoyleSoftware.com/)."
017: *
018: * Alternately, this acknowledgment may appear in the software itself, if
019: * and wherever such third-party acknowledgments normally appear.
020: * 4. The name "Gargoyle Software" must not be used to endorse or promote
021: * products derived from this software without prior written permission.
022: * For written permission, please contact info@GargoyleSoftware.com.
023: * 5. Products derived from this software may not be called "HtmlUnit", nor may
024: * "HtmlUnit" appear in their name, without prior written permission of
025: * Gargoyle Software Inc.
026: *
027: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
028: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
029: * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
030: * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
031: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
032: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
033: * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
034: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
035: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
036: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
037: */
038: package com.gargoylesoftware.htmlunit.javascript;
039:
040: import java.io.File;
041: import java.util.ArrayList;
042: import java.util.Collection;
043: import java.util.Collections;
044: import java.util.HashSet;
045: import java.util.List;
046: import java.util.Map;
047: import java.util.Set;
048: import java.util.TreeSet;
049:
050: import org.apache.commons.collections.CollectionUtils;
051: import org.apache.commons.collections.Transformer;
052: import org.apache.commons.lang.ClassUtils;
053:
054: import com.gargoylesoftware.htmlunit.CollectingAlertHandler;
055: import com.gargoylesoftware.htmlunit.MockWebConnection;
056: import com.gargoylesoftware.htmlunit.ScriptException;
057: import com.gargoylesoftware.htmlunit.WebClient;
058: import com.gargoylesoftware.htmlunit.WebTestCase;
059: import com.gargoylesoftware.htmlunit.html.HtmlPage;
060: import com.gargoylesoftware.htmlunit.javascript.configuration.JavaScriptConfiguration;
061:
062: /**
063: * Tests for {@link SimpleScriptable}.
064: *
065: * @version $Revision: 2157 $
066: * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
067: * @author <a href="mailto:BarnabyCourt@users.sourceforge.net">Barnaby Court</a>
068: * @author David K. Taylor
069: * @author <a href="mailto:bcurren@esomnie.com">Ben Curren</a>
070: * @author Marc Guillemot
071: * @author Chris Erskine
072: * @author Ahmed Ashour
073: */
074: public class SimpleScriptableTest extends WebTestCase {
075: /**
076: * Create an instance
077: * @param name The name of the test
078: */
079: public SimpleScriptableTest(final String name) {
080: super (name);
081: }
082:
083: /**
084: * @throws Exception if the test fails
085: */
086: public void testCallInheritedFunction() throws Exception {
087: final WebClient client = new WebClient();
088: final MockWebConnection webConnection = new MockWebConnection(
089: client);
090:
091: final String content = "<html><head><title>foo</title><script>"
092: + "function doTest() {\n"
093: + " document.form1.textfield1.focus();\n"
094: + " alert('past focus');\n"
095: + "}\n"
096: + "</script></head><body onload='doTest()'>"
097: + "<p>hello world</p>"
098: + "<form name='form1'>"
099: + " <input type='text' name='textfield1' id='textfield1' value='foo' />"
100: + "</form>" + "</body></html>";
101:
102: webConnection.setDefaultResponse(content);
103: client.setWebConnection(webConnection);
104:
105: final List expectedAlerts = Collections
106: .singletonList("past focus");
107: createTestPageForRealBrowserIfNeeded(content, expectedAlerts);
108:
109: final List collectedAlerts = new ArrayList();
110: client.setAlertHandler(new CollectingAlertHandler(
111: collectedAlerts));
112:
113: final HtmlPage page = (HtmlPage) client.getPage(URL_GARGOYLE);
114: assertEquals("foo", page.getTitleText());
115: assertEquals("focus not changed to textfield1", page
116: .getFormByName("form1").getInputByName("textfield1"),
117: page.getElementWithFocus());
118: assertEquals(expectedAlerts, collectedAlerts);
119: }
120:
121: /**
122: */
123: public void testHtmlJavaScriptMapping_AllJavaScriptClassesArePresent() {
124: final Map map = JavaScriptConfiguration
125: .getHtmlJavaScriptMapping();
126: final String directoryName = "../../../src/main/java/com/gargoylesoftware/htmlunit/javascript/host";
127: final Set names = getFileNames(directoryName.replace('/',
128: File.separatorChar));
129:
130: // Now pull out those names that we know don't have html equivalents
131: names.remove("ActiveXObject");
132: names.remove("BoxObject");
133: names.remove("Document");
134: names.remove("DOMImplementation");
135: names.remove("DOMParser");
136: names.remove("Event");
137: names.remove("EventHandler");
138: names.remove("EventListenersContainer");
139: names.remove("FormField");
140: names.remove("History");
141: names.remove("JavaScriptBackgroundJob");
142: names.remove("Location");
143: names.remove("MimeType");
144: names.remove("MimeTypeArray");
145: names.remove("MouseEvent");
146: names.remove("Navigator");
147: names.remove("Node");
148: names.remove("Plugin");
149: names.remove("PluginArray");
150: names.remove("Popup");
151: names.remove("Range");
152: names.remove("RowContainer");
153: names.remove("Screen");
154: names.remove("ScoperFunctionObject");
155: names.remove("SimpleArray");
156: names.remove("Style");
157: names.remove("Stylesheet");
158: names.remove("StyleSheetList");
159: names.remove("TextRectangle");
160: names.remove("UIEvent");
161: names.remove("Window");
162: names.remove("XMLDocument");
163: names.remove("XMLDOMParseError");
164: names.remove("XMLHttpRequest");
165: names.remove("XMLSerializer");
166: names.remove("XPathNSResolver");
167: names.remove("XPathResult");
168: names.remove("XSLTProcessor");
169: names.remove("XSLTemplate");
170:
171: final Transformer class2ShortName = new Transformer() {
172: public Object transform(final Object obj) {
173: return ClassUtils.getShortClassName((Class) obj);
174: }
175: };
176: final Collection hostClassNames = new ArrayList(map.values());
177: CollectionUtils.transform(hostClassNames, class2ShortName);
178: assertEquals(new TreeSet(names), new TreeSet(hostClassNames));
179: }
180:
181: private Set getFileNames(final String directoryName) {
182: File directory = new File("." + File.separatorChar
183: + directoryName);
184: if (!directory.exists()) {
185: directory = new File("./src/main/java/".replace('/',
186: File.separatorChar)
187: + directoryName);
188: }
189: assertTrue("directory exists", directory.exists());
190: assertTrue("is a directory", directory.isDirectory());
191:
192: final String fileNames[] = directory.list();
193: final Set collection = new HashSet();
194:
195: for (int i = 0; i < fileNames.length; i++) {
196: final String name = fileNames[i];
197: if (name.endsWith(".java")) {
198: collection.add(name.substring(0, name.length() - 5));
199: }
200: }
201: return collection;
202: }
203:
204: /**
205: * This test fails on IE and FF but not by HtmlUnit because according to Ecma standard,
206: * attempts to set read only properties should be silently ignored.
207: * Furthermore document.body = document.body will work on FF but not on IE
208: * @throws Exception if the test fails
209: */
210: public void testSetNonWritableProperty() throws Exception {
211: if (notYetImplemented()) {
212: return;
213: }
214: final String content = "<html><head><title>foo</title></head><body onload='document.body=123456'>"
215: + "</body></html>";
216:
217: try {
218: loadPage(content);
219: fail("Exception should have been thrown");
220: } catch (final ScriptException e) {
221: // it's ok
222: }
223: }
224:
225: /**
226: * @throws Exception if the test fails
227: */
228: public void testArguments_toString() throws Exception {
229: if (notYetImplemented()) {
230: return;
231: }
232: final String content = "<html><head><title>foo</title><script>\n"
233: + " function test() {\n"
234: + " alert(arguments);\n"
235: + " }\n"
236: + "</script></head><body onload='test()'>\n"
237: + "</body></html>";
238:
239: final String[] expectedAlerts = { "[object Object]" };
240: final List collectedAlerts = new ArrayList();
241: loadPage(content, collectedAlerts);
242: assertEquals(expectedAlerts, collectedAlerts);
243: }
244:
245: /**
246: * @throws Exception if the test fails
247: */
248: public void testStringWithExclamationMark() throws Exception {
249: if (notYetImplemented()) {
250: return;
251: }
252: final String content = "<html><head><title>foo</title><script>\n"
253: + " function test() {\n"
254: + " var x = '<!>';\n"
255: + " alert(x.length);\n"
256: + " }\n"
257: + "</script></head><body onload='test()'>\n"
258: + "</body></html>";
259:
260: final String[] expectedAlerts = { "3" };
261: final List collectedAlerts = new ArrayList();
262: loadPage(content, collectedAlerts);
263: assertEquals(expectedAlerts, collectedAlerts);
264: }
265: }
|