Index: headless/test/test_harness.js |
diff --git a/headless/test/test_harness.js b/headless/test/test_harness.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..865d0e2160ad268e3916ba581d29a5ca74ceb9d0 |
--- /dev/null |
+++ b/headless/test/test_harness.js |
@@ -0,0 +1,185 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
Sami
2017/05/24 09:16:22
Could we reuse an existing test framework (jstest?
alex clarke (OOO till 29th)
2017/05/24 11:38:17
Is that in chromium somewhere?
Sami
2017/05/25 17:53:35
Sorry, meant testharness.js. See here: https://cs.
alex clarke (OOO till 29th)
2017/05/26 11:37:02
As discussed offline I refactored the test se we d
|
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+goog.require('goog.DevTools.Connection'); |
+goog.provide('goog.DevTools.TestHarness'); |
+ |
+goog.scope(function() { |
+ |
+/** |
+ * The DevTools connection |
+ * |
+ * @private {!goog.DevTools.Connection} |
+ */ |
+goog.DevTools.TestHarness.connection_ = |
+ new goog.DevTools.Connection(window.TabSocket); |
+ |
+/** |
+ * Asks the C++ test harness to quit. |
+ * |
+ * @private |
+ */ |
+goog.DevTools.TestHarness.QuitTest_ = function() { |
+ goog.DevTools.TestHarness.connection_.SendDevToolsMessage('__QuitTest', {}); |
+}; |
+ |
+/** |
+ * Used to report a test failure. |
+ * |
+ * @param {string} error The error message to report. |
+ */ |
+goog.DevTools.TestHarness.FailTest = function(error) { |
+ goog.DevTools.TestHarness.connection_.SendDevToolsMessage('__FailTest', |
+ {"error": error}); |
+}; |
+ |
+/** |
+ * Asks the C++ test harness to log a message. |
+ * |
+ * @param {string} message The message to report. |
+ */ |
+goog.DevTools.TestHarness.Log = function(message) { |
+ goog.DevTools.TestHarness.connection_.SendDevToolsMessage( |
+ '__Log', {"message": message}); |
+}; |
+ |
+/** |
+ * @class A simple asynchronous test class. |
+ * @param {!goog.DevTools.Connection} connection The DevTools connection. |
+ * @param {string} testName The name of the test to run. |
+ * @param {!function(!goog.DevTools.Test)} testFunction The test function |
+ * @constructor |
+ */ |
+goog.DevTools.Test = function(connection, testName, testFunction) { |
+ /** |
+ * @type {!goog.DevTools.Connection} |
+ */ |
+ this.connection_ = connection; |
+ |
+ /** |
+ * @type {string} |
+ */ |
+ this.testName_ = testName; |
+ |
+ /** |
+ * @type {!function(!goog.DevTools.Test)} |
+ */ |
+ this.testFunction_ = testFunction; |
+ |
+ /** |
+ * @private {boolean} |
+ */ |
+ this.testPassed_ = true; |
+}; |
+ |
+/** |
+ * Used to report a test failure. |
+ * |
+ * @param {string} error The error message to report. |
+ */ |
+goog.DevTools.Test.prototype.Fail = function(error) { |
+ this.testPassed_ = false; |
+ goog.DevTools.TestHarness.Log(error); |
+}; |
+ |
+ |
+/** |
+ * Compares two JavaScript values for type and value equality. |
+ * It checks internals of arrays and objects. |
+ */ |
+function deepEquals(a, b) { |
+ if (a === b) { |
+ // Check for -0. |
+ if (a === 0) return (1 / a) === (1 / b); |
+ return true; |
+ } |
+ if (typeof a != typeof b) return false; |
+ if (typeof a == 'number') return isNaN(a) && isNaN(b); |
+ if (typeof a !== 'object' && typeof a !== 'function') return false; |
+ // Neither a nor b is primitive. |
+ var objectClass = classOf(a); |
+ if (objectClass !== classOf(b)) return false; |
+ if (objectClass === 'RegExp') { |
+ // For RegExp, just compare pattern and flags using its toString. |
+ return (a.toString() === b.toString()); |
+ } |
+ // Functions are only identical to themselves. |
+ if (objectClass === 'Function') return false; |
+ if (objectClass === 'Array') { |
+ var elementCount = 0; |
+ if (a.length != b.length) { |
+ return false; |
+ } |
+ for (var i = 0; i < a.length; i++) { |
+ if (!deepEquals(a[i], b[i])) return false; |
+ } |
+ return true; |
+ } |
+ if (objectClass == 'String' || objectClass == 'Number' || |
+ objectClass == 'Boolean' || objectClass == 'Date') { |
+ if (a.valueOf() !== b.valueOf()) return false; |
+ } |
+ return deepObjectEquals(a, b); |
+} |
+ |
+ |
+/** |
+ * @param {*} expected The expected result. |
+ * @param {*} found The value found. |
+ * @param {string=} opt_message Optional message. |
+ */ |
+goog.DevTools.Test.prototype.AssertEq = function(expected, found, opt_message) { |
+ if (!deepEquals(expected, found)) { |
+ this.Fail('Expected \'' + JSON.stringify(expected) +'\' but found \'' + |
+ JSON.stringify(found) + '\' ' + (opt_message ? opt_message : '')); |
+ } |
+}; |
+ |
+ |
+/** |
+ * Used to report the end of the test. |
+ */ |
+goog.DevTools.Test.prototype.Finish = function() { |
+ if (this.testPassed_) { |
+ goog.DevTools.TestHarness.Log('[ OK ] ' + this.testName_); |
+ goog.DevTools.TestHarness.RunTests(); |
+ } else { |
+ goog.DevTools.TestHarness.FailTest('[ FAIL ] ' + this.testName_); |
+ } |
+}; |
+ |
+ |
+/** |
+ * The tests to run. |
+ * |
+ * @private {!Array.<!goog.DevTools.Test>} |
+ */ |
+goog.DevTools.TestHarness.tests_ = []; |
+ |
+/** |
+ * Asks the C++ test harness to quit and report an error. |
+ * |
+ * @param {string} testName The name of the test to run. |
+ * @param {!function(!goog.DevTools.Test)} testFunction A test to run. |
+ */ |
+goog.DevTools.TestHarness.AddTest = function(testName, testFunction) { |
+ goog.DevTools.TestHarness.tests_.push( |
+ new goog.DevTools.Test(goog.DevTools.TestHarness.connection_, testName, |
+ testFunction)); |
+}; |
+ |
+/** |
+ * Runs the next test in the list. |
+ */ |
+goog.DevTools.TestHarness.RunTests = function() { |
+ let test = goog.DevTools.TestHarness.tests_.shift(); |
+ if (test === undefined) { |
+ goog.DevTools.TestHarness.QuitTest_(); |
+ } else { |
+ goog.DevTools.TestHarness.Log('[ RUN ] ' + test.testName_); |
+ test.testFunction_(test); |
+ } |
+}; |
+ |
+}); // goog.scope |