Title: [188544] trunk
Revision
188544
Author
bb...@apple.com
Date
2015-08-17 14:51:45 -0700 (Mon, 17 Aug 2015)

Log Message

Web Inspector: split TestStub.js into multiple files and modernize it
https://bugs.webkit.org/show_bug.cgi?id=148077

Reviewed by Timothy Hatcher.
Source/WebInspectorUI:

Since we want to share files between the two harnesses, split some of the parts
into different files so not everything has to be included at once.

Rename InjectedTestHarness to just TestHarness. Update some code to use
ES6 features where appropriate. Put test classes into Test/ directory.

* UserInterface/Base/TestStub.js: Removed.
* UserInterface/Test.html:
* UserInterface/Test/InspectorProtocol.js: Added.
(InspectorProtocol.sendCommand):
(InspectorProtocol.awaitCommand):
(InspectorProtocol.awaitEvent.):
(InspectorProtocol.awaitEvent):
(InspectorProtocol.addEventListener):
(InspectorProtocol.sendMessage):
(InspectorProtocol.checkForError):
(InspectorProtocol.dispatchMessageFromBackend):
* UserInterface/Test/ProtocolTestHarness.js: Added.
(ProtocolTestHarness.prototype.completeTest):
(ProtocolTestHarness.prototype.addResult):
(ProtocolTestHarness.prototype.debugLog):
(ProtocolTestHarness.prototype.evaluateInPage):
(ProtocolTestHarness):
* UserInterface/Test/Test.js: Renamed from Source/WebInspectorUI/UserInterface/Base/Test.js.
(WebInspector.loaded):
(WebInspector.contentLoaded):
(WebInspector.UIString):
(WebInspector.updateDockedState):
(WebInspector.updateDockingAvailability):
(InspectorTest.EventDispatcher.prototype.dispatchEvent):
(InspectorTest.EventDispatcher):
(InspectorTest.log):
(InspectorTest.assert):
(InspectorTest.expectThat):
(InspectorTest.debugLog):
(InspectorTest.expectNoError):
(InspectorTest.completeTest):
(InspectorTest.evaluateInPage):
(InspectorTest.addResult):
(InspectorTest._resendResults):
(InspectorTest.testPageDidLoad):
(InspectorTest.reloadPage):
(InspectorTest.reportUncaughtException):
* UserInterface/Test/TestHarness.js: Added.
(TestHarness):
(TestHarness.prototype.completeTest):
(TestHarness.prototype.addResult):
(TestHarness.prototype.debugLog):
(TestHarness.prototype.evaluateInPage):
(TestHarness.prototype.createAsyncSuite):
(TestHarness.prototype.createSyncSuite):
(TestHarness.prototype.get logCount):
(TestHarness.prototype.log):
(TestHarness.prototype.assert):
(TestHarness.prototype.expectThat):
* UserInterface/Test/TestStub.js: Added.
* UserInterface/Test/TestSuite.js: Added.
(TestSuite):
(TestSuite.prototype.runTestCasesAndFinish):
(TestSuite.prototype.runTestCases):
(TestSuite.prototype.get passCount):
(TestSuite.prototype.get skipCount):
(TestSuite.prototype.addTestCase):
(AsyncTestSuite.prototype.runTestCasesAndFinish.finish):
(AsyncTestSuite.prototype.runTestCasesAndFinish):
(AsyncTestSuite.prototype.runTestCases):
(AsyncTestSuite):
(SyncTestSuite.prototype.runTestCasesAndFinish):
(SyncTestSuite.prototype.runTestCases):
(SyncTestSuite):
* UserInterface/TestStub.html:

LayoutTests:

Add the prefix 'TestPage' to everything in protocol-test.js. Continue
exporting it to the global namespace for backwards compatibility, too.

Rename some things to match changes in the test harness. Tighten up
preconditions for test suite and test case names. Sprinkle some ES6.

* http/tests/inspector/dom/resources/InspectorDOMListener.js:
* http/tests/inspector/resources/console-test.js:
* http/tests/inspector/resources/probe-test.js:
* http/tests/inspector/resources/protocol-test.js:
(TestPage.registerInitializer):
(TestPage.debugLog.window.debugLog):
(TestPage.log.window.log):
(TestPage.closeTest.window.closeTest):
(TestPage.runTest.window.runTest):
(ProtocolTestProxy.registerInitializer): Deleted.
(debugLog): Deleted.
(log): Deleted.
(closeTest): Deleted.
(runTest): Deleted.
* inspector/dom/resources/dom-search-queries.js:
* inspector/unit-tests/async-test-suite.html:
* inspector/unit-tests/sync-test-suite.html:

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (188543 => 188544)


--- trunk/LayoutTests/ChangeLog	2015-08-17 21:50:24 UTC (rev 188543)
+++ trunk/LayoutTests/ChangeLog	2015-08-17 21:51:45 UTC (rev 188544)
@@ -1,5 +1,36 @@
 2015-08-17  Brian Burg  <bb...@apple.com>
 
+        Web Inspector: split TestStub.js into multiple files and modernize it
+        https://bugs.webkit.org/show_bug.cgi?id=148077
+
+        Reviewed by Timothy Hatcher.
+
+        Add the prefix 'TestPage' to everything in protocol-test.js. Continue
+        exporting it to the global namespace for backwards compatibility, too.
+
+        Rename some things to match changes in the test harness. Tighten up
+        preconditions for test suite and test case names. Sprinkle some ES6.
+
+        * http/tests/inspector/dom/resources/InspectorDOMListener.js:
+        * http/tests/inspector/resources/console-test.js:
+        * http/tests/inspector/resources/probe-test.js:
+        * http/tests/inspector/resources/protocol-test.js:
+        (TestPage.registerInitializer):
+        (TestPage.debugLog.window.debugLog):
+        (TestPage.log.window.log):
+        (TestPage.closeTest.window.closeTest):
+        (TestPage.runTest.window.runTest):
+        (ProtocolTestProxy.registerInitializer): Deleted.
+        (debugLog): Deleted.
+        (log): Deleted.
+        (closeTest): Deleted.
+        (runTest): Deleted.
+        * inspector/dom/resources/dom-search-queries.js:
+        * inspector/unit-tests/async-test-suite.html:
+        * inspector/unit-tests/sync-test-suite.html:
+
+2015-08-17  Brian Burg  <bb...@apple.com>
+
         Web Inspector: load ProtocolTestStub from the WebInspectorUI bundle
         https://bugs.webkit.org/show_bug.cgi?id=147955
 

Modified: trunk/LayoutTests/http/tests/inspector/dom/resources/InspectorDOMListener.js (188543 => 188544)


--- trunk/LayoutTests/http/tests/inspector/dom/resources/InspectorDOMListener.js	2015-08-17 21:50:24 UTC (rev 188543)
+++ trunk/LayoutTests/http/tests/inspector/dom/resources/InspectorDOMListener.js	2015-08-17 21:51:45 UTC (rev 188544)
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  */
 
-ProtocolTestProxy.registerInitializer(function(){
+TestPage.registerInitializer(function(){
 
 window.createDOMListener = function()
 {

Modified: trunk/LayoutTests/http/tests/inspector/resources/console-test.js (188543 => 188544)


--- trunk/LayoutTests/http/tests/inspector/resources/console-test.js	2015-08-17 21:50:24 UTC (rev 188543)
+++ trunk/LayoutTests/http/tests/inspector/resources/console-test.js	2015-08-17 21:51:45 UTC (rev 188544)
@@ -1,4 +1,4 @@
-ProtocolTestProxy.registerInitializer(function() {
+TestPage.registerInitializer(function() {
 
 ProtocolTest.Console = {};
 
@@ -34,7 +34,7 @@
 
 ProtocolTest.Console.addTestCase = function(suite, args)
 {
-    if (!(suite instanceof InjectedTestHarness.AsyncTestSuite))
+    if (!(suite instanceof AsyncTestSuite))
         throw new Error("Console test cases must be added to an async test suite.");
 
     var {name, description, _expression_, expected} = args;

Modified: trunk/LayoutTests/http/tests/inspector/resources/probe-test.js (188543 => 188544)


--- trunk/LayoutTests/http/tests/inspector/resources/probe-test.js	2015-08-17 21:50:24 UTC (rev 188543)
+++ trunk/LayoutTests/http/tests/inspector/resources/probe-test.js	2015-08-17 21:51:45 UTC (rev 188544)
@@ -1,4 +1,4 @@
-ProtocolTestProxy.registerInitializer(function() {
+TestPage.registerInitializer(function() {
 
 ProtocolTest.Probe = {};
 

Modified: trunk/LayoutTests/http/tests/inspector/resources/protocol-test.js (188543 => 188544)


--- trunk/LayoutTests/http/tests/inspector/resources/protocol-test.js	2015-08-17 21:50:24 UTC (rev 188543)
+++ trunk/LayoutTests/http/tests/inspector/resources/protocol-test.js	2015-08-17 21:51:45 UTC (rev 188544)
@@ -25,33 +25,26 @@
  */
 
 // This namespace is injected into every test page. Its functions are invoked by
-// ProtocolTest methods on the inspector page via InjectedTestHarness.
-ProtocolTestProxy = {};
-ProtocolTestProxy._initializers = [];
+// ProtocolTest methods on the inspector page via a TestHarness subclass.
+TestPage = {};
+TestPage._initializers = [];
 
 // Helper scripts like `console-test.js` must register their initialization
 // function with this method so it will be marshalled to the inspector page.
-ProtocolTestProxy.registerInitializer = function(initializer)
+TestPage.registerInitializer = function(initializer)
 {
     if (typeof initializer === "function")
         this._initializers.push(initializer.toString());
-}
+};
 
 let outputElement;
 
-/**
- * Logs message to process stdout via alert (hopefully implemented with immediate flush).
- * @param {string} text
- */
-function debugLog(text)
+TestPage.debugLog = window.debugLog = function(text)
 {
     alert(text);
-}
+};
 
-/**
- * @param {string} text
- */
-function log(text)
+TestPage.log = window.log = function(text)
 {
     if (!outputElement) {
         let intermediate = document.createElement("div");
@@ -68,9 +61,9 @@
     }
     outputElement.appendChild(document.createTextNode(text));
     outputElement.appendChild(document.createElement("br"));
-}
+};
 
-function closeTest()
+TestPage.closeTest = window.closeTest = function()
 {
     window.internals.closeDummyInspectorFrontend();
 
@@ -79,20 +72,21 @@
     setTimeout(function() {
         testRunner.notifyDone();
     }, 0);
-}
+};
 
-function runTest()
+TestPage.runTest = window.runTest = function()
 {
     if (!window.testRunner) {
-        console.error("This test requires DumpRenderTree");
+        console.error("This test must be run via DumpRenderTree or WebKitTestRunner.");
         return;
     }
+
     testRunner.dumpAsText();
     testRunner.waitUntilDone();
     testRunner.setCanOpenWindows(true);
 
     let testFunction = window.test;
-    if (!(typeof testFunction === "function")) {
+    if (typeof testFunction !== "function") {
         alert("Failed to send test() because it is not a function.");
         testRunner.notifyDone();
     }
@@ -127,10 +121,10 @@
 
     let inspectorFrontend = window.internals.openDummyInspectorFrontend(url);
     inspectorFrontend.addEventListener("load", function(event) {
-        let initializationCodeString = `(${runInitializationMethodsInFrontend.toString()})([${ProtocolTestProxy._initializers}]);`;
+        let initializationCodeString = `(${runInitializationMethodsInFrontend.toString()})([${TestPage._initializers}]);`;
         let testFunctionCodeString = `(${runTestMethodInFrontend.toString()})(${testFunction.toString()});`;
 
         inspectorFrontend.postMessage(initializationCodeString, "*");
         inspectorFrontend.postMessage(testFunctionCodeString, "*");
     });
-}
+};

Modified: trunk/LayoutTests/inspector/dom/resources/dom-search-queries.js (188543 => 188544)


--- trunk/LayoutTests/inspector/dom/resources/dom-search-queries.js	2015-08-17 21:50:24 UTC (rev 188543)
+++ trunk/LayoutTests/inspector/dom/resources/dom-search-queries.js	2015-08-17 21:51:45 UTC (rev 188544)
@@ -1,4 +1,4 @@
-ProtocolTestProxy.registerInitializer(function() {
+TestPage.registerInitializer(function() {
 
 // Having the queries in an external file, so that DOM search will not find the script when searching for values.
 

Modified: trunk/LayoutTests/inspector/unit-tests/async-test-suite-expected.txt (188543 => 188544)


--- trunk/LayoutTests/inspector/unit-tests/async-test-suite-expected.txt	2015-08-17 21:50:24 UTC (rev 188543)
+++ trunk/LayoutTests/inspector/unit-tests/async-test-suite-expected.txt	2015-08-17 21:51:45 UTC (rev 188544)
@@ -1,9 +1,11 @@
 PASS: instantiating AsyncTestSuite requires name argument.
 PASS: instantiating AsyncTestSuite requires string name argument.
+PASS: instantiating AsyncTestSuite requires non-whitespace name argument.
 PASS: instantiating AsyncTestSuite requires test harness argument.
 PASS: should not be able to add empty test case.
 PASS: should not be able to add non-object test case.
 PASS: test case should require string name.
+PASS: test case should require non-whitespace name.
 PASS: test case should require test function.
 PASS: should not be able to run empty test suite.
 

Modified: trunk/LayoutTests/inspector/unit-tests/async-test-suite.html (188543 => 188544)


--- trunk/LayoutTests/inspector/unit-tests/async-test-suite.html	2015-08-17 21:50:24 UTC (rev 188543)
+++ trunk/LayoutTests/inspector/unit-tests/async-test-suite.html	2015-08-17 21:51:45 UTC (rev 188544)
@@ -6,27 +6,34 @@
 function test()
 {
     try {
-        let result = new InjectedTestHarness.AsyncTestSuite(this);
+        let result = new AsyncTestSuite(this);
         ProtocolTest.log("FAIL: instantiating AsyncTestSuite requires name argument.");
     } catch (e) {
         ProtocolTest.log("PASS: instantiating AsyncTestSuite requires name argument.");
     }
 
     try {
-        let result = new InjectedTestHarness.AsyncTestSuite(this, {});
+        let result = new AsyncTestSuite(this, {});
         ProtocolTest.log("FAIL: instantiating AsyncTestSuite requires string name argument.");
     } catch (e) {
         ProtocolTest.log("PASS: instantiating AsyncTestSuite requires string name argument.");
     }
 
     try {
-        let result = new InjectedTestHarness.AsyncTestSuite("something", {});
+        let result = new AsyncTestSuite(this, "      ");
+        ProtocolTest.log("FAIL: instantiating AsyncTestSuite requires non-whitespace name argument.");
+    } catch (e) {
+        ProtocolTest.log("PASS: instantiating AsyncTestSuite requires non-whitespace name argument.");
+    }
+
+    try {
+        let result = new AsyncTestSuite("something", {});
         ProtocolTest.log("FAIL: instantiating AsyncTestSuite requires test harness argument.");
     } catch (e) {
         ProtocolTest.log("PASS: instantiating AsyncTestSuite requires test harness argument.");
     }
 
-    var badArgsSuite = ProtocolTest.createAsyncSuite("dummy");
+    let badArgsSuite = ProtocolTest.createAsyncSuite("dummy");
     try {
         badArgsSuite.addTestCase();
         ProtocolTest.log("FAIL: should not be able to add empty test case.");
@@ -50,6 +57,15 @@
     }
     try {
         badArgsSuite.addTestCase({
+            name: "        ",
+            test: function() {},
+        });
+        ProtocolTest.log("FAIL: test case should require non-whitespace name.");
+    } catch (e) {
+        ProtocolTest.log("PASS: test case should require non-whitespace name.");
+    }
+    try {
+        badArgsSuite.addTestCase({
             name: "foo",
             test: null,
         });
@@ -58,7 +74,7 @@
         ProtocolTest.log("PASS: test case should require test function.");
     }
 
-    var runEmptySuite = ProtocolTest.createAsyncSuite("AsyncTestSuite.RunEmptySuite");
+    let runEmptySuite = ProtocolTest.createAsyncSuite("AsyncTestSuite.RunEmptySuite");
     try {
         runEmptySuite.runTestCases();
         ProtocolTest.log("FAIL: should not be able to run empty test suite.");
@@ -66,7 +82,7 @@
         ProtocolTest.log("PASS: should not be able to run empty test suite.");
     }
 
-    var runTwiceSuite = ProtocolTest.createAsyncSuite("AsyncTestSuite.RunTwiceSuite");
+    let runTwiceSuite = ProtocolTest.createAsyncSuite("AsyncTestSuite.RunTwiceSuite");
     runTwiceSuite.addTestCase({
         name: "DummyTest0",
         description: "Check that a suite can't run more than once.",
@@ -75,7 +91,7 @@
         }
     });
 
-    var result = runTwiceSuite.runTestCases();
+    let result = runTwiceSuite.runTestCases();
     try {
         // Test cases won't run in this event loop; this call should still throw.
         // Later tests are chained to this suite to avoid nondeterminism.
@@ -85,10 +101,10 @@
         ProtocolTest.log("PASS: should not be able to run a test suite twice.");
     }
 
-    var rejectToken = {"token": 666};
-    var thrownError = new Error(rejectToken);
+    let rejectToken = {"token": 666};
+    let thrownError = new Error(rejectToken);
 
-    var sequentialExecutionSuite = ProtocolTest.createAsyncSuite("AsyncTestSuite.SequentialExecution");
+    let sequentialExecutionSuite = ProtocolTest.createAsyncSuite("AsyncTestSuite.SequentialExecution");
     sequentialExecutionSuite.addTestCase({
         name: "DummyTest1",
         description: "Check test case execution order.",
@@ -118,7 +134,7 @@
         }
     });
 
-    var abortOnFailureSuite = ProtocolTest.createAsyncSuite("AsyncTestSuite.AbortOnFailure");
+    let abortOnFailureSuite = ProtocolTest.createAsyncSuite("AsyncTestSuite.AbortOnFailure");
     abortOnFailureSuite.addTestCase({
         name: "PassingTest5",
         description: "This test is a dummy.",
@@ -142,7 +158,7 @@
     });
 
     result = result.then(function() {
-        var promise = sequentialExecutionSuite.runTestCases();
+        let promise = sequentialExecutionSuite.runTestCases();
         ProtocolTest.expectThat(result instanceof Promise, "AsyncTestSuite.RunTestCases() should return a Promise.");
         return promise;
     });

Modified: trunk/LayoutTests/inspector/unit-tests/sync-test-suite-expected.txt (188543 => 188544)


--- trunk/LayoutTests/inspector/unit-tests/sync-test-suite-expected.txt	2015-08-17 21:50:24 UTC (rev 188543)
+++ trunk/LayoutTests/inspector/unit-tests/sync-test-suite-expected.txt	2015-08-17 21:51:45 UTC (rev 188544)
@@ -1,9 +1,11 @@
 PASS: instantiating SyncTestSuite requires name argument.
 PASS: instantiating SyncTestSuite requires string name argument.
+PASS: instantiating AsyncTestSuite requires non-whitespace name argument.
 PASS: instantiating SyncTestSuite requires test harness argument.
 PASS: should not be able to add empty test case.
 PASS: should not be able to add non-object test case.
 PASS: test case should require string name.
+PASS: test case should require non-whitespace name.
 PASS: test case should require test function.
 PASS: should not be able to run empty test suite.
 

Modified: trunk/LayoutTests/inspector/unit-tests/sync-test-suite.html (188543 => 188544)


--- trunk/LayoutTests/inspector/unit-tests/sync-test-suite.html	2015-08-17 21:50:24 UTC (rev 188543)
+++ trunk/LayoutTests/inspector/unit-tests/sync-test-suite.html	2015-08-17 21:51:45 UTC (rev 188544)
@@ -6,27 +6,34 @@
 function test()
 {
     try {
-        let result = new ProtocolTest.SyncTestSuite(this);
+        let result = new SyncTestSuite(this);
         ProtocolTest.log("FAIL: instantiating SyncTestSuite requires name argument.");
     } catch (e) {
         ProtocolTest.log("PASS: instantiating SyncTestSuite requires name argument.");
     }
 
     try {
-        let result = new ProtocolTest.SyncTestSuite(this, {});
+        let result = new SyncTestSuite(this, {});
         ProtocolTest.log("FAIL: instantiating SyncTestSuite requires string name argument.");
     } catch (e) {
         ProtocolTest.log("PASS: instantiating SyncTestSuite requires string name argument.");
     }
 
     try {
-        let result = new ProtocolTest.SyncTestSuite("something", {});
+        let result = new syncTestSuite(this, "      ");
+        ProtocolTest.log("FAIL: instantiating AsyncTestSuite requires non-whitespace name argument.");
+    } catch (e) {
+        ProtocolTest.log("PASS: instantiating AsyncTestSuite requires non-whitespace name argument.");
+    }
+
+    try {
+        let result = new SyncTestSuite("something", {});
         ProtocolTest.log("FAIL: instantiating SyncTestSuite requires test harness argument.");
     } catch (e) {
         ProtocolTest.log("PASS: instantiating SyncTestSuite requires test harness argument.");
     }
 
-    var badArgsSuite = ProtocolTest.createSyncSuite("dummy");
+    let badArgsSuite = ProtocolTest.createSyncSuite("dummy");
     try {
         badArgsSuite.addTestCase();
         ProtocolTest.log("FAIL: should not be able to add empty test case.");
@@ -50,6 +57,15 @@
     }
     try {
         badArgsSuite.addTestCase({
+            name: "        ",
+            test: function() {},
+        });
+        ProtocolTest.log("FAIL: test case should require non-whitespace name.");
+    } catch (e) {
+        ProtocolTest.log("PASS: test case should require non-whitespace name.");
+    }
+    try {
+        badArgsSuite.addTestCase({
             name: "foo",
             test: null,
         });
@@ -58,7 +74,7 @@
         ProtocolTest.log("PASS: test case should require test function.");
     }
 
-    var runEmptySuite = ProtocolTest.createSyncSuite("SyncTestSuite.RunEmptySuite");
+    let runEmptySuite = ProtocolTest.createSyncSuite("SyncTestSuite.RunEmptySuite");
     try {
         runEmptySuite.runTestCases();
         ProtocolTest.log("FAIL: should not be able to run empty test suite.");
@@ -66,7 +82,7 @@
         ProtocolTest.log("PASS: should not be able to run empty test suite.");
     }
 
-    var runTwiceSuite = ProtocolTest.createSyncSuite("SyncTestSuite.RunTwiceSuite");
+    let runTwiceSuite = ProtocolTest.createSyncSuite("SyncTestSuite.RunTwiceSuite");
     runTwiceSuite.addTestCase({
         name: "DummyTest0",
         description: "Check that a suite can't run more than once.",
@@ -74,7 +90,7 @@
     });
 
     try {
-        var result = runTwiceSuite.runTestCases();
+        let result = runTwiceSuite.runTestCases();
         ProtocolTest.expectThat(result === true, "Return value of runTwiceSuite.runTestCases() should be true when all tests pass.");
 
         runTwiceSuite.runTestCases(); // Try to trigger an error.
@@ -83,9 +99,9 @@
         ProtocolTest.log("PASS: should not be able to run a test suite twice.");
     }
 
-    var thrownError = new Error({"token": 666});
+    let thrownError = new Error({"token": 666});
 
-    var sequentialExecutionSuite = ProtocolTest.createSyncSuite("SyncTestSuite.SequentialExecution");
+    let sequentialExecutionSuite = ProtocolTest.createSyncSuite("SyncTestSuite.SequentialExecution");
     sequentialExecutionSuite.addTestCase({
         name: "DummyTest1",
         description: "Check test case execution order.",
@@ -107,14 +123,14 @@
         test: function() { throw thrownError; }
     });
 
-    var result = sequentialExecutionSuite.runTestCases();
+    let result = sequentialExecutionSuite.runTestCases();
     ProtocolTest.expectThat(result === false, "Return value of sequentialExecutionSuite.runTestCases() should be false when a test case fails.");
     ProtocolTest.expectThat(sequentialExecutionSuite.runCount === 4, "sequentialExecutionSuite should have executed four tests.");
     ProtocolTest.expectThat(sequentialExecutionSuite.passCount === 3, "sequentialExecutionSuite should have passed three tests.");
     ProtocolTest.expectThat(sequentialExecutionSuite.failCount === 1, "sequentialExecutionSuite should have failed 1 test.");
     ProtocolTest.expectThat(sequentialExecutionSuite.skipCount === 0, "sequentialExecutionSuite should have skipped zero tests.");
 
-    var abortOnFailureSuite = ProtocolTest.createSyncSuite("SyncTestSuite.AbortOnFailure");
+    let abortOnFailureSuite = ProtocolTest.createSyncSuite("SyncTestSuite.AbortOnFailure");
     abortOnFailureSuite.addTestCase({
         name: "PassingTest5",
         description: "This test is a dummy.",

Modified: trunk/Source/WebInspectorUI/ChangeLog (188543 => 188544)


--- trunk/Source/WebInspectorUI/ChangeLog	2015-08-17 21:50:24 UTC (rev 188543)
+++ trunk/Source/WebInspectorUI/ChangeLog	2015-08-17 21:51:45 UTC (rev 188544)
@@ -1,5 +1,84 @@
 2015-08-17  Brian Burg  <bb...@apple.com>
 
+        Web Inspector: split TestStub.js into multiple files and modernize it
+        https://bugs.webkit.org/show_bug.cgi?id=148077
+
+        Reviewed by Timothy Hatcher.
+ 
+        Since we want to share files between the two harnesses, split some of the parts
+        into different files so not everything has to be included at once.
+
+        Rename InjectedTestHarness to just TestHarness. Update some code to use
+        ES6 features where appropriate. Put test classes into Test/ directory.
+
+        * UserInterface/Base/TestStub.js: Removed.
+        * UserInterface/Test.html:
+        * UserInterface/Test/InspectorProtocol.js: Added.
+        (InspectorProtocol.sendCommand):
+        (InspectorProtocol.awaitCommand):
+        (InspectorProtocol.awaitEvent.):
+        (InspectorProtocol.awaitEvent):
+        (InspectorProtocol.addEventListener):
+        (InspectorProtocol.sendMessage):
+        (InspectorProtocol.checkForError):
+        (InspectorProtocol.dispatchMessageFromBackend):
+        * UserInterface/Test/ProtocolTestHarness.js: Added.
+        (ProtocolTestHarness.prototype.completeTest):
+        (ProtocolTestHarness.prototype.addResult):
+        (ProtocolTestHarness.prototype.debugLog):
+        (ProtocolTestHarness.prototype.evaluateInPage):
+        (ProtocolTestHarness):
+        * UserInterface/Test/Test.js: Renamed from Source/WebInspectorUI/UserInterface/Base/Test.js.
+        (WebInspector.loaded):
+        (WebInspector.contentLoaded):
+        (WebInspector.UIString):
+        (WebInspector.updateDockedState):
+        (WebInspector.updateDockingAvailability):
+        (InspectorTest.EventDispatcher.prototype.dispatchEvent):
+        (InspectorTest.EventDispatcher):
+        (InspectorTest.log):
+        (InspectorTest.assert):
+        (InspectorTest.expectThat):
+        (InspectorTest.debugLog):
+        (InspectorTest.expectNoError):
+        (InspectorTest.completeTest):
+        (InspectorTest.evaluateInPage):
+        (InspectorTest.addResult):
+        (InspectorTest._resendResults):
+        (InspectorTest.testPageDidLoad):
+        (InspectorTest.reloadPage):
+        (InspectorTest.reportUncaughtException):
+        * UserInterface/Test/TestHarness.js: Added.
+        (TestHarness):
+        (TestHarness.prototype.completeTest):
+        (TestHarness.prototype.addResult):
+        (TestHarness.prototype.debugLog):
+        (TestHarness.prototype.evaluateInPage):
+        (TestHarness.prototype.createAsyncSuite):
+        (TestHarness.prototype.createSyncSuite):
+        (TestHarness.prototype.get logCount):
+        (TestHarness.prototype.log):
+        (TestHarness.prototype.assert):
+        (TestHarness.prototype.expectThat):
+        * UserInterface/Test/TestStub.js: Added.
+        * UserInterface/Test/TestSuite.js: Added.
+        (TestSuite):
+        (TestSuite.prototype.runTestCasesAndFinish):
+        (TestSuite.prototype.runTestCases):
+        (TestSuite.prototype.get passCount):
+        (TestSuite.prototype.get skipCount):
+        (TestSuite.prototype.addTestCase):
+        (AsyncTestSuite.prototype.runTestCasesAndFinish.finish):
+        (AsyncTestSuite.prototype.runTestCasesAndFinish):
+        (AsyncTestSuite.prototype.runTestCases):
+        (AsyncTestSuite):
+        (SyncTestSuite.prototype.runTestCasesAndFinish):
+        (SyncTestSuite.prototype.runTestCases):
+        (SyncTestSuite):
+        * UserInterface/TestStub.html:
+
+2015-08-17  Brian Burg  <bb...@apple.com>
+
         Web Inspector: load ProtocolTestStub from the WebInspectorUI bundle
         https://bugs.webkit.org/show_bug.cgi?id=147955
 

Deleted: trunk/Source/WebInspectorUI/UserInterface/Base/Test.js (188543 => 188544)


--- trunk/Source/WebInspectorUI/UserInterface/Base/Test.js	2015-08-17 21:50:24 UTC (rev 188543)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Test.js	2015-08-17 21:51:45 UTC (rev 188544)
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 2013, 2014 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
- * HOLDER OR 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.
- */
-
-WebInspector.DebuggableType = {
-    Web: "web",
-    _javascript_: "_javascript_"
-};
-
-WebInspector.loaded = function()
-{
-    this.debuggableType = WebInspector.DebuggableType.Web;
-    this.hasExtraDomains = false;
-
-    // Register observers for events from the InspectorBackend.
-    // The initialization order should match the same in Main.js.
-    InspectorBackend.registerInspectorDispatcher(new WebInspector.InspectorObserver);
-    InspectorBackend.registerPageDispatcher(new WebInspector.PageObserver);
-    InspectorBackend.registerConsoleDispatcher(new WebInspector.ConsoleObserver);
-    InspectorBackend.registerDOMDispatcher(new WebInspector.DOMObserver);
-    InspectorBackend.registerNetworkDispatcher(new WebInspector.NetworkObserver);
-    InspectorBackend.registerDebuggerDispatcher(new WebInspector.DebuggerObserver);
-    InspectorBackend.registerTimelineDispatcher(new WebInspector.TimelineObserver);
-    InspectorBackend.registerCSSDispatcher(new WebInspector.CSSObserver);
-    InspectorBackend.registerRuntimeDispatcher(new WebInspector.RuntimeObserver);
-    if (InspectorBackend.registerReplayDispatcher)
-        InspectorBackend.registerReplayDispatcher(new WebInspector.ReplayObserver);
-
-    // Instantiate controllers used by tests.
-    this.frameResourceManager = new WebInspector.FrameResourceManager;
-    this.domTreeManager = new WebInspector.DOMTreeManager;
-    this.cssStyleManager = new WebInspector.CSSStyleManager;
-    this.logManager = new WebInspector.LogManager;
-    this.issueManager = new WebInspector.IssueManager;
-    this.runtimeManager = new WebInspector.RuntimeManager;
-    this.timelineManager = new WebInspector.TimelineManager;
-    this.debuggerManager = new WebInspector.DebuggerManager;
-    this.probeManager = new WebInspector.ProbeManager;
-    this.replayManager = new WebInspector.ReplayManager;
-
-    // Global controllers.
-    this.quickConsole = {executionContextIdentifier: undefined};
-
-    document.addEventListener("DOMContentLoaded", this.contentLoaded.bind(this));
-
-    // Enable agents.
-    InspectorAgent.enable();
-    ConsoleAgent.enable();
-
-    // Perform one-time tasks.
-    WebInspector.CSSCompletions.requestCSSCompletions();
-
-    // Global settings.
-    this.showShadowDOMSetting = new WebInspector.Setting("show-shadow-dom", true);
-}
-
-WebInspector.contentLoaded = function()
-{
-    // Signal that the frontend is now ready to receive messages.
-    InspectorFrontendAPI.loadCompleted();
-
-    // Tell the InspectorFrontendHost we loaded, which causes the window to display
-    // and pending InspectorFrontendAPI commands to be sent.
-    InspectorFrontendHost.loaded();
-}
-
-WebInspector.UIString = function(string)
-{
-    return 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);
-
-// Redirect frontend console methods to log messages into the test result.
-(function() {
-    function createProxyConsoleHandler(type) {
-        return function() {
-            InspectorTest.addResult(type + ": " + Array.from(arguments).join(" "));
-        };
-    }
-
-    for (var type of ["log", "error", "info"]) {
-        InspectorTest._originalConsoleMethods[type] = console[type].bind(console);
-        console[type] = createProxyConsoleHandler(type.toUpperCase());
-    }
-})();

Deleted: trunk/Source/WebInspectorUI/UserInterface/Base/TestStub.js (188543 => 188544)


--- trunk/Source/WebInspectorUI/UserInterface/Base/TestStub.js	2015-08-17 21:50:24 UTC (rev 188543)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/TestStub.js	2015-08-17 21:51:45 UTC (rev 188544)
@@ -1,480 +0,0 @@
-/*
- * Copyright (C) 2012 Samsung Electronics. All rights reserved.
- * Copyright (C) 2014, 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.
- */
-InspectorFrontendAPI = {};
-
-InjectedTestHarness = class InjectedTestHarness
-{
-    constructor()
-    {
-        this._logCount = 0;
-        this.forceSyncDebugLogging = false;
-    }
-
-    completeTest()
-    {
-        throw new Error("Must be implemented by subclasses.");
-    }
-
-    addResult()
-    {
-        throw new Error("Must be implemented by subclasses.");
-    }
-
-    debugLog()
-    {
-        throw new Error("Must be implemented by subclasses.");
-    }
-
-    evaluateInPage(string, callback)
-    {
-        throw new Error("Must be implemented by subclasses.");
-    }
-
-    createAsyncSuite(name)
-    {
-        return new InjectedTestHarness.AsyncTestSuite(this, name);
-    }
-
-    createSyncSuite(name)
-    {
-        return new InjectedTestHarness.SyncTestSuite(this, name);
-    }
-
-    get logCount()
-    {
-        return this._logCount;
-    }
-
-    log(message)
-    {
-        ++this._logCount;
-
-        if (this.forceSyncDebugLogging)
-            this.debugLog(message);
-        else
-            this.addResult(message);
-    }
-
-    assert(condition, message)
-    {
-        if (condition)
-            return;
-
-        let stringifiedMessage = typeof message !== "object" ? message : JSON.stringify(message);
-        this.addResult("ASSERT: " + stringifiedMessage);
-    }
-
-    expectThat(condition, message)
-    {
-        let prefix = condition ? "PASS" : "FAIL";
-        let stringifiedMessage = typeof message !== "object" ? message : JSON.stringify(message);
-        this.addResult(prefix + ": " + stringifiedMessage);
-    }
-}
-
-InjectedTestHarness.AsyncTestSuite = class AsyncTestSuite
-{
-    constructor(harness, name) {
-        if (!(harness instanceof InjectedTestHarness))
-            throw new Error("Must pass the test's harness as the first argument.");
-
-        if (!name || typeof name !== "string")
-            throw new Error("Tried to create AsyncTestSuite without string suite name.");
-
-        this.name = name;
-        this._harness = harness;
-
-        this.testcases = [];
-        this.runCount = 0;
-        this.failCount = 0;
-    }
-
-    get passCount()
-    {
-        return this.runCount - this.failCount;
-    }
-
-    get skipCount()
-    {
-        if (this.failCount)
-            return this.testcases.length - this.runCount;
-        else
-            return 0;
-    }
-
-    addTestCase(testcase)
-    {
-        if (!testcase || !(testcase instanceof Object))
-            throw new Error("Tried to add non-object test case.");
-
-        if (typeof testcase.name !== "string")
-            throw new Error("Tried to add test case without a name.");
-
-        if (typeof testcase.test !== "function")
-            throw new Error("Tried to add test case without `test` function.");
-
-        this.testcases.push(testcase);
-    }
-
-    // Use this if the test file only has one suite, and no handling
-    // of the promise returned by runTestCases() is needed.
-    runTestCasesAndFinish()
-    {
-        function finish() {
-            this._harness.completeTest();
-        }
-
-        this.runTestCases()
-            .then(finish.bind(this))
-            .catch(finish.bind(this));
-    }
-
-    runTestCases()
-    {
-        if (!this.testcases.length)
-            throw new Error("Tried to call runTestCases() for suite with no test cases");
-        if (this._startedRunning)
-            throw new Error("Tried to call runTestCases() more than once.");
-
-        this._startedRunning = true;
-
-        this._harness.log("");
-        this._harness.log("== Running test suite: " + this.name);
-
-        // Avoid adding newlines if nothing was logged.
-        var priorLogCount = this._harness.logCount;
-        var suite = this;
-        var result = this.testcases.reduce(function(chain, testcase, i) {
-            return chain.then(function() {
-                if (i > 0 && priorLogCount + 1 < suite._harness.logCount)
-                    suite._harness.log("");
-
-                priorLogCount = suite._harness.logCount;
-                suite._harness.log("-- Running test case: " + testcase.name);
-                suite.runCount++;
-                return new Promise(testcase.test);
-            });
-        }, Promise.resolve());
-
-        return result.catch(function(e) {
-            suite.failCount++;
-            var message = e;
-            if (e instanceof Error)
-                message = e.message;
-
-            if (typeof message !== "string")
-                message = JSON.stringify(message);
-
-            suite._harness.log("!! EXCEPTION: " + message);
-            throw e; // Reject this promise by re-throwing the error.
-        });
-    }
-}
-
-InjectedTestHarness.SyncTestSuite = class SyncTestSuite
-{
-    constructor(harness, name) {
-        if (!(harness instanceof InjectedTestHarness))
-            throw new Error("Must pass the test's harness as the first argument.");
-
-        if (!name || typeof name !== "string")
-            throw new Error("Tried to create SyncTestSuite without string suite name.");
-
-        this.name = name;
-        this._harness = harness;
-
-        this.testcases = [];
-        this.runCount = 0;
-        this.failCount = 0;
-    }
-
-    get passCount()
-    {
-        return this.runCount - this.failCount;
-    }
-
-    get skipCount()
-    {
-        if (this.failCount)
-            return this.testcases.length - this.runCount;
-        else
-            return 0;
-    }
-
-    addTestCase(testcase)
-    {
-        if (!testcase || !(testcase instanceof Object))
-            throw new Error("Tried to add non-object test case.");
-
-        if (typeof testcase.name !== "string")
-            throw new Error("Tried to add test case without a name.");
-
-        if (typeof testcase.test !== "function")
-            throw new Error("Tried to add test case without `test` function.");
-
-        this.testcases.push(testcase);
-    }
-
-    // Use this if the test file only has one suite.
-    runTestCasesAndFinish()
-    {
-        this.runTestCases();
-        this._harness.completeTest();
-    }
-
-    runTestCases()
-    {
-        if (!this.testcases.length)
-            throw new Error("Tried to call runTestCases() for suite with no test cases");
-        if (this._startedRunning)
-            throw new Error("Tried to call runTestCases() more than once.");
-
-        this._startedRunning = true;
-
-        this._harness.log("");
-        this._harness.log("== Running test suite: " + this.name);
-
-        var priorLogCount = this._harness.logCount;
-        var suite = this;
-        for (var i = 0; i < this.testcases.length; i++) {
-            var testcase = this.testcases[i];
-            if (i > 0 && priorLogCount + 1 < this._harness.logCount)
-                this._harness.log("");
-
-            priorLogCount = this._harness.logCount;
-
-            this._harness.log("-- Running test case: " + testcase.name);
-            suite.runCount++;
-            try {
-                var result = testcase.test.call(null);
-                if (result === false) {
-                    suite.failCount++;
-                    return false;
-                }
-            } catch (e) {
-                suite.failCount++;
-                var message = e;
-                if (e instanceof Error)
-                    message = e.message;
-                else
-                    e = new Error(e);
-
-                if (typeof message !== "string")
-                    message = JSON.stringify(message);
-
-                this._harness.log("!! EXCEPTION: " + message);
-                return false;
-            }
-        }
-
-        return true;
-    }
-}
-
-class ProtocolTestHarness extends InjectedTestHarness
-{
-    // InjectedTestHarness Overrides
-
-    completeTest()
-    {
-        this.evaluateInPage("closeTest();");
-    }
-
-    addResult(message)
-    {
-        // Unfortunately, every string argument must be escaped because tests are not consistent
-        // with respect to escaping with single or double quotes. Some exceptions use single quotes.
-        var stringifiedMessage = typeof message !== "string" ? JSON.stringify(message) : message;
-        this.evaluateInPage("log(unescape('" + escape(stringifiedMessage) + "'));");
-    }
-
-    debugLog(message)
-    {
-        var stringifiedMessage = typeof message !== "string" ? JSON.stringify(message) : message;
-        this.evaluateInPage("debugLog(unescape('" + escape(stringifiedMessage) + "'));")
-    }
-
-    evaluateInPage(_expression_, callback)
-    {
-        let args = {
-            method: "Runtime.evaluate",
-            params: {_expression_}
-        }
-
-        if (typeof callback === "function")
-            InspectorProtocol.sendCommand(args, callback);
-        else
-            return InspectorProtocol.awaitCommand(args);
-    }
-}
-
-window.ProtocolTest = new ProtocolTestHarness();
-
-InspectorProtocol = {};
-InspectorProtocol._dispatchTable = [];
-InspectorProtocol._requestId = -1;
-InspectorProtocol.eventHandler = {};
-
-InspectorProtocol.dumpInspectorProtocolMessages = false;
-
-InspectorProtocol.sendCommand = function(methodOrObject, params, handler)
-{
-    // Allow new-style arguments object, as in awaitCommand.
-    var method = methodOrObject;
-    if (typeof methodOrObject === "object")
-        var {method, params, handler} = methodOrObject;
-
-    this._dispatchTable[++this._requestId] = handler;
-    var messageObject = {method, params, "id": this._requestId};
-    this.sendMessage(messageObject);
-
-    return this._requestId;
-}
-
-InspectorProtocol.awaitCommand = function(args)
-{
-    var {method, params} = args;
-    return new Promise(function(resolve, reject) {
-        this._dispatchTable[++this._requestId] = {resolve, reject};
-        var messageObject = {method, params, "id": this._requestId};
-        this.sendMessage(messageObject);
-    }.bind(this));
-}
-
-InspectorProtocol.awaitEvent = function(args)
-{
-    var {event} = args;
-    if (typeof event !== "string")
-        throw new Error("Event must be a string.");
-
-    return new Promise(function(resolve, reject) {
-        InspectorProtocol.eventHandler[event] = function(message) {
-            InspectorProtocol.eventHandler[event] = undefined;
-            resolve(message);
-        }
-    });
-}
-
-InspectorProtocol.addEventListener = function(eventTypeOrObject, listener)
-{
-    var event = eventTypeOrObject;
-    if (typeof eventTypeOrObject === "object")
-        var {event, listener} = eventTypeOrObject;
-
-    if (typeof event !== "string")
-        throw new Error("Event name must be a string.");
-
-    if (typeof listener !== "function")
-        throw new Error("Event listener must be callable.");
-
-    // Convert to an array of listeners.
-    var listeners = InspectorProtocol.eventHandler[event];
-    if (!listeners)
-        listeners = InspectorProtocol.eventHandler[event] = [];
-    else if (typeof listeners === "function")
-        listeners = InspectorProtocol.eventHandler[event] = [listeners];
-
-    // Prevent registering multiple times.
-    if (listeners.includes(listener))
-        throw new Error("Cannot register the same listener more than once.");
-
-    listeners.push(listener);
-}
-
-InspectorProtocol.sendMessage = function(messageObject)
-{
-    // This matches the debug dumping in InspectorBackend, which is bypassed
-    // by InspectorProtocol. Return messages should be dumped by InspectorBackend.
-    if (InspectorProtocol.dumpInspectorProtocolMessages)
-        console.log("frontend: " + JSON.stringify(messageObject));
-
-    InspectorFrontendHost.sendMessageToBackend(JSON.stringify(messageObject));
-}
-
-InspectorProtocol.checkForError = function(responseObject)
-{
-    if (responseObject.error) {
-        ProtocolTest.log("PROTOCOL ERROR: " + JSON.stringify(responseObject.error));
-        ProtocolTest.completeTest();
-        throw "PROTOCOL ERROR";
-    }
-}
-
-InspectorFrontendAPI.dispatchMessageAsync = function(messageObject)
-{
-    // This matches the debug dumping in InspectorBackend, which is bypassed
-    // by InspectorProtocol. Return messages should be dumped by InspectorBackend.
-    if (InspectorProtocol.dumpInspectorProtocolMessages)
-        console.log("backend: " + JSON.stringify(messageObject));
-
-    // If the message has an id, then it is a reply to a command.
-    var messageId = messageObject["id"];
-    if (typeof messageId === "number") {
-        var handler = InspectorProtocol._dispatchTable[messageId];
-        if (!handler)
-            return;
-
-        if (typeof handler === "function")
-            handler(messageObject);
-        else if (typeof handler === "object") {
-            var {resolve, reject} = handler;
-            if ("error" in messageObject)
-                reject(messageObject.error.message);
-            else
-                resolve(messageObject.result);
-        }
-    // Otherwise, it is an event.
-    } else {
-        var eventName = messageObject["method"];
-        var handler = InspectorProtocol.eventHandler[eventName];
-        if (!handler)
-            return;
-
-        if (typeof handler === "function")
-            handler(messageObject);
-        else if (handler instanceof Array) {
-            handler.map(function(listener) {
-                listener.call(null, messageObject);
-            });
-        } else if (typeof handler === "object") {
-            var {resolve, reject} = handler;
-            if ("error" in messageObject)
-                reject(messageObject.error.message);
-            else
-                resolve(messageObject.result);
-        }
-    }
-}
-
-window.addEventListener("message", function(event) {
-    try {
-        eval(event.data);
-    } catch (e) {
-        alert(e.stack);
-        ProtocolTest.completeTest();
-        throw e;
-    }
-});
\ No newline at end of file

Added: trunk/Source/WebInspectorUI/UserInterface/Test/InspectorProtocol.js (0 => 188544)


--- trunk/Source/WebInspectorUI/UserInterface/Test/InspectorProtocol.js	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Test/InspectorProtocol.js	2015-08-17 21:51:45 UTC (rev 188544)
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics. All rights reserved.
+ * Copyright (C) 2014, 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.
+ */
+
+InspectorProtocol = {};
+InspectorProtocol._dispatchTable = [];
+InspectorProtocol._requestId = -1;
+InspectorProtocol.eventHandler = {};
+
+InspectorProtocol.sendCommand = function(methodOrObject, params, handler)
+{
+    // Allow new-style arguments object, as in awaitCommand.
+    let method = methodOrObject;
+    if (typeof methodOrObject === "object")
+        var {method, params, handler} = methodOrObject;
+
+    this._dispatchTable[++this._requestId] = handler;
+    let messageObject = {method, params, id: this._requestId};
+    this.sendMessage(messageObject);
+
+    return this._requestId;
+}
+
+InspectorProtocol.awaitCommand = function(args)
+{
+    let {method, params} = args;
+    return new Promise(function(resolve, reject) {
+        this._dispatchTable[++this._requestId] = {resolve, reject};
+        let messageObject = {method, params, id: this._requestId};
+        this.sendMessage(messageObject);
+    }.bind(this));
+}
+
+InspectorProtocol.awaitEvent = function(args)
+{
+    let event = args.event;
+    if (typeof event !== "string")
+        throw new Error("Event must be a string.");
+
+    return new Promise(function(resolve, reject) {
+        InspectorProtocol.eventHandler[event] = function(message) {
+            InspectorProtocol.eventHandler[event] = undefined;
+            resolve(message);
+        }
+    });
+}
+
+InspectorProtocol.addEventListener = function(eventTypeOrObject, listener)
+{
+    let event = eventTypeOrObject;
+    if (typeof eventTypeOrObject === "object")
+        var {event, listener} = eventTypeOrObject;
+
+    if (typeof event !== "string")
+        throw new Error("Event name must be a string.");
+
+    if (typeof listener !== "function")
+        throw new Error("Event listener must be callable.");
+
+    // Convert to an array of listeners.
+    let listeners = InspectorProtocol.eventHandler[event];
+    if (!listeners)
+        listeners = InspectorProtocol.eventHandler[event] = [];
+    else if (typeof listeners === "function")
+        listeners = InspectorProtocol.eventHandler[event] = [listeners];
+
+    // Prevent registering multiple times.
+    if (listeners.includes(listener))
+        throw new Error("Cannot register the same listener more than once.");
+
+    listeners.push(listener);
+}
+
+InspectorProtocol.sendMessage = function(messageObject)
+{
+    // This matches the debug dumping in InspectorBackend, which is bypassed
+    // by InspectorProtocol. Return messages should be dumped by InspectorBackend.
+    if (ProtocolTest.dumpInspectorProtocolMessages)
+        console.log("frontend: " + JSON.stringify(messageObject));
+
+    InspectorFrontendHost.sendMessageToBackend(JSON.stringify(messageObject));
+}
+
+InspectorProtocol.checkForError = function(responseObject)
+{
+    if (responseObject.error) {
+        ProtocolTest.log("PROTOCOL ERROR: " + JSON.stringify(responseObject.error));
+        ProtocolTest.completeTest();
+        throw "PROTOCOL ERROR";
+    }
+}
+
+InspectorProtocol.dispatchMessageFromBackend = function(messageObject)
+{
+    // This matches the debug dumping in InspectorBackend, which is bypassed
+    // by InspectorProtocol. Return messages should be dumped by InspectorBackend.
+    if (ProtocolTest.dumpInspectorProtocolMessages)
+        console.log("backend: " + JSON.stringify(messageObject));
+
+    // If the message has an id, then it is a reply to a command.
+    let messageId = messageObject.id;
+    if (typeof messageId === "number") {
+        let handler = InspectorProtocol._dispatchTable[messageId];
+        if (!handler)
+            return;
+
+        if (typeof handler === "function")
+            handler(messageObject);
+        else if (typeof handler === "object") {
+            let {resolve, reject} = handler;
+            if ("error" in messageObject)
+                reject(messageObject.error.message);
+            else
+                resolve(messageObject.result);
+        }
+    // Otherwise, it is an event.
+    } else {
+        let eventName = messageObject["method"];
+        let handler = InspectorProtocol.eventHandler[eventName];
+        if (!handler)
+            return;
+
+        if (typeof handler === "function")
+            handler(messageObject);
+        else if (handler instanceof Array) {
+            handler.map(function(listener) {
+                listener.call(null, messageObject);
+            });
+        } else if (typeof handler === "object") {
+            let {resolve, reject} = handler;
+            if ("error" in messageObject)
+                reject(messageObject.error.message);
+            else
+                resolve(messageObject.result);
+        }
+    }
+}
\ No newline at end of file

Added: trunk/Source/WebInspectorUI/UserInterface/Test/ProtocolTestHarness.js (0 => 188544)


--- trunk/Source/WebInspectorUI/UserInterface/Test/ProtocolTestHarness.js	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Test/ProtocolTestHarness.js	2015-08-17 21:51:45 UTC (rev 188544)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 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.
+ */
+
+ProtocolTestHarness = class ProtocolTestHarness extends TestHarness
+{
+    // TestHarness Overrides
+
+    completeTest()
+    {
+        this.evaluateInPage("TestPage.closeTest();");
+    }
+
+    addResult(message)
+    {
+        // Unfortunately, every string argument must be escaped because tests are not consistent
+        // with respect to escaping with single or double quotes. Some exceptions use single quotes.
+        let stringifiedMessage = typeof message !== "string" ? JSON.stringify(message) : message;
+        this.evaluateInPage(`TestPage.log(unescape("${escape(stringifiedMessage)}"));`);
+    }
+
+    debugLog(message)
+    {
+        let stringifiedMessage = typeof message !== "string" ? JSON.stringify(message) : message;
+        this.evaluateInPage(`TestPage.debugLog(unescape("${escape(stringifiedMessage)}"));`);
+    }
+
+    evaluateInPage(_expression_, callback)
+    {
+        let args = {
+            method: "Runtime.evaluate",
+            params: {_expression_}
+        }
+
+        if (typeof callback === "function")
+            InspectorProtocol.sendCommand(args, callback);
+        else
+            return InspectorProtocol.awaitCommand(args);
+    }
+}

Copied: trunk/Source/WebInspectorUI/UserInterface/Test/Test.js (from rev 188542, trunk/Source/WebInspectorUI/UserInterface/Base/Test.js) (0 => 188544)


--- trunk/Source/WebInspectorUI/UserInterface/Test/Test.js	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Test/Test.js	2015-08-17 21:51:45 UTC (rev 188544)
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2013, 2014 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * HOLDER OR 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.
+ */
+
+WebInspector.DebuggableType = {
+    Web: "web",
+    _javascript_: "_javascript_"
+};
+
+WebInspector.loaded = function()
+{
+    this.debuggableType = WebInspector.DebuggableType.Web;
+    this.hasExtraDomains = false;
+
+    // Register observers for events from the InspectorBackend.
+    // The initialization order should match the same in Main.js.
+    InspectorBackend.registerInspectorDispatcher(new WebInspector.InspectorObserver);
+    InspectorBackend.registerPageDispatcher(new WebInspector.PageObserver);
+    InspectorBackend.registerConsoleDispatcher(new WebInspector.ConsoleObserver);
+    InspectorBackend.registerDOMDispatcher(new WebInspector.DOMObserver);
+    InspectorBackend.registerNetworkDispatcher(new WebInspector.NetworkObserver);
+    InspectorBackend.registerDebuggerDispatcher(new WebInspector.DebuggerObserver);
+    InspectorBackend.registerTimelineDispatcher(new WebInspector.TimelineObserver);
+    InspectorBackend.registerCSSDispatcher(new WebInspector.CSSObserver);
+    InspectorBackend.registerRuntimeDispatcher(new WebInspector.RuntimeObserver);
+    if (InspectorBackend.registerReplayDispatcher)
+        InspectorBackend.registerReplayDispatcher(new WebInspector.ReplayObserver);
+
+    // Instantiate controllers used by tests.
+    this.frameResourceManager = new WebInspector.FrameResourceManager;
+    this.domTreeManager = new WebInspector.DOMTreeManager;
+    this.cssStyleManager = new WebInspector.CSSStyleManager;
+    this.logManager = new WebInspector.LogManager;
+    this.issueManager = new WebInspector.IssueManager;
+    this.runtimeManager = new WebInspector.RuntimeManager;
+    this.timelineManager = new WebInspector.TimelineManager;
+    this.debuggerManager = new WebInspector.DebuggerManager;
+    this.probeManager = new WebInspector.ProbeManager;
+    this.replayManager = new WebInspector.ReplayManager;
+
+    // Global controllers.
+    this.quickConsole = {executionContextIdentifier: undefined};
+
+    document.addEventListener("DOMContentLoaded", this.contentLoaded.bind(this));
+
+    // Enable agents.
+    InspectorAgent.enable();
+    ConsoleAgent.enable();
+
+    // Perform one-time tasks.
+    WebInspector.CSSCompletions.requestCSSCompletions();
+
+    // Global settings.
+    this.showShadowDOMSetting = new WebInspector.Setting("show-shadow-dom", true);
+}
+
+WebInspector.contentLoaded = function()
+{
+    // Signal that the frontend is now ready to receive messages.
+    InspectorFrontendAPI.loadCompleted();
+
+    // Tell the InspectorFrontendHost we loaded, which causes the window to display
+    // and pending InspectorFrontendAPI commands to be sent.
+    InspectorFrontendHost.loaded();
+}
+
+WebInspector.UIString = function(string)
+{
+    return 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);
+
+// Redirect frontend console methods to log messages into the test result.
+(function() {
+    function createProxyConsoleHandler(type) {
+        return function() {
+            InspectorTest.addResult(type + ": " + Array.from(arguments).join(" "));
+        };
+    }
+
+    for (var type of ["log", "error", "info"]) {
+        InspectorTest._originalConsoleMethods[type] = console[type].bind(console);
+        console[type] = createProxyConsoleHandler(type.toUpperCase());
+    }
+})();

Added: trunk/Source/WebInspectorUI/UserInterface/Test/TestHarness.js (0 => 188544)


--- trunk/Source/WebInspectorUI/UserInterface/Test/TestHarness.js	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Test/TestHarness.js	2015-08-17 21:51:45 UTC (rev 188544)
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 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.
+ */
+
+TestHarness = class TestHarness extends WebInspector.Object
+{
+    constructor()
+    {
+        super();
+
+        this._logCount = 0;
+    }
+
+    completeTest()
+    {
+        throw new Error("Must be implemented by subclasses.");
+    }
+
+    addResult()
+    {
+        throw new Error("Must be implemented by subclasses.");
+    }
+
+    debugLog()
+    {
+        throw new Error("Must be implemented by subclasses.");
+    }
+
+    evaluateInPage(string, callback)
+    {
+        throw new Error("Must be implemented by subclasses.");
+    }
+
+    createAsyncSuite(name)
+    {
+        return new AsyncTestSuite(this, name);
+    }
+
+    createSyncSuite(name)
+    {
+        return new SyncTestSuite(this, name);
+    }
+
+    get logCount()
+    {
+        return this._logCount;
+    }
+
+    log(message)
+    {
+        ++this._logCount;
+
+        if (this.forceSyncDebugLogging)
+            this.debugLog(message);
+        else
+            this.addResult(message);
+    }
+
+    assert(condition, message)
+    {
+        if (condition)
+            return;
+
+        let stringifiedMessage = typeof message !== "object" ? message : JSON.stringify(message);
+        this.addResult("ASSERT: " + stringifiedMessage);
+    }
+
+    expectThat(condition, message)
+    {
+        let prefix = condition ? "PASS" : "FAIL";
+        let stringifiedMessage = typeof message !== "object" ? message : JSON.stringify(message);
+        this.addResult(`${prefix}: ${stringifiedMessage}`);
+    }
+};

Added: trunk/Source/WebInspectorUI/UserInterface/Test/TestStub.js (0 => 188544)


--- trunk/Source/WebInspectorUI/UserInterface/Test/TestStub.js	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Test/TestStub.js	2015-08-17 21:51:45 UTC (rev 188544)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics. All rights reserved.
+ * Copyright (C) 2014, 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.
+ */
+
+InspectorFrontendAPI = {};
+InspectorFrontendAPI.dispatchMessageAsync = InspectorProtocol.dispatchMessageFromBackend;
+
+window.ProtocolTest = new ProtocolTestHarness();
+
+window.addEventListener("message", function(event) {
+    try {
+        eval(event.data);
+    } catch (e) {
+        alert(e.stack);
+        ProtocolTest.completeTest();
+        throw e;
+    }
+});

Added: trunk/Source/WebInspectorUI/UserInterface/Test/TestSuite.js (0 => 188544)


--- trunk/Source/WebInspectorUI/UserInterface/Test/TestSuite.js	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Test/TestSuite.js	2015-08-17 21:51:45 UTC (rev 188544)
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 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.
+ */
+
+TestSuite = class TestSuite extends WebInspector.Object
+{
+    constructor(harness, name) {
+        if (!(harness instanceof TestHarness))
+            throw new Error("Must pass the test's harness as the first argument.");
+
+        if (typeof name !== "string" || !name.trim().length)
+            throw new Error("Tried to create TestSuite without string suite name.");
+
+        super();
+
+        this.name = name;
+        this._harness = harness;
+
+        this.testcases = [];
+        this.runCount = 0;
+        this.failCount = 0;
+    }
+
+    // Use this if the test file only has one suite, and no handling
+    // of the value returned by runTestCases() is needed.
+    runTestCasesAndFinish()
+    {
+        throw new Error("Must be implemented by subclasses.");
+    }
+
+    runTestCases()
+    {
+        throw new Error("Must be implemented by subclasses.");
+    }
+
+    get passCount()
+    {
+        return this.runCount - this.failCount;
+    }
+
+    get skipCount()
+    {
+        if (this.failCount)
+            return this.testcases.length - this.runCount;
+        else
+            return 0;
+    }
+
+    addTestCase(testcase)
+    {
+        if (!testcase || !(testcase instanceof Object))
+            throw new Error("Tried to add non-object test case.");
+
+        if (typeof testcase.name !== "string" || !testcase.name.trim().length)
+            throw new Error("Tried to add test case without a name.");
+
+        if (typeof testcase.test !== "function")
+            throw new Error("Tried to add test case without `test` function.");
+
+        this.testcases.push(testcase);
+    }
+};
+
+AsyncTestSuite = class AsyncTestSuite extends TestSuite
+{
+    runTestCasesAndFinish()
+    {
+        function finish() {
+            this._harness.completeTest();
+        }
+
+        this.runTestCases()
+            .then(finish.bind(this))
+            .catch(finish.bind(this));
+    }
+
+    runTestCases()
+    {
+        if (!this.testcases.length)
+            throw new Error("Tried to call runTestCases() for suite with no test cases");
+        if (this._startedRunning)
+            throw new Error("Tried to call runTestCases() more than once.");
+
+        this._startedRunning = true;
+
+        this._harness.log("");
+        this._harness.log("== Running test suite: " + this.name);
+
+        // Avoid adding newlines if nothing was logged.
+        let priorLogCount = this._harness.logCount;
+        let self = this;
+        let result = this.testcases.reduce(function(chain, testcase, i) {
+            return chain.then(function() {
+                if (i > 0 && priorLogCount + 1 < self._harness.logCount)
+                    self._harness.log("");
+
+                priorLogCount = self._harness.logCount;
+                self._harness.log("-- Running test case: " + testcase.name);
+                self.runCount++;
+                return new Promise(testcase.test);
+            });
+        }, Promise.resolve());
+
+        return result.catch(function(e) {
+            self.failCount++;
+            let message = e;
+            if (e instanceof Error)
+                message = e.message;
+
+            if (typeof message !== "string")
+                message = JSON.stringify(message);
+
+            self._harness.log("!! EXCEPTION: " + message);
+            throw e; // Reject this promise by re-throwing the error.
+        });
+    }
+};
+
+SyncTestSuite = class SyncTestSuite extends TestSuite
+{
+    runTestCasesAndFinish()
+    {
+        this.runTestCases();
+        this._harness.completeTest();
+    }
+
+    runTestCases()
+    {
+        if (!this.testcases.length)
+            throw new Error("Tried to call runTestCases() for suite with no test cases");
+        if (this._startedRunning)
+            throw new Error("Tried to call runTestCases() more than once.");
+
+        this._startedRunning = true;
+
+        this._harness.log("");
+        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)
+                this._harness.log("");
+
+            priorLogCount = this._harness.logCount;
+
+            this._harness.log("-- Running test case: " + testcase.name);
+            self.runCount++;
+            try {
+                let result = testcase.test.call(null);
+                if (result === false) {
+                    self.failCount++;
+                    return false;
+                }
+            } catch (e) {
+                self.failCount++;
+                let message = e;
+                if (e instanceof Error)
+                    message = e.message;
+                else
+                    e = new Error(e);
+
+                if (typeof message !== "string")
+                    message = JSON.stringify(message);
+
+                this._harness.log("!! EXCEPTION: " + message);
+                return false;
+            }
+        }
+
+        return true;
+    }
+};

Modified: trunk/Source/WebInspectorUI/UserInterface/Test.html (188543 => 188544)


--- trunk/Source/WebInspectorUI/UserInterface/Test.html	2015-08-17 21:50:24 UTC (rev 188543)
+++ trunk/Source/WebInspectorUI/UserInterface/Test.html	2015-08-17 21:51:45 UTC (rev 188544)
@@ -32,7 +32,7 @@
     <script src=""
     <script src=""
 
-    <script src=""
+    <script src=""
 
     <script src=""
     <script src=""

Modified: trunk/Source/WebInspectorUI/UserInterface/TestStub.html (188543 => 188544)


--- trunk/Source/WebInspectorUI/UserInterface/TestStub.html	2015-08-17 21:50:24 UTC (rev 188543)
+++ trunk/Source/WebInspectorUI/UserInterface/TestStub.html	2015-08-17 21:51:45 UTC (rev 188544)
@@ -22,8 +22,29 @@
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 -->
+<!DOCTYPE html>
 <html>
 <head>
-    <script type="text/_javascript_" src=""
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+    <!--
+    These resources should match the order and groups used in Main.html and Test.html.
+    -->
+    <script src=""
+    <script src=""
+
+    <script src=""
+    <script src=""
+    <script src=""
+
+    <script src=""
+
+    <script src=""
+    <script>
+        // Not reliable unless console messages are dumped to console. See wiki for details.
+        ProtocolTest.dumpInspectorProtocolMessages = false;
+
+        // Synchronous logging may produce more output prior to a timeout.
+        ProtocolTest.forceSyncDebugLogging = false;
+    </script>
 </head>
 </html>
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to