Web Inspector: InspectorTest should be a subclass of TestHarness
authorbburg@apple.com <bburg@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Aug 2015 19:09:34 +0000 (19:09 +0000)
committerbburg@apple.com <bburg@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Aug 2015 19:09:34 +0000 (19:09 +0000)
https://bugs.webkit.org/show_bug.cgi?id=148079

Reviewed by Timothy Hatcher.

Source/WebInspectorUI:

Extract the frontend test harness into a subclass. Delete some code that
is now redundant. Sprinkle some ES6 syntax where possible.

Rewrite the code that redirects the Inspector page's console messages to
the test page, since it didn't appear to work any more.

* UserInterface/Test.html: Add debug options here, and a wiki link.
* UserInterface/Test/FrontendTestHarness.js: Added.
(FrontendTestHarness):
(FrontendTestHarness.prototype.completeTest):
(FrontendTestHarness.prototype.addResult):
(FrontendTestHarness.prototype.debugLog):
(FrontendTestHarness.prototype.evaluateInPage):
(FrontendTestHarness.prototype.expectNoError):
(FrontendTestHarness.prototype.testPageDidLoad):
(FrontendTestHarness.prototype.reloadPage):
(FrontendTestHarness.prototype.redirectConsoleToTestOutput.createProxyConsoleHandler):
(FrontendTestHarness.prototype.redirectConsoleToTestOutput):
(FrontendTestHarness.prototype.reportUncaughtException):
(FrontendTestHarness.prototype._resendResults):
* UserInterface/Test/Test.js:
(WebInspector.loaded):
(WebInspector.UIString): Arrow it.
(WebInspector.updateDockedState): Arrow it.
(WebInspector.updateDockingAvailability): Arrow it.
(InspectorTest.EventDispatcher.prototype.dispatchEvent): Deleted.
(InspectorTest.EventDispatcher): Deleted.
(InspectorTest.log): Deleted.
(InspectorTest.assert): Deleted.
(InspectorTest.expectThat): Deleted.
(InspectorTest.debugLog): Deleted.
(InspectorTest.expectNoError): Deleted.
(InspectorTest.completeTest): Deleted.
(InspectorTest.evaluateInPage): Deleted.
(InspectorTest.addResult): Deleted.
(InspectorTest._resendResults): Deleted.
(InspectorTest.testPageDidLoad): Deleted.
(InspectorTest.reloadPage): Deleted.
(InspectorTest.reportUncaughtException): Deleted.
* UserInterface/Test/TestSuite.js: Clean an unnecessary self = this.
(SyncTestSuite.prototype.runTestCases):
(SyncTestSuite):
* UserInterface/TestStub.html: Add matching link to wiki.

LayoutTests:

Rename InspectorTestProxy to TestPage. Update some code style in
the harness script files to be consistent.

* http/tests/inspector/debugger/debugger-test.js:
* http/tests/inspector/dom/shapes-test.js:
* http/tests/inspector/replay/replay-test.js:
* http/tests/inspector/resources/inspector-test.js:
(TestPage.registerInitializer):
(runTest.runInitializationMethodsInFrontend):
(runTest.runTestMethodInFrontend):
(runTest):
(TestPage.completeTest):
(TestPage.debugLog):
(TestPage.addResult):
(TestPage.reportUncaughtException):
(InspectorTestProxy.registerInitializer): Deleted.
(InspectorTestProxy.completeTest): Deleted.
(InspectorTestProxy.debugLog): Deleted.
(InspectorTestProxy.addResult): Deleted.
(InspectorTestProxy.reportUncaughtException): Deleted.
* inspector/debugger/breakpoint-action-eval.html:
* inspector/debugger/resources/break-on-exception-tests.js:
* inspector/debugger/resources/script-for-breakpoint-actions.js:
(breakpointActions):
* inspector/debugger/search-scripts.html:
* inspector/replay/window-navigator-plugins-memoized.html:
* inspector/timeline/debugger-paused-while-recording.html:
* inspector/timeline/exception-in-injected-script-while-recording.html:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@188644 268f45cc-cd09-0410-ab3c-d52691b4dbfc

18 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/inspector/debugger/debugger-test.js
LayoutTests/http/tests/inspector/dom/shapes-test.js
LayoutTests/http/tests/inspector/replay/replay-test.js
LayoutTests/http/tests/inspector/resources/inspector-test.js
LayoutTests/inspector/debugger/breakpoint-action-eval.html
LayoutTests/inspector/debugger/resources/break-on-exception-tests.js
LayoutTests/inspector/debugger/resources/script-for-breakpoint-actions.js
LayoutTests/inspector/debugger/search-scripts.html
LayoutTests/inspector/replay/window-navigator-plugins-memoized.html
LayoutTests/inspector/timeline/debugger-paused-while-recording.html
LayoutTests/inspector/timeline/exception-in-injected-script-while-recording.html
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/UserInterface/Test.html
Source/WebInspectorUI/UserInterface/Test/FrontendTestHarness.js [new file with mode: 0644]
Source/WebInspectorUI/UserInterface/Test/Test.js
Source/WebInspectorUI/UserInterface/Test/TestSuite.js
Source/WebInspectorUI/UserInterface/TestStub.html

index 7dafd11..9b13306 100644 (file)
@@ -1,3 +1,39 @@
+2015-08-19  Brian Burg  <bburg@apple.com>
+
+        Web Inspector: InspectorTest should be a subclass of TestHarness
+        https://bugs.webkit.org/show_bug.cgi?id=148079
+
+        Reviewed by Timothy Hatcher.
+
+        Rename InspectorTestProxy to TestPage. Update some code style in
+        the harness script files to be consistent.
+
+        * http/tests/inspector/debugger/debugger-test.js:
+        * http/tests/inspector/dom/shapes-test.js:
+        * http/tests/inspector/replay/replay-test.js:
+        * http/tests/inspector/resources/inspector-test.js:
+        (TestPage.registerInitializer):
+        (runTest.runInitializationMethodsInFrontend):
+        (runTest.runTestMethodInFrontend):
+        (runTest):
+        (TestPage.completeTest):
+        (TestPage.debugLog):
+        (TestPage.addResult):
+        (TestPage.reportUncaughtException):
+        (InspectorTestProxy.registerInitializer): Deleted.
+        (InspectorTestProxy.completeTest): Deleted.
+        (InspectorTestProxy.debugLog): Deleted.
+        (InspectorTestProxy.addResult): Deleted.
+        (InspectorTestProxy.reportUncaughtException): Deleted.
+        * inspector/debugger/breakpoint-action-eval.html:
+        * inspector/debugger/resources/break-on-exception-tests.js:
+        * inspector/debugger/resources/script-for-breakpoint-actions.js:
+        (breakpointActions):
+        * inspector/debugger/search-scripts.html:
+        * inspector/replay/window-navigator-plugins-memoized.html:
+        * inspector/timeline/debugger-paused-while-recording.html:
+        * inspector/timeline/exception-in-injected-script-while-recording.html:
+
 2015-08-19  Chris Dumez  <cdumez@apple.com>
 
         WebKit may keep outdated entry in the disk cache after a reload
index d102558..74da92e 100644 (file)
@@ -1,4 +1,4 @@
-InspectorTestProxy.registerInitializer(function() {
+TestPage.registerInitializer(function() {
 
 InspectorTest.startTracingBreakpoints = function()
 {
index bcce9f1..bbbeea9 100644 (file)
@@ -1,4 +1,4 @@
-InspectorTestProxy.registerInitializer(function() {
+TestPage.registerInitializer(function() {
 
 InspectorTest.Shapes = {
     getShapeOutsideInfoForSelector: function(selector, callback)
index 333d783..c8f4a83 100644 (file)
@@ -1,4 +1,4 @@
-InspectorTestProxy.registerInitializer(function() {
+TestPage.registerInitializer(function() {
 
 InspectorTest.Replay = {};
 
index 02deab0..cc355cd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 // This namespace is injected into every test page. Its functions are invoked by
-// InspectorTest methods on the inspector page via RuntimeAgent.evaluate() calls.
-InspectorTestProxy = {};
-InspectorTestProxy._initializers = [];
+// InspectorTest methods on the inspector page via a TestHarness subclass.
+TestPage = {};
+TestPage._initializers = [];
 
 // Helper scripts like `debugger-test.js` must register their initialization
 // function with this method so it will be marshalled to the inspector page.
-InspectorTestProxy.registerInitializer = function(initializer)
+TestPage.registerInitializer = function(initializer)
 {
     if (typeof initializer === "function")
         this._initializers.push(initializer.toString());
@@ -53,6 +53,12 @@ function runTest()
     window.internals.setInspectorIsUnderTest(true);
     testRunner.showWebInspector();
 
+    let testFunction = window.test;
+    if (typeof testFunction !== "function") {
+        alert("Failed to send test() because it is not a function.");
+        testRunner.notifyDone();
+    }
+
     function runInitializationMethodsInFrontend(initializersArray)
     {
         InspectorTest.testPageDidLoad();
@@ -62,7 +68,7 @@ function runTest()
         if (InspectorTest.didInjectTestCode)
             return;
 
-        for (var initializer of initializersArray) {
+        for (let initializer of initializersArray) {
             try {
                 initializer();
             } catch (e) {
@@ -82,43 +88,41 @@ function runTest()
         try {
             testFunction();
         } catch (e) {
+            // FIXME: the redirected console methods do not forward additional arguments.
             console.error("Exception during test execution: " + e, e.stack || "(no stack trace)");
             InspectorTest.completeTest();
         }
     }
 
-    var codeStringToEvaluate = "(" + runInitializationMethodsInFrontend.toString() + ")([" + InspectorTestProxy._initializers + "]);";
-    testRunner.evaluateInWebInspector(codeStringToEvaluate);
+    let initializationCodeString = `(${runInitializationMethodsInFrontend.toString()})([${TestPage._initializers}]);`;
+    let testFunctionCodeString = `(${runTestMethodInFrontend.toString()})(${testFunction.toString()});`;
 
-    // `test` refers to a function defined in global scope in the test HTML page.
-    codeStringToEvaluate = "(" + runTestMethodInFrontend.toString() + ")(" + test.toString() + ");";
-    testRunner.evaluateInWebInspector(codeStringToEvaluate);
+    testRunner.evaluateInWebInspector(initializationCodeString);
+    testRunner.evaluateInWebInspector(testFunctionCodeString);
 }
 
-InspectorTestProxy.completeTest = function()
+TestPage.completeTest = function()
 {
     // Don't try to use testRunner if running through the browser.
     if (!window.testRunner)
         return;
 
     // Close inspector asynchrously in case we want to test tear-down behavior.
-    setTimeout(function() {
+    setTimeout(() => {
         testRunner.closeWebInspector();
-        setTimeout(function() {
-            testRunner.notifyDone();
-        }, 0);
+        setTimeout(() => { testRunner.notifyDone(); }, 0);
     }, 0);
 }
 
 // Logs message to unbuffered process stdout, avoiding timeouts.
 // only be used to debug tests and not to produce normal test output.
-InspectorTestProxy.debugLog = function(message)
+TestPage.debugLog = function(message)
 {
     window.alert(message);
 }
 
 // Add and clear test output from the results window.
-InspectorTestProxy.addResult = function(text)
+TestPage.addResult = function(text)
 {
     // For early errors triggered when loading the test page, write to stderr.
     if (!document.body) {
@@ -135,24 +139,24 @@ InspectorTestProxy.addResult = function(text)
     this._resultElement.append(text, document.createElement("br"));
 }
 
-InspectorTestProxy.needToSanitizeUncaughtExceptionURLs = false;
+TestPage.needToSanitizeUncaughtExceptionURLs = false;
 
-InspectorTestProxy.reportUncaughtException = function(message, url, lineNumber)
+TestPage.reportUncaughtException = function(message, url, lineNumber)
 {
-    if (InspectorTestProxy.needToSanitizeUncaughtExceptionURLs) {
-        if (typeof url == "string") {
-            var lastSlash = url.lastIndexOf("/");
-            var lastBackSlash = url.lastIndexOf("\\");
-            var lastPathSeparator = Math.max(lastSlash, lastBackSlash);
+    if (TestPage.needToSanitizeUncaughtExceptionURLs) {
+        if (typeof url === "string") {
+            let lastSlash = url.lastIndexOf("/");
+            let lastBackSlash = url.lastIndexOf("\\");
+            let lastPathSeparator = Math.max(lastSlash, lastBackSlash);
             if (lastPathSeparator > 0)
                 url = url.substr(lastPathSeparator + 1);
         }
     }
 
-    var result = "Uncaught exception in test page: " + message + " [" + url + ":" + lineNumber + "]";
-    InspectorTestProxy.addResult(result);
-    InspectorTestProxy.completeTest();
+    let result = `Uncaught exception in test page: ${message} [${url}:${lineNumber}]`;
+    TestPage.addResult(result);
+    TestPage.completeTest();
 }
 
 // Catch syntax errors, type errors, and other exceptions. Run this before loading other files.
-window.onerror = InspectorTestProxy.reportUncaughtException;
+window.onerror = TestPage.reportUncaughtException.bind(TestPage);
index ac7153c..5188912 100644 (file)
@@ -13,8 +13,8 @@ function runBreakpointActions()
 
 function action(a, b)
 {
-    InspectorTestProxy.addResult("Breakpoint action evaluated. a:(" + a + ") b:(" + b + ")");
-    InspectorTestProxy.completeTest();
+    TestPage.addResult("Breakpoint action evaluated. a:(" + a + ") b:(" + b + ")");
+    TestPage.completeTest();
 }
 
 function test()
index af95e42..ae9e3ba 100644 (file)
@@ -1,4 +1,4 @@
-InspectorTestProxy.needToSanitizeUncaughtExceptionURLs = true;
+TestPage.needToSanitizeUncaughtExceptionURLs = true;
 
 var arr = [ 1, 2, 3 ];
 var mapData = [[ "a", arr ]];
index d0a06a8..f1168c4 100644 (file)
@@ -1,5 +1,5 @@
 function breakpointActions(a, b)
 {
     // Only preserve this message on the current test page load.
-    InspectorTestProxy.addResult("inside breakpointActions a:(" + a + ") b:(" + b + ")");
+    TestPage.addResult("inside breakpointActions a:(" + a + ") b:(" + b + ")");
 }
index 956950e..49ad84f 100644 (file)
@@ -44,7 +44,7 @@ function test()
         });
     });
 
-    InspectorTest.eventDispatcher.addEventListener(InspectorTest.EventDispatcher.Event.TestPageDidLoad, function() {
+    InspectorTest.addEventListener(FrontendTestHarness.Event.TestPageDidLoad, () => {
         InspectorTest.evaluateInPage("performEvals()");
     });
 
index ff5ded6..3bb2b39 100644 (file)
@@ -77,12 +77,12 @@ function dumpNondeterministicState()
 // These functions are called in the previous main frame prior to the initial
 // navigation that begins capturing or replaying. Careful, heap state will be lost.
 function setupPreCapture() {
-    InspectorTestProxy.addResult("Enabling plugins before capture.");
+    TestPage.addResult("Enabling plugins before capture.");
     testRunner.setPluginsEnabled(false);
 }
 
 function setupPreReplay() {
-    InspectorTestProxy.addResult("Disabling plugins before replay.");
+    TestPage.addResult("Disabling plugins before replay.");
     testRunner.setPluginsEnabled(true);
 }
 
index b673438..e9ac9b3 100644 (file)
@@ -15,13 +15,13 @@ function installTimer()
 
 function add(a, b)
 {
-    InspectorTestProxy.addResult("Calling add(): " + a + " + " + b);
+    TestPage.addResult("Calling add(): " + a + " + " + b);
     return a + b;
 }
 
 function mul(a, b)
 {
-    InspectorTestProxy.addResult("Calling mul(): " + a + " * " + b);
+    TestPage.addResult("Calling mul(): " + a + " * " + b);
     return a * b;
 }
 
index 9b5fcf9..19e37c8 100644 (file)
@@ -15,13 +15,13 @@ function installTimer()
 
 function add(a, b)
 {
-    InspectorTestProxy.addResult("Calling add(): " + a + " + " + b);
+    TestPage.addResult("Calling add(): " + a + " + " + b);
     return a + b;
 }
 
 function mul(a, b)
 {
-    InspectorTestProxy.addResult("Calling mul(): " + a + " * " + b);
+    TestPage.addResult("Calling mul(): " + a + " * " + b);
     return a * b;
 }
 
index e13786f..0bb9489 100644 (file)
@@ -1,5 +1,56 @@
 2015-08-19  Brian Burg  <bburg@apple.com>
 
+        Web Inspector: InspectorTest should be a subclass of TestHarness
+        https://bugs.webkit.org/show_bug.cgi?id=148079
+
+        Reviewed by Timothy Hatcher.
+
+        Extract the frontend test harness into a subclass. Delete some code that
+        is now redundant. Sprinkle some ES6 syntax where possible.
+
+        Rewrite the code that redirects the Inspector page's console messages to
+        the test page, since it didn't appear to work any more.
+
+        * UserInterface/Test.html: Add debug options here, and a wiki link.
+        * UserInterface/Test/FrontendTestHarness.js: Added.
+        (FrontendTestHarness):
+        (FrontendTestHarness.prototype.completeTest):
+        (FrontendTestHarness.prototype.addResult):
+        (FrontendTestHarness.prototype.debugLog):
+        (FrontendTestHarness.prototype.evaluateInPage):
+        (FrontendTestHarness.prototype.expectNoError):
+        (FrontendTestHarness.prototype.testPageDidLoad):
+        (FrontendTestHarness.prototype.reloadPage):
+        (FrontendTestHarness.prototype.redirectConsoleToTestOutput.createProxyConsoleHandler):
+        (FrontendTestHarness.prototype.redirectConsoleToTestOutput):
+        (FrontendTestHarness.prototype.reportUncaughtException):
+        (FrontendTestHarness.prototype._resendResults):
+        * UserInterface/Test/Test.js:
+        (WebInspector.loaded):
+        (WebInspector.UIString): Arrow it.
+        (WebInspector.updateDockedState): Arrow it.
+        (WebInspector.updateDockingAvailability): Arrow it.
+        (InspectorTest.EventDispatcher.prototype.dispatchEvent): Deleted.
+        (InspectorTest.EventDispatcher): Deleted.
+        (InspectorTest.log): Deleted.
+        (InspectorTest.assert): Deleted.
+        (InspectorTest.expectThat): Deleted.
+        (InspectorTest.debugLog): Deleted.
+        (InspectorTest.expectNoError): Deleted.
+        (InspectorTest.completeTest): Deleted.
+        (InspectorTest.evaluateInPage): Deleted.
+        (InspectorTest.addResult): Deleted.
+        (InspectorTest._resendResults): Deleted.
+        (InspectorTest.testPageDidLoad): Deleted.
+        (InspectorTest.reloadPage): Deleted.
+        (InspectorTest.reportUncaughtException): Deleted.
+        * UserInterface/Test/TestSuite.js: Clean an unnecessary self = this.
+        (SyncTestSuite.prototype.runTestCases):
+        (SyncTestSuite):
+        * UserInterface/TestStub.html: Add matching link to wiki.
+
+2015-08-19  Brian Burg  <bburg@apple.com>
+
         Web Inspector: split TestStub.js into multiple files and modernize it
         https://bugs.webkit.org/show_bug.cgi?id=148077
 
index 9d41d36..85c76ac 100644 (file)
     <script src="Base/WebInspector.js"></script>
     <script src="Base/Object.js"></script>
 
+    <script src="Test/TestHarness.js"></script>
+    <script src="Test/FrontendTestHarness.js"></script>
+    <script src="Test/TestSuite.js"></script>
+
     <script src="Test/Test.js"></script>
 
     <script src="Base/DOMUtilities.js"></script>
 
     <script type="text/javascript">
         WebInspector.loaded();
+
+        // Not reliable unless console messages are dumped to stderr.
+        // See wiki for details <https://http://trac.webkit.org/wiki/WebInspectorDebugging>.
+        InspectorBackend.dumpInspectorProtocolMessages = false;
+
+        // Synchronous logging may produce more output prior to a timeout.
+        InspectorTest.forceSyncDebugLogging = false;
     </script>
 </head>
 <body>
diff --git a/Source/WebInspectorUI/UserInterface/Test/FrontendTestHarness.js b/Source/WebInspectorUI/UserInterface/Test/FrontendTestHarness.js
new file mode 100644 (file)
index 0000000..96178f6
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+FrontendTestHarness = class FrontendTestHarness extends TestHarness
+{
+    constructor()
+    {
+        super();
+
+        this._results = [];
+        this._shouldResendResults = true;
+    }
+
+    // TestHarness Overrides
+
+    completeTest()
+    {
+        if (this.forceSyncDebugLogging)
+            InspectorFrontendHost.unbufferedLog("FrontendTestHarness.completeTest()");
+
+        // Wait for results to be resent before requesting completeTest(). Otherwise, messages will be
+        // queued after pending dispatches run to zero and the test page will quit before processing them.
+        if (this._testPageIsReloading) {
+            this._completeTestAfterReload = true;
+            return;
+        }
+
+        InspectorBackend.runAfterPendingDispatches(this.evaluateInPage.bind(this, "TestPage.completeTest()"));
+    }
+
+    addResult(message)
+    {
+        this._results.push(message);
+
+        if (this.forceSyncDebugLogging)
+            InspectorFrontendHost.unbufferedLog("addResult: " + message);
+
+        if (!this._testPageIsReloading)
+            this.evaluateInPage(`TestPage.addResult(unescape("${escape(message)}"))`);
+    }
+
+    debugLog(message)
+    {
+        let stringifiedMessage = typeof message !== "string" ? JSON.stringify(message) : message;
+        this.evaluateInPage(`TestPage.debugLog(unescape("${escape(stringifiedMessage)}"));`);
+    }
+
+    evaluateInPage(expression, callback)
+    {
+        // If we load this page outside of the inspector, or hit an early error when loading
+        // the test frontend, then defer evaluating the commands (indefinitely in the former case).
+        if (this._originalConsole && !window.RuntimeAgent) {
+            this._originalConsole["error"]("Tried to evaluate in test page, but connection not yet established:", expression);
+            return;
+        }
+
+        RuntimeAgent.evaluate.invoke({expression, objectGroup: "test", includeCommandLineAPI: false}, callback);
+    }
+
+    // Frontend test-specific methods.
+
+    expectNoError(error)
+    {
+        if (error) {
+            InspectorTest.log("PROTOCOL ERROR: " + error);
+            InspectorTest.completeTest();
+            throw "PROTOCOL ERROR";
+        }
+    }
+
+    testPageDidLoad()
+    {
+        this._testPageIsReloading = false;
+        this._resendResults();
+
+        this.dispatchEventToListeners(FrontendTestHarness.Event.TestPageDidLoad);
+
+        if (this._completeTestAfterReload)
+            this.completeTest();
+    }
+
+    reloadPage(shouldIgnoreCache)
+    {
+        console.assert(!this._testPageIsReloading);
+        console.assert(!this._testPageReloadedOnce);
+
+        this._testPageIsReloading = true;
+
+        return PageAgent.reload(!!shouldIgnoreCache)
+            .then(() => {
+                this._shouldResendResults = true;
+                this._testPageReloadedOnce = true;
+
+                return Promise.resolve(null);
+            });
+    }
+
+    redirectConsoleToTestOutput()
+    {
+        // We can't use arrow functions here because of 'arguments'. It might
+        // be okay once rest parameters work.
+        let self = this;
+        function createProxyConsoleHandler(type) {
+            return function() {
+                self.addResult(`${type}: ` + Array.from(arguments).join(" ")); 
+            };
+        }
+
+        let redirectedMethods = {};
+        for (let key in window.console) 
+            redirectedMethods[key] = window.console[key].bind(window.console);
+
+        for (let type of ["log", "error", "info"])
+            redirectedMethods[type] = createProxyConsoleHandler(type.toUpperCase());
+
+        this._originalConsole = window.console;
+        window.console = redirectedMethods;
+    }
+
+    reportUncaughtException(message, url, lineNumber, columnNumber)
+    {
+        let result = `Uncaught exception in inspector page: ${message} [${url}:${lineNumber}:${columnNumber}]`;
+
+        // If the connection to the test page is not set up, then just dump to console and give up.
+        // Errors encountered this early can be debugged by loading Test.html in a normal browser page.
+        if (this._originalConsole && (!InspectorFrontendHost || !InspectorBackend)) {
+            this._originalConsole["error"](result);
+            return false;
+        }
+
+        this.addResult(result);
+        this.completeTest();
+        // Stop default handler so we can empty InspectorBackend's message queue.
+        return true;
+    }
+
+    // Private
+
+    _resendResults()
+    {
+        console.assert(this._shouldResendResults);
+        this._shouldResendResults = false;
+
+        for (let result of this._results)
+            this.evaluateInPage(`TestPage.addResult(unescape("${escape(result)}"))`);
+    }
+};
+
+FrontendTestHarness.Event = {
+    TestPageDidLoad: "frontend-test-test-page-did-load"
+};
index a3aa51a..7b28d55 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -62,7 +62,7 @@ WebInspector.loaded = function()
     // Global controllers.
     this.quickConsole = {executionContextIdentifier: undefined};
 
-    document.addEventListener("DOMContentLoaded", this.contentLoaded.bind(this));
+    document.addEventListener("DOMContentLoaded", this.contentLoaded);
 
     // Enable agents.
     InspectorAgent.enable();
@@ -85,195 +85,12 @@ WebInspector.contentLoaded = function()
     InspectorFrontendHost.loaded();
 }
 
-WebInspector.UIString = function(string)
-{
-    return string;
-}
+WebInspector.UIString = (string) => string;
 
 // Add stubs that are called by the frontend API.
-WebInspector.updateDockedState = function() {};
-WebInspector.updateDockingAvailability = function() {};
-
-// InspectorTest contains extra methods that are only available to test code running
-// in the Web Inspector page. They rely on equivalents in the actual test page
-// which are provided by `inspector-test.js`.
-InspectorTest = {};
-
-// This is useful for debugging Inspector tests by synchronously logging messages.
-InspectorTest.dumpMessagesToConsole = false;
-
-// This is a workaround for the fact that it would be hard to set up a constructor,
-// prototype, and prototype chain for the singleton InspectorTest.
-InspectorTest.EventDispatcher = class EventDispatcher extends WebInspector.Object
-{
-    dispatchEvent(event)
-    {
-        this.dispatchEventToListeners(event);
-    }
-};
-
-InspectorTest.EventDispatcher.Event = {
-    TestPageDidLoad: "inspector-test-test-page-did-load"
-};
-
-InspectorTest.eventDispatcher = new InspectorTest.EventDispatcher;
-
-// Note: Additional InspectorTest methods are included on a per-test basis from
-// files like `debugger-test.js`.
-
-// Appends a log message in the test document.
-InspectorTest.log = function(message)
-{
-    var stringifiedMessage = typeof message !== "object" ? message : JSON.stringify(message);
-    InspectorTest.addResult(stringifiedMessage);
-}
-
-// Appends a message in the test document only if the condition is false.
-InspectorTest.assert = function(condition, message)
-{
-    if (condition)
-        return;
-
-    var stringifiedMessage = typeof message !== "object" ? message : JSON.stringify(message);
-    InspectorTest.addResult("ASSERT: " + stringifiedMessage);
-}
-
-// Appends a message in the test document whether the condition is true or not.
-InspectorTest.expectThat = function(condition, message)
-{
-    var prefix = condition ? "PASS" : "FAIL";
-    var stringifiedMessage = typeof message !== "object" ? message : JSON.stringify(message);
-    InspectorTest.addResult(prefix + ": " + stringifiedMessage);
-}
-
-// This function should only be used to debug tests and not to produce normal test output.
-InspectorTest.debugLog = function(message)
-{
-    if (InspectorTest.dumpMessagesToConsole)
-        InspectorFrontendHost.unbufferedLog("debugLog: " + message);
-
-    this.evaluateInPage("InspectorTestProxy.debugLog(unescape('" + escape(JSON.stringify(message)) + "'))");
-}
-
-// Appends a message in the test document if there was an error, and attempts to complete the test.
-InspectorTest.expectNoError = function(error)
-{
-    if (error) {
-        InspectorTest.log("PROTOCOL ERROR: " + error);
-        InspectorTest.completeTest();
-        throw "PROTOCOL ERROR";
-    }
-}
-
-InspectorTest.completeTest = function()
-{
-    if (InspectorTest.dumpMessagesToConsole)
-        InspectorFrontendHost.unbufferedLog("InspectorTest.completeTest()");
-
-    // Wait for results to be resent before requesting completeTest(). Otherwise, messages will be
-    // queued after pending dispatches run to zero and the test page will quit before processing them.
-    if (this._testPageIsReloading) {
-        this._completeTestAfterReload = true;
-        return;
-    }
-
-    InspectorBackend.runAfterPendingDispatches(this.evaluateInPage.bind(this, "InspectorTestProxy.completeTest()"));
-}
-
-InspectorTest.evaluateInPage = function(codeString, callback)
-{
-    // If we load this page outside of the inspector, or hit an early error when loading
-    // the test frontend, then defer evaluating the commands (indefinitely in the former case).
-    if (!window.RuntimeAgent) {
-        this._originalConsoleMethods["error"]("Tried to evaluate in test page, but connection not yet established:", codeString);
-        return;
-    }
-
-    RuntimeAgent.evaluate.invoke({expression: codeString, objectGroup: "test", includeCommandLineAPI: false}, callback);
-}
-
-InspectorTest.addResult = function(text)
-{
-    this._results.push(text);
-
-    if (InspectorTest.dumpMessagesToConsole)
-        InspectorFrontendHost.unbufferedLog("addResult: " + text);
-
-    if (!this._testPageIsReloading)
-        this.evaluateInPage("InspectorTestProxy.addResult(unescape('" + escape(text) + "'))");
-}
-
-InspectorTest._resendResults = function()
-{
-    console.assert(this._shouldResendResults);
-    this._shouldResendResults = false;
-
-    for (var result of this._results)
-        this.evaluateInPage("InspectorTestProxy.addResult(unescape('" + escape(result) + "'))");
-}
-
-InspectorTest.testPageDidLoad = function()
-{
-    this._testPageIsReloading = false;
-    this._resendResults();
-
-    this.eventDispatcher.dispatchEvent(InspectorTest.EventDispatcher.Event.TestPageDidLoad);
-
-    if (this._completeTestAfterReload)
-        InspectorTest.completeTest();
-}
-
-InspectorTest.reloadPage = function(shouldIgnoreCache)
-{
-    console.assert(!this._testPageIsReloading);
-    console.assert(!this._testPageReloadedOnce);
-
-    this._testPageIsReloading = true;
-
-    return PageAgent.reload(!!shouldIgnoreCache)
-        .then(function() {
-            this._shouldResendResults = true;
-            this._testPageReloadedOnce = true;
-
-            return Promise.resolve(null);
-        }.bind(this));
-}
-
-InspectorTest.reportUncaughtException = function(message, url, lineNumber)
-{
-    var result = "Uncaught exception in inspector page: " + message + " [" + url + ":" + lineNumber + "]";
-
-    // If the connection to the test page is not set up, then just dump to console and give up.
-    // Errors encountered this early can be debugged by loading Test.html in a normal browser page.
-    if (!InspectorFrontendHost || !InspectorBackend) {
-        this._originalConsoleMethods["error"](result);
-        return false;
-    }
-
-    this.addResult(result);
-    this.completeTest();
-    // Stop default handler so we can empty InspectorBackend's message queue.
-    return true;
-}
-
-// Initialize reporting mechanisms before loading the rest of the inspector page.
-InspectorTest._results = [];
-InspectorTest._shouldResendResults = true;
-InspectorTest._originalConsoleMethods = {};
-
-// Catch syntax errors, type errors, and other exceptions.
-window.onerror = InspectorTest.reportUncaughtException.bind(InspectorTest);
+WebInspector.updateDockedState = () => {};
+WebInspector.updateDockingAvailability = () => {};
 
-// Redirect frontend console methods to log messages into the test result.
-(function() {
-    function createProxyConsoleHandler(type) {
-        return function() {
-            InspectorTest.addResult(type + ": " + Array.from(arguments).join(" "));
-        };
-    }
+window.InspectorTest = new FrontendTestHarness();
 
-    for (var type of ["log", "error", "info"]) {
-        InspectorTest._originalConsoleMethods[type] = console[type].bind(console);
-        console[type] = createProxyConsoleHandler(type.toUpperCase());
-    }
-})();
+InspectorTest.redirectConsoleToTestOutput();
index f3760f9..fdd531e 100644 (file)
@@ -155,7 +155,6 @@ SyncTestSuite = class SyncTestSuite extends TestSuite
         this._harness.log("== Running test suite: " + this.name);
 
         let priorLogCount = this._harness.logCount;
-        let self = this;
         for (let i = 0; i < this.testcases.length; i++) {
             let testcase = this.testcases[i];
             if (i > 0 && priorLogCount + 1 < this._harness.logCount)
@@ -164,15 +163,15 @@ SyncTestSuite = class SyncTestSuite extends TestSuite
             priorLogCount = this._harness.logCount;
 
             this._harness.log("-- Running test case: " + testcase.name);
-            self.runCount++;
+            this.runCount++;
             try {
                 let result = testcase.test.call(null);
                 if (result === false) {
-                    self.failCount++;
+                    this.failCount++;
                     return false;
                 }
             } catch (e) {
-                self.failCount++;
+                this.failCount++;
                 let message = e;
                 if (e instanceof Error)
                     message = e.message;
index d831593..30970d3 100644 (file)
@@ -40,7 +40,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
     <script src="Test/TestStub.js"></script>
     <script>
-        // Not reliable unless console messages are dumped to console. See wiki for details.
+        // Not reliable unless console messages are dumped to console.
+        // See wiki for details <https://http://trac.webkit.org/wiki/WebInspectorDebugging>.
         ProtocolTest.dumpInspectorProtocolMessages = false;
 
         // Synchronous logging may produce more output prior to a timeout.