GWT 2.5.0-rc1 HtmlUnit has broken getElementsByTagNameNS implementation

138 views
Skip to first unread message

Colin Alworth

unread,
Jul 17, 2012, 4:34:31 PM7/17/12
to google-we...@googlegroups.com
GWT 2.4 included a custom copy of htmlunit, apparently built from rev 5940[1] of the htmlunit's source - the following unit test passes under that version using the com.google.gwt.xml.XML module:

  public void testSelectElement() {
    String xml = "<root><child></child><child /><child attr='value'>contents</child><other /></root>";
    Document doc = XMLParser.parse(xml);
    NodeList children = doc.getDocumentElement().getElementsByTagName("child");// works
    assertEquals(3, children.getLength());

    NodeList all = doc.getDocumentElement().getElementsByTagName("*");// fails
    assertEquals(4, all.getLength());//child x3 + other
  }

The method getElementsByTagName is implemented by XMLParserImplStandard.getElementsByTagNameImpl(JavaScriptObject, String), which invokes o.getElementsByTagNameNS("*",tagName); in JSNI, resulting in o.getElementsByTagNameNS("*","*") in the failing case. This works in all real browsers (that would use that impl), and in the 2.4.0 copy of htmlunit.

In the GWT 2.5.0-rc1 -dev jar, this has been updated to the 1.9 release[2], which no longer passes this test case. I've noticed that there is an extra patch for 1.9 that modifies document.getElementsByTagNameNS[3], but this apparently doesn't affect the case where getElementsByTagNameNS is invoked on an element (or the fix is for something else altogether). Based on my quick testing, it isn't possible to load both gwt-dev 2.5.0-rc1 and htmlunit r5940 on the classpath to resolve this, as the GWT unit test code is now wiring up webClient.setJavaScriptErrorListener, and didn't do so in earlier GWT versions.

Is there an additional patch which can be applied to HtmlUnit to ensure that this behavior is the same in real/emulated browsers? Is there a cleaner way to detect that HtmlUnit is being used, to kick to another impl of such classes?

Tentative workaround for the actual case where this presented itself (the XML module was just a way to build a clear case of the issue) was to check if tagName was "*", and if so, invoke element.getElementsByTagName("*") instead.


[1] http://code.google.com/p/google-web-toolkit/source/browse/releases/2.4/dev/build.xml#101
[2] http://code.google.com/p/google-web-toolkit/source/browse/releases/2.5/dev/build.xml#102
[3] http://code.google.com/p/google-web-toolkit/source/browse/#svn%2Ftools%2Flib%2Fhtmlunit%2Fhtmlunit-2.9

Thomas Broyer

unread,
Jul 17, 2012, 5:34:24 PM7/17/12
to google-we...@googlegroups.com
This is only a workaround but you can selectively disable the unit-test in HtmlUnit by annotating it with @DoNotRunWith(Platform.HtmlUnitBug); that way, it'll only be run in real browsers (when using -runStyle Manual, RemoteWeb, Selenium or ExternalBrowser)

Colin Alworth

unread,
Jul 17, 2012, 8:57:41 PM7/17/12
to google-we...@googlegroups.com
Right, thanks - that is a way to get around it, but in the case I'm after, queries are occurring on dom elements on the page, which means that any tests which use these widgets or tools are unable to be run in html - this has the potential to poison a lot of tests, by virtue of depending on a browser that claims it is what it says it is...

And that's why we're all in the wonderful state where all browsers have 'mozilla' somewhere in their useragent string.

Thanks for the suggestion, maybe this bug will force my project to start using real browser testing by default, instead of sanity testing in htmlunit first, then going to the actual browsers.
-Colin
Reply all
Reply to author
Forward
0 new messages