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.configuration;
039:
040: import java.io.FileNotFoundException;
041: import java.io.IOException;
042: import java.io.Reader;
043: import java.io.StringReader;
044: import java.lang.reflect.Field;
045: import java.lang.reflect.Method;
046: import java.util.HashMap;
047: import java.util.Iterator;
048:
049: import org.xml.sax.EntityResolver;
050: import org.xml.sax.ErrorHandler;
051: import org.xml.sax.InputSource;
052: import org.xml.sax.SAXException;
053: import org.xml.sax.SAXParseException;
054: import org.xml.sax.XMLReader;
055: import org.xml.sax.helpers.XMLReaderFactory;
056:
057: import com.gargoylesoftware.htmlunit.BrowserVersion;
058: import com.gargoylesoftware.htmlunit.WebTestCase;
059: import com.gargoylesoftware.htmlunit.javascript.host.Document;
060:
061: /**
062: * Tests for {@link JavaScriptConfiguration}.
063: *
064: * @version $Revision: 2157 $
065: * @author Chris Erskine
066: * @author Ahmed Ashour
067: */
068: public class JavaScriptConfigurationTest extends WebTestCase {
069: /**
070: * Create an instance
071: * @param name The name of the test
072: */
073: public JavaScriptConfigurationTest(final String name) {
074: super (name);
075: }
076:
077: /**
078: * Reset the JavaScriptConfiguration file for each test to it's initial clean state.
079: *
080: * @throws Exception if the test fails
081: */
082: protected void setUp() throws Exception {
083: super .setUp();
084: JavaScriptConfiguration.resetClassForTesting();
085: }
086:
087: /**
088: * Reset the JavaScriptConfiguration file for each test to it's initial clean state.
089: *
090: * @throws Exception if the test fails
091: */
092: protected void tearDown() throws Exception {
093: super .tearDown();
094: JavaScriptConfiguration.resetClassForTesting();
095: }
096:
097: /**
098: * Test loading a configuration from the supplied stream
099: *
100: */
101: public void testLoadLocalConfiguration() {
102: final String configurationString = "<?xml version=\"1.0\"?>\n"
103: + "<configuration\n"
104: + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
105: + " xsi:noNamespaceSchemaLocation=\"JavaScriptConfiguration.xsd\">\n"
106: + " <class name=\"Document\" "
107: + "classname=\"com.gargoylesoftware.htmlunit.javascript.host.Document\">\n"
108: + " <property name=\"readyState\" readable=\"true\" writable=\"false\">\n"
109: + " </property>\n" + " </class>\n"
110: + "</configuration>";
111: final Reader reader = new StringReader(configurationString);
112: assertFalse("Document should not be loaded",
113: JavaScriptConfiguration.isDocumentLoaded());
114: JavaScriptConfiguration.loadConfiguration(reader);
115: assertTrue("Documnet should now be loaded",
116: JavaScriptConfiguration.isDocumentLoaded());
117: }
118:
119: /**
120: * Test loading a configuration from the supplied stream
121: *
122: */
123: public void testLoadSystemConfigurationFile() {
124: assertFalse("Document should not be loaded",
125: JavaScriptConfiguration.isDocumentLoaded());
126: JavaScriptConfiguration.loadConfiguration();
127: assertTrue("Documnet should now be loaded",
128: JavaScriptConfiguration.isDocumentLoaded());
129: }
130:
131: /**
132: * Test getting the configuration for the full browser
133: *
134: * @throws Exception - Exception on error
135: */
136: public void testGetInstance() throws Exception {
137: final String configurationString = "<?xml version=\"1.0\"?>\n"
138: + "<configuration\n"
139: + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
140: + " xsi:noNamespaceSchemaLocation=\"JavaScriptConfiguration.xsd\">\n"
141: + " <class name=\"Document\" extends=\"Node\" "
142: + "classname=\"com.gargoylesoftware.htmlunit.javascript.host.Document\">\n"
143: + " <property name=\"readyState\" readable=\"true\" writable=\"false\">\n"
144: + " <browser name=\"Microsoft Internet Explorer\" min-version=\"4\"/>\n"
145: + " </property>\n"
146: + " </class>\n"
147: + " <class name=\"Node\" "
148: + "classname=\"com.gargoylesoftware.htmlunit.javascript.host.Node\">\n"
149: + " <property name=\"firstChild\" readable=\"true\" writable=\"false\">\n"
150: + " </property>\n" + " </class>\n"
151: + "</configuration>\n";
152: final Reader reader = new StringReader(configurationString);
153: JavaScriptConfiguration.loadConfiguration(reader);
154: final BrowserVersion browser = BrowserVersion.INTERNET_EXPLORER_6_0;
155: final JavaScriptConfiguration configuration = JavaScriptConfiguration
156: .getInstance(browser);
157: final ClassConfiguration expectedConfig = new ClassConfiguration(
158: "Document", Document.class.getName(), null, null, null,
159: true);
160: expectedConfig.addProperty("readyState", true, false);
161: assertTrue("Document property did not match", configuration
162: .classConfigEquals("Document", expectedConfig));
163: }
164:
165: /**
166: * Test getting the configuration for the Netscape browser. The readyState property should not be
167: * available in this case.
168: *
169: * @throws Exception - Exception on error
170: */
171: public void testGetConditionalPropertyBrowser() throws Exception {
172: final String configurationString = "<?xml version=\"1.0\"?>\n"
173: + "<configuration\n"
174: + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
175: + " xsi:noNamespaceSchemaLocation=\"JavaScriptConfiguration.xsd\">\n"
176: + " <class name=\"Document\" extends=\"Node\" "
177: + "classname=\"com.gargoylesoftware.htmlunit.javascript.host.Document\">\n"
178: + " <property name=\"readyState\" readable=\"true\" writable=\"false\">\n"
179: + " <browser name=\"Microsoft Internet Explorer\" min-version=\"4\"/>\n"
180: + " </property>\n"
181: + " </class>\n"
182: + " <class name=\"Node\" "
183: + "classname=\"com.gargoylesoftware.htmlunit.javascript.host.Node\">\n"
184: + " <property name=\"firstChild\" readable=\"true\" writable=\"false\">\n"
185: + " </property>\n" + " </class>\n"
186: + "</configuration>\n";
187: final Reader reader = new StringReader(configurationString);
188: JavaScriptConfiguration.loadConfiguration(reader);
189: final BrowserVersion browser = BrowserVersion.FIREFOX_2;
190: final JavaScriptConfiguration configuration = JavaScriptConfiguration
191: .getInstance(browser);
192: final ClassConfiguration expectedConfig = new ClassConfiguration(
193: "Document", Document.class.getName(), null, null, null,
194: true);
195: assertTrue("Document property did not match", configuration
196: .classConfigEquals("Document", expectedConfig));
197: }
198:
199: /**
200: * Test that the JSObject is being set correctly
201: * @throws Exception on error
202: */
203: public void testForSettingJSObject() throws Exception {
204: final String configurationString = "<?xml version=\"1.0\"?>\n"
205: + "<configuration\n"
206: + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
207: + " xsi:noNamespaceSchemaLocation=\"JavaScriptConfiguration.xsd\">\n"
208: + " <class name=\"Document\" extends=\"Node\" "
209: + "classname=\"com.gargoylesoftware.htmlunit.javascript.host.Document\" JSObject=\"true\">\n"
210: + " </class>\n" + "</configuration>\n";
211: final Reader reader = new StringReader(configurationString);
212: JavaScriptConfiguration.loadConfiguration(reader);
213: final BrowserVersion browser = BrowserVersion.INTERNET_EXPLORER_6_0;
214: final JavaScriptConfiguration configuration = JavaScriptConfiguration
215: .getInstance(browser);
216: final ClassConfiguration config = configuration
217: .getClassConfiguration("Document");
218: assertTrue("JSObject is not set", config.isJsObject());
219: }
220:
221: /**
222: * Test getting the configuration for the Netscape browser. The readyState property should not be
223: * available in this case.
224: *
225: * @throws Exception - Exception on error
226: */
227: public void testInstanceForTestVersion() throws Exception {
228: final String configurationString = "<?xml version=\"1.0\"?>\n"
229: + "<configuration\n"
230: + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
231: + " xsi:noNamespaceSchemaLocation=\"JavaScriptConfiguration.xsd\">\n"
232: + " <class name=\"Document\" extends=\"Node\" "
233: + "classname=\"com.gargoylesoftware.htmlunit.javascript.host.Document\">\n"
234: + " <property name=\"readyState\" readable=\"true\" writable=\"false\">\n"
235: + " <browser name=\"Microsoft Internet Explorer\" min-version=\"4\"/>\n"
236: + " </property>\n"
237: + " </class>\n"
238: + " <class name=\"Node\" "
239: + "classname=\"com.gargoylesoftware.htmlunit.javascript.host.Node\">\n"
240: + " <property name=\"firstChild\" readable=\"true\" writable=\"false\">\n"
241: + " </property>\n" + " </class>\n"
242: + "</configuration>\n";
243: final Reader reader = new StringReader(configurationString);
244: JavaScriptConfiguration.loadConfiguration(reader);
245: final JavaScriptConfiguration configuration = JavaScriptConfiguration
246: .getAllEntries();
247: final ClassConfiguration expectedConfig = new ClassConfiguration(
248: "Document", Document.class.getName(), null, null, null,
249: true);
250: expectedConfig.addProperty("readyState", true, false);
251: assertTrue("Document property did not match", configuration
252: .classConfigEquals("Document", expectedConfig));
253: }
254:
255: /**
256: * Test getting the configuration for the Netscape browser. The readyState property should not be
257: * available in this case.
258: *
259: * @throws Exception - Exception on error
260: */
261: public void testPropertyForNullBrowser() throws Exception {
262: final String configurationString = "<?xml version=\"1.0\"?>\n"
263: + "<configuration\n"
264: + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
265: + " xsi:noNamespaceSchemaLocation=\"JavaScriptConfiguration.xsd\">\n"
266: + " <class name=\"Document\" extends=\"Node\" "
267: + "classname=\"com.gargoylesoftware.htmlunit.javascript.host.Document\">\n"
268: + " <property name=\"readyState\" readable=\"true\" writable=\"false\">\n"
269: + " <browser name=\"Microsoft Internet Explorer\" min-version=\"4\"/>\n"
270: + " </property>\n"
271: + " </class>\n"
272: + " <class name=\"Node\" "
273: + "classname=\"com.gargoylesoftware.htmlunit.javascript.host.Node\">\n"
274: + " <property name=\"firstChild\" readable=\"true\" writable=\"false\">\n"
275: + " </property>\n" + " </class>\n"
276: + "</configuration>\n";
277: final Reader reader = new StringReader(configurationString);
278: JavaScriptConfiguration.loadConfiguration(reader);
279: try {
280: JavaScriptConfiguration.getInstance(null);
281: assertTrue(
282: "Should have thrown an exception for no browser supplied",
283: false);
284: } catch (final IllegalStateException e) {
285: // everything is fine
286: }
287: }
288:
289: /**
290: * Test getting the configuration for the Netscape browser. The readyState property should not be
291: * available in this case.
292: *
293: * @throws Exception - Exception on error
294: */
295: public void testGetConditionalPropertyMinBrowserVersion()
296: throws Exception {
297: final String configurationString = "<?xml version=\"1.0\"?>\n"
298: + "<configuration\n"
299: + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
300: + " xsi:noNamespaceSchemaLocation=\"JavaScriptConfiguration.xsd\">\n"
301: + " <class name=\"Document\" extends=\"Node\" "
302: + "classname=\"com.gargoylesoftware.htmlunit.javascript.host.Document\">\n"
303: + " <property name=\"readyState\" readable=\"true\" writable=\"false\">\n"
304: + " <browser name=\"Microsoft Internet Explorer\" min-version=\"8\"/>\n"
305: + " </property>\n"
306: + " </class>\n"
307: + " <class name=\"Node\" "
308: + "classname=\"com.gargoylesoftware.htmlunit.javascript.host.Node\">\n"
309: + " <property name=\"firstChild\" readable=\"true\" writable=\"false\">\n"
310: + " </property>\n" + " </class>\n"
311: + "</configuration>\n";
312: final Reader reader = new StringReader(configurationString);
313: JavaScriptConfiguration.loadConfiguration(reader);
314: final BrowserVersion browser = BrowserVersion.INTERNET_EXPLORER_6_0;
315: final JavaScriptConfiguration configuration = JavaScriptConfiguration
316: .getInstance(browser);
317: final ClassConfiguration expectedConfig = new ClassConfiguration(
318: "Document", Document.class.getName(), null, null, null,
319: true);
320: assertTrue("Document should not property did not match",
321: configuration.classConfigEquals("Document",
322: expectedConfig));
323: }
324:
325: /**
326: * Test getting the configuration for the browser max version. The readyState property should not be
327: * available in this case.
328: *
329: * @throws Exception - Exception on error
330: */
331: public void testGetConditionalPropertyMaxBrowserVersion()
332: throws Exception {
333: final String configurationString = "<?xml version=\"1.0\"?>\n"
334: + "<configuration\n"
335: + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
336: + " xsi:noNamespaceSchemaLocation=\"JavaScriptConfiguration.xsd\">\n"
337: + " <class name=\"Document\" extends=\"Node\" "
338: + "classname=\"com.gargoylesoftware.htmlunit.javascript.host.Document\">\n"
339: + " <property name=\"readyState\" readable=\"true\" writable=\"false\">\n"
340: + " <browser name=\"Microsoft Internet Explorer\" max-version=\"3\"/>\n"
341: + " </property>\n"
342: + " </class>\n"
343: + " <class name=\"Node\" "
344: + "classname=\"com.gargoylesoftware.htmlunit.javascript.host.Node\">\n"
345: + " <property name=\"firstChild\" readable=\"true\" writable=\"false\">\n"
346: + " </property>\n" + " </class>\n"
347: + "</configuration>\n";
348: final Reader reader = new StringReader(configurationString);
349: JavaScriptConfiguration.loadConfiguration(reader);
350: final BrowserVersion browser = BrowserVersion.INTERNET_EXPLORER_6_0;
351: final JavaScriptConfiguration configuration = JavaScriptConfiguration
352: .getInstance(browser);
353: final ClassConfiguration expectedConfig = new ClassConfiguration(
354: "Document", Document.class.getName(), null, null, null,
355: true);
356: assertTrue("Document should not property did not match",
357: configuration.classConfigEquals("Document",
358: expectedConfig));
359: }
360:
361: /**
362: * Test getting the configuration for the JavaScript max version. The readyState property should not be
363: * available in this case.
364: *
365: * @throws Exception - Exception on error
366: */
367: public void testGetConditionalPropertyMaxJSVersion()
368: throws Exception {
369: final String configurationString = "<?xml version=\"1.0\"?>\n"
370: + "<configuration\n"
371: + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
372: + " xsi:noNamespaceSchemaLocation=\"JavaScriptConfiguration.xsd\">\n"
373: + " <class name=\"Document\" extends=\"Node\" "
374: + "classname=\"com.gargoylesoftware.htmlunit.javascript.host.Document\">\n"
375: + " <property name=\"readyState\" readable=\"true\" writable=\"false\">\n"
376: + " <javascript max-version=\"1\"/>\n"
377: + " </property>\n"
378: + " </class>\n"
379: + " <class name=\"Node\" "
380: + "classname=\"com.gargoylesoftware.htmlunit.javascript.host.Node\">\n"
381: + " <property name=\"firstChild\" readable=\"true\" writable=\"false\">\n"
382: + " </property>\n" + " </class>\n"
383: + "</configuration>\n";
384: final Reader reader = new StringReader(configurationString);
385: JavaScriptConfiguration.loadConfiguration(reader);
386: final BrowserVersion browser = BrowserVersion.INTERNET_EXPLORER_6_0;
387: final JavaScriptConfiguration configuration = JavaScriptConfiguration
388: .getInstance(browser);
389: final ClassConfiguration expectedConfig = new ClassConfiguration(
390: "Document", Document.class.getName(), null, null, null,
391: true);
392: assertTrue("Document should not property did not match",
393: configuration.classConfigEquals("Document",
394: expectedConfig));
395: }
396:
397: /**
398: * Test parsing the configuration with a function in it.
399: *
400: * @throws Exception - Exception on error
401: */
402: public void testParseFunction() throws Exception {
403: final String configurationString = "<?xml version=\"1.0\"?>\n"
404: + "<configuration\n"
405: + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
406: + " xsi:noNamespaceSchemaLocation=\"JavaScriptConfiguration.xsd\">\n"
407: + " <class name=\"Document\" "
408: + "classname=\"com.gargoylesoftware.htmlunit.javascript.host.Document\">\n"
409: + " <function name=\"createAttribute\"/>\n"
410: + " </class>\n" + "</configuration>\n";
411: final Reader reader = new StringReader(configurationString);
412: JavaScriptConfiguration.loadConfiguration(reader);
413: final BrowserVersion browser = BrowserVersion.INTERNET_EXPLORER_6_0;
414: final JavaScriptConfiguration configuration = JavaScriptConfiguration
415: .getInstance(browser);
416: final ClassConfiguration expectedConfig = new ClassConfiguration(
417: "Document", Document.class.getName(), null, null, null,
418: true);
419: expectedConfig.addFunction("createAttribute");
420: assertTrue("Document function did not match", configuration
421: .classConfigEquals("Document", expectedConfig));
422: }
423:
424: /**
425: * Test parsing the configuration for a browser that does not support the function.
426: *
427: * @throws Exception - Exception on error
428: */
429: public void testParseFunctionForLimitedBrowser() throws Exception {
430: final String configurationString = "<?xml version=\"1.0\"?>\n"
431: + "<configuration\n"
432: + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
433: + " xsi:noNamespaceSchemaLocation=\"JavaScriptConfiguration.xsd\">\n"
434: + " <class name=\"Document\" "
435: + "classname=\"com.gargoylesoftware.htmlunit.javascript.host.Document\">\n"
436: + " <function name=\"createAttribute\">\n"
437: + " <browser name=\"Netscape\"/>\n"
438: + " </function>\n" + " </class>\n"
439: + "</configuration>\n";
440: final Reader reader = new StringReader(configurationString);
441: JavaScriptConfiguration.loadConfiguration(reader);
442: final BrowserVersion browser = BrowserVersion.INTERNET_EXPLORER_6_0;
443: final JavaScriptConfiguration configuration = JavaScriptConfiguration
444: .getInstance(browser);
445: final ClassConfiguration expectedConfig = new ClassConfiguration(
446: "Document", Document.class.getName(), null, null, null,
447: true);
448: assertTrue("Document function did not match", configuration
449: .classConfigEquals("Document", expectedConfig));
450: }
451:
452: /**
453: * Test that the file JavaScriptConfiguration.xml is valid.
454: * @throws Exception If the test fails
455: */
456: public void testConfigurationFileAgainstSchema() throws Exception {
457: final XMLReader parser = XMLReaderFactory
458: .createXMLReader("org.apache.xerces.parsers.SAXParser");
459: final String directory = "src/main/resources/com/gargoylesoftware/htmlunit/javascript/configuration/";
460: parser.setFeature("http://xml.org/sax/features/validation",
461: true);
462: parser.setFeature(
463: "http://apache.org/xml/features/validation/schema",
464: true);
465: parser.setEntityResolver(new EntityResolver() {
466: public InputSource resolveEntity(final String publicId,
467: final String systemId) throws IOException {
468: return createInputSourceForFile(directory
469: + "JavaScriptConfiguration.xsd");
470: }
471: });
472: parser.setErrorHandler(new ErrorHandler() {
473: public void warning(final SAXParseException exception)
474: throws SAXException {
475: throw exception;
476: }
477:
478: public void error(final SAXParseException exception)
479: throws SAXException {
480: throw exception;
481: }
482:
483: public void fatalError(final SAXParseException exception)
484: throws SAXException {
485: throw exception;
486: }
487: });
488:
489: parser.parse(createInputSourceForFile(directory
490: + "JavaScriptConfiguration.xml"));
491:
492: }
493:
494: private InputSource createInputSourceForFile(final String fileName)
495: throws FileNotFoundException {
496: return new InputSource(getFileAsStream(fileName));
497: }
498:
499: /**
500: * Test that the data in the JavaScriptConfiguration file matches the classes in listed
501: * properties and functions. The first step is to get the configuration using a special method which
502: * ignores the browser and javascript constraints. This checks that there is a method for each item in
503: * the configuration file and fails by throwing an exception.
504: *
505: * The second step is to go through each class and determine if for each jsGet, jsSet, and jsFunction class,
506: * there is an entry in the configuration.
507: *
508: * @throws Exception Exception on error
509: */
510: public void testConfigurationFile() throws Exception {
511: final JavaScriptConfiguration configuration = JavaScriptConfiguration
512: .getAllEntries();
513:
514: final Iterator it = configuration.keyIterator();
515: while (it.hasNext()) {
516: final String classname = (String) it.next();
517: getLog().debug("Now testing for class " + classname);
518: final Class clazz = configuration.getClassObject(classname);
519: final Method[] methods = clazz.getMethods();
520: String elementName;
521: Method theMethod;
522: for (int i = 0; i < methods.length; i++) {
523: final String name = methods[i].getName();
524: if (checkForIgnore(name, classname)) {
525: continue;
526: }
527: if (name.startsWith("jsxGet_")) {
528: elementName = name.substring(7);
529: theMethod = configuration.getPropertyReadMethod(
530: classname, elementName);
531: assertNotNull("No definition found for " + name
532: + " defined in " + clazz.getName()
533: + " for object " + classname, theMethod);
534: } else if (name.startsWith("jsxSet_")) {
535: elementName = name.substring(7);
536: theMethod = configuration.getPropertyWriteMethod(
537: classname, elementName);
538: assertNotNull("No definition found for " + name
539: + " defined in " + clazz.getName()
540: + " for object " + classname, theMethod);
541: } else if (name.startsWith("jsxFunction_")) {
542: elementName = name.substring(12);
543: theMethod = configuration.getFunctionMethod(
544: classname, elementName);
545: assertNotNull("No definition found for " + name
546: + " defined in " + clazz.getName()
547: + " for object " + classname, theMethod);
548: }
549: }
550: }
551: // Now test the config for each class and test for methods being defined in the config file
552: // This is the place
553: }
554:
555: private boolean checkForIgnore(final String methodName,
556: final String classname) {
557: final String[] ignoreList = { "Button|jsxGet_form",
558: "FormField|jsxGet_form", "FileUpload|jsxGet_form",
559: "Radio|jsxGet_form", "Reset|jsxGet_form",
560: "Submit|jsxGet_form", "Checkbox|jsxGet_form",
561: "Hidden|jsxGet_form", "Select|jsxGet_form",
562: "Textarea|jsxGet_form", "Input|jsxGet_form",
563: "Password|jsxGet_form",
564: "CharacterDataImpl|jsxGet_tabindex" };
565: final String key = classname + "|" + methodName;
566: for (int i = 0; i < ignoreList.length; i++) {
567: if (ignoreList[i].equals(key)) {
568: return true;
569: }
570: }
571: return false;
572: }
573:
574: /**
575: * Test for if the property exists for the configuration
576: *
577: * @throws Exception Exception on error
578: */
579: public void testForPropertyExist() throws Exception {
580: final String configurationString = "<?xml version=\"1.0\"?>\n"
581: + "<configuration\n"
582: + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
583: + " xsi:noNamespaceSchemaLocation=\"JavaScriptConfiguration.xsd\">\n"
584: + " <class name=\"Document\" extends=\"Node\" "
585: + "classname=\"com.gargoylesoftware.htmlunit.javascript.host.Document\">\n"
586: + " <property name=\"readyState\" readable=\"true\" writable=\"false\">\n"
587: + " <browser name=\"Microsoft Internet Explorer\" min-version=\"4\"/>\n"
588: + " </property>\n"
589: + " </class>\n"
590: + " <class name=\"Node\" "
591: + "classname=\"com.gargoylesoftware.htmlunit.javascript.host.Node\">\n"
592: + " <property name=\"firstChild\" readable=\"true\" writable=\"false\">\n"
593: + " </property>\n" + " </class>\n"
594: + "</configuration>\n";
595: final Reader reader = new StringReader(configurationString);
596: JavaScriptConfiguration.loadConfiguration(reader);
597: final BrowserVersion browser = BrowserVersion.INTERNET_EXPLORER_6_0;
598: final JavaScriptConfiguration configuration = JavaScriptConfiguration
599: .getInstance(browser);
600: assertTrue("Requested property should have existed",
601: configuration.propertyExists(Document.class,
602: "readyState"));
603: }
604:
605: /**
606: * Test for if the property exists for the configuration
607: *
608: * @throws Exception Exception on error
609: */
610: public void testForPropertyNotExist() throws Exception {
611: final String configurationString = "<?xml version=\"1.0\"?>\n"
612: + "<configuration\n"
613: + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
614: + " xsi:noNamespaceSchemaLocation=\"JavaScriptConfiguration.xsd\">\n"
615: + " <class name=\"Document\" extends=\"Node\" "
616: + "classname=\"com.gargoylesoftware.htmlunit.javascript.host.Document\">\n"
617: + " <property name=\"readyState\" readable=\"true\" writable=\"false\">\n"
618: + " <browser name=\"Microsoft Internet Explorer\" min-version=\"4\"/>\n"
619: + " </property>\n"
620: + " </class>\n"
621: + " <class name=\"Node\" "
622: + "classname=\"com.gargoylesoftware.htmlunit.javascript.host.Node\">\n"
623: + " <property name=\"firstChild\" readable=\"true\" writable=\"false\">\n"
624: + " </property>\n" + " </class>\n"
625: + "</configuration>\n";
626: final Reader reader = new StringReader(configurationString);
627: JavaScriptConfiguration.loadConfiguration(reader);
628: final BrowserVersion browser = BrowserVersion.INTERNET_EXPLORER_6_0;
629: final JavaScriptConfiguration configuration = JavaScriptConfiguration
630: .getInstance(browser);
631: assertFalse("Requested property should not exist",
632: configuration.propertyExists(Document.class,
633: "noreadyState"));
634: }
635:
636: /**
637: * Test if configuration map expands with each new instance of BrowserVersion used.
638: *
639: * @throws Exception If the test fails
640: */
641: public void testConfigurationMapExpands() throws Exception {
642: // get a reference to the leaky map
643: final Field field = JavaScriptConfiguration.class
644: .getDeclaredField("ConfigurationMap_");
645: field.setAccessible(true);
646: final HashMap leakyMap = (HashMap) field.get(null);
647:
648: for (int i = 0; i < 3; i++) {
649: final BrowserVersion browserVersion = new BrowserVersion(
650: "App", "Version", "User agent", "1.2", 1);
651: JavaScriptConfiguration.getInstance(browserVersion);
652: }
653: assertEquals(1, leakyMap.size());
654: }
655: }
|