-
Bug
-
Resolution: Fixed
-
Medium
-
2.8
-
None
JWebUnit is pretending to be MSIE, which is causing IE-hack code to be served to it, which is causing its Javascript engine to break down and cry.
[CONFSERVER-9046] Functional tests dump a load of Javascript errors to the logs
Carlo, please use the TEST space for testing JIRA. I'll clean up the links.
Oh dear! I thought this was a test area for playing around. But I suspect its production. I'm very sorry for messing things up. I've just been playing with JIRA links functionality. Do you want me to revert my changes?
Current solution is to use a script preprocessor in our custom HtmlUnit dialog:
public class ConfluenceHtmlUnitDialog extends HtmlUnitDialog { // ... protected void initWebClient() { // ... // Strip invalid Javascript in YUI wc.setScriptPreProcessor(new ScriptPreProcessor() { private final Pattern INVALID_SRC_PATTERN = Pattern.compile( "src=" + // src attribute "\\\\?" + // optional backslash (present in YUI 2.3.1, but not 2.2.2) "\"" + // open quotes "//:" + // invalid src attribute in yui-event.js "\\\\?" + // optional backslash "\"" // close quotes ); public String preProcess(HtmlPage htmlPage, String sourceCode, String sourceName, HtmlElement htmlElement) { return INVALID_SRC_PATTERN.matcher(sourceCode).replaceAll(""); } }); // ... } // ... }
The tests seem to be running really slowly, however, once all this Javascript is included. We might need to be a bit more selective with which tests are run with HtmlUnit scripting enabled.
The full stack trace is this:
2007-12-18 18:10:36,481 ERROR [main] [gargoylesoftware.htmlunit.html.HtmlPage] loadJavaScriptFromUrl Error loading javascript from http://::
java.lang.IllegalArgumentException: Host of origin may not be blank
at org.apache.commons.httpclient.cookie.CookieSpecBase.match(CookieSpecBase.java:460)
at org.apache.commons.httpclient.cookie.CookieSpecBase.match(CookieSpecBase.java:556)
at org.apache.commons.httpclient.HttpMethodBase.addCookieRequestHeader(HttpMethodBase.java:1179)
at org.apache.commons.httpclient.HttpMethodBase.addRequestHeaders(HttpMethodBase.java:1305)
at org.apache.commons.httpclient.HttpMethodBase.writeRequestHeaders(HttpMethodBase.java:2036)
at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:1919)
at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:993)
at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:397)
at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:170)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:396)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:346)
at com.gargoylesoftware.htmlunit.HttpWebConnection.getResponse(HttpWebConnection.java:126)
at com.gargoylesoftware.htmlunit.WebClient.loadWebResponseFromWebConnection(WebClient.java:1424)
at com.gargoylesoftware.htmlunit.WebClient.loadWebResponse(WebClient.java:1381)
at com.gargoylesoftware.htmlunit.html.HtmlPage.loadJavaScriptFromUrl(HtmlPage.java:817)
at com.gargoylesoftware.htmlunit.html.HtmlPage.loadExternalJavaScriptFile(HtmlPage.java:775)
at com.gargoylesoftware.htmlunit.html.HtmlScript.executeScriptIfNeeded(HtmlScript.java:229)
at com.gargoylesoftware.htmlunit.html.HtmlPage.notifyNodeAdded(HtmlPage.java:1409)
at com.gargoylesoftware.htmlunit.html.DomNode.appendChild(DomNode.java:603)
at com.gargoylesoftware.htmlunit.javascript.host.HTMLElement.jsxFunction_insertAdjacentHTML(HTMLElement.java:666)
at com.gargoylesoftware.htmlunit.javascript.host.Document.write(Document.java:301)
at com.gargoylesoftware.htmlunit.javascript.host.Document.jsxFunction_write(Document.java:240)
at sun.reflect.GeneratedMethodAccessor35.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:145)
at org.mozilla.javascript.FunctionObject.call(FunctionObject.java:408)
at org.mozilla.javascript.Interpreter.interpretLoop(Interpreter.java:3085)
at org.mozilla.javascript.Interpreter.interpret(Interpreter.java:2251)
at org.mozilla.javascript.InterpretedFunction.call(InterpretedFunction.java:161)
at org.mozilla.javascript.ContextFactory.doTopCall(ContextFactory.java:340)
at com.gargoylesoftware.htmlunit.javascript.HtmlUnitContextFactory.doTopCall(HtmlUnitContextFactory.java:151)
at org.mozilla.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:2758)
at org.mozilla.javascript.InterpretedFunction.exec(InterpretedFunction.java:172)
at org.mozilla.javascript.Context.evaluateString(Context.java:1132)
at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine.execute(JavaScriptEngine.java:255)
at com.gargoylesoftware.htmlunit.html.HtmlPage.loadExternalJavaScriptFile(HtmlPage.java:775)
at com.gargoylesoftware.htmlunit.html.HtmlScript.executeScriptIfNeeded(HtmlScript.java:229)
at com.gargoylesoftware.htmlunit.html.HtmlPage.notifyNodeAdded(HtmlPage.java:1409)
at com.gargoylesoftware.htmlunit.html.DomNode.appendChild(DomNode.java:603)
at com.gargoylesoftware.htmlunit.html.HTMLParser$HtmlUnitDOMBuilder.startElement(HTMLParser.java:406)
at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source)
at org.cyberneko.html.filters.DefaultFilter.startElement(DefaultFilter.java:179)
at org.cyberneko.html.filters.NamespaceBinder.startElement(NamespaceBinder.java:286)
at org.cyberneko.html.HTMLTagBalancer.callStartElement(HTMLTagBalancer.java:1009)
at org.cyberneko.html.HTMLTagBalancer.startElement(HTMLTagBalancer.java:639)
at org.cyberneko.html.HTMLScanner$ContentScanner.scanStartElement(HTMLScanner.java:2407)
at org.cyberneko.html.HTMLScanner$ContentScanner.scan(HTMLScanner.java:1881)
at org.cyberneko.html.HTMLScanner.scanDocument(HTMLScanner.java:809)
at org.cyberneko.html.HTMLConfiguration.parse(HTMLConfiguration.java:478)
at org.cyberneko.html.HTMLConfiguration.parse(HTMLConfiguration.java:431)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at com.gargoylesoftware.htmlunit.html.HTMLParser$HtmlUnitDOMBuilder.parse(HTMLParser.java:346)
at com.gargoylesoftware.htmlunit.html.HTMLParser.parse(HTMLParser.java:229)
at com.gargoylesoftware.htmlunit.DefaultPageCreator.createHtmlPage(DefaultPageCreator.java:112)
at com.gargoylesoftware.htmlunit.DefaultPageCreator.createPage(DefaultPageCreator.java:85)
at com.gargoylesoftware.htmlunit.WebClient.loadWebResponseInto(WebClient.java:441)
at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:345)
at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:399)
at com.atlassian.confluence.htmlunit.HtmlUnitDialog.beginAt(HtmlUnitDialog.java:158)
at net.sourceforge.jwebunit.junit.WebTester.beginAt(WebTester.java:190)
at net.sourceforge.jwebunit.junit.WebTestCase.beginAt(WebTestCase.java:130)
at com.atlassian.confluence.AbstractConfluenceAcceptanceTest.logInAs(AbstractConfluenceAcceptanceTest.java:349)
at com.atlassian.confluence.AbstractConfluenceAcceptanceTest.logInAs(AbstractConfluenceAcceptanceTest.java:329)
at com.atlassian.confluence.AbstractConfluenceAcceptanceTest.logInAsAdmin(AbstractConfluenceAcceptanceTest.java:380)
at com.atlassian.confluence.AbstractConfluenceAcceptanceTest.setEnableWysiwyg(AbstractConfluenceAcceptanceTest.java:1881)
at com.atlassian.confluence.AddPageAcceptanceTest.testPageAuthorWithAttachmentOnCreate(AddPageAcceptanceTest.java:94)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at net.sourceforge.jwebunit.junit.WebTestCase.runBare(WebTestCase.java:58)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at sun.reflect.GeneratedMethodAccessor92.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at org.apache.maven.surefire.junit.JUnitTestSet.execute(JUnitTestSet.java:213)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:138)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:125)
at org.apache.maven.surefire.Surefire.run(Surefire.java:132)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:290)
at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:818)
I spent most of a day on this.
The cause is that if JWebUnit identifies itself to Javascript as MSIE, YUI will cause it to use this as a way to defer loading stuff until the page is loaded (in event.js, or yahoo-dom-event.js):
if (EU.isIE) { document.write( '<scr' + 'ipt id="_yui_eu_dr" defer="true" src="//:"></script>'); var el = document.getElementById("_yui_eu_dr"); el.onreadystatechange = function() { if ("complete" == this.readyState) { this.parentNode.removeChild(this); YAHOO.util.Event._ready(); } }; el=null; // Process onAvailable/onContentReady items when when the // DOM is ready. YAHOO.util.Event.onDOMReady( YAHOO.util.Event._tryPreloadAttach, YAHOO.util.Event, true); // Safari: The document's readyState in Safari currently will // change to loaded/complete before images are loaded. }
JWebUnit then complains about the bogus URL "//:"
Telling JWebUnit to identify itself as not being MSIE causes other tests to break. For example PagePermissionsAcceptanceTest will fail to find certain text in the permissions section of the edit page if you identify as some other browser.
The temporary fix I added was to not load the event.js code at all if we weren't displaying the menus (since we don't display the menus to MSIE). If we ever enable the menus generally, this problem will come back and it will be a bastard to fix.
YUI is being removed from the product for 2.9, along with an HtmlUnit upgrade that fixes the parse error.
Our workaround fixed it temporarily for 2.8 anyway.