diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebInspectorUI/UserInterface/Test/FrontendTestHarness.js | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebInspectorUI/UserInterface/Test/FrontendTestHarness.js')
-rw-r--r-- | Source/WebInspectorUI/UserInterface/Test/FrontendTestHarness.js | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/Source/WebInspectorUI/UserInterface/Test/FrontendTestHarness.js b/Source/WebInspectorUI/UserInterface/Test/FrontendTestHarness.js new file mode 100644 index 000000000..5d9bb202e --- /dev/null +++ b/Source/WebInspectorUI/UserInterface/Test/FrontendTestHarness.js @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +FrontendTestHarness = class FrontendTestHarness extends TestHarness +{ + constructor() + { + super(); + + this._results = []; + this._shouldResendResults = true; + + // Options that are set per-test for debugging purposes. + this.dumpActivityToSystemConsole = false; + } + + // TestHarness Overrides + + completeTest() + { + if (this.dumpActivityToSystemConsole) + InspectorFrontendHost.unbufferedLog("completeTest()"); + + // Wait for results to be resent before requesting completeTest(). Otherwise, messages will be + // queued after pending dispatches run to zero and the test page will quit before processing them. + if (this._testPageIsReloading) { + this._completeTestAfterReload = true; + return; + } + + InspectorBackend.runAfterPendingDispatches(this.evaluateInPage.bind(this, "TestPage.completeTest()")); + } + + addResult(message) + { + let stringifiedMessage = TestHarness.messageAsString(message); + + // Save the stringified message, since message may be a DOM element that won't survive reload. + this._results.push(stringifiedMessage); + + if (this.dumpActivityToSystemConsole) + InspectorFrontendHost.unbufferedLog(stringifiedMessage); + + if (!this._testPageIsReloading) + this.evaluateInPage(`TestPage.addResult(unescape("${escape(stringifiedMessage)}"))`); + } + + debugLog(message) + { + let stringifiedMessage = TestHarness.messageAsString(message); + + if (this.dumpActivityToSystemConsole) + InspectorFrontendHost.unbufferedLog(stringifiedMessage); + + this.evaluateInPage(`TestPage.debugLog(unescape("${escape(stringifiedMessage)}"));`); + } + + evaluateInPage(expression, callback) + { + // If we load this page outside of the inspector, or hit an early error when loading + // the test frontend, then defer evaluating the commands (indefinitely in the former case). + if (this._originalConsole && !window.RuntimeAgent) { + this._originalConsole["error"]("Tried to evaluate in test page, but connection not yet established:", expression); + return; + } + + RuntimeAgent.evaluate.invoke({expression, objectGroup: "test", includeCommandLineAPI: false}, callback); + } + + debug() + { + this.dumpActivityToSystemConsole = true; + InspectorBackend.dumpInspectorProtocolMessages = true; + } + + // Frontend test-specific methods. + + expectNoError(error) + { + if (error) { + InspectorTest.log("PROTOCOL ERROR: " + error); + InspectorTest.completeTest(); + throw "PROTOCOL ERROR"; + } + } + + testPageDidLoad() + { + if (this.dumpActivityToSystemConsole) + InspectorFrontendHost.unbufferedLog("testPageDidLoad()"); + + this._testPageIsReloading = false; + this._resendResults(); + + this.dispatchEventToListeners(FrontendTestHarness.Event.TestPageDidLoad); + + if (this._completeTestAfterReload) + this.completeTest(); + } + + reloadPage(shouldIgnoreCache) + { + console.assert(!this._testPageIsReloading); + console.assert(!this._testPageReloadedOnce); + + this._testPageIsReloading = true; + + return PageAgent.reload(!!shouldIgnoreCache) + .then(() => { + this._shouldResendResults = true; + this._testPageReloadedOnce = true; + + return Promise.resolve(null); + }); + } + + redirectConsoleToTestOutput() + { + // We can't use arrow functions here because of 'arguments'. It might + // be okay once rest parameters work. + let self = this; + function createProxyConsoleHandler(type) { + return function() { + self.addResult(`${type}: ` + Array.from(arguments).join(" ")); + }; + } + + function createProxyConsoleTraceHandler(){ + return function() { + try { + throw new Exception(); + } catch (e) { + // Skip the first frame which is added by this function. + let frames = e.stack.split("\n").slice(1); + let sanitizedFrames = frames.map(TestHarness.sanitizeStackFrame); + self.addResult("TRACE: " + Array.from(arguments).join(" ")); + self.addResult(sanitizedFrames.join("\n")); + } + }; + } + + let redirectedMethods = {}; + for (let key in window.console) + redirectedMethods[key] = window.console[key]; + + for (let type of ["log", "error", "info", "warn"]) + redirectedMethods[type] = createProxyConsoleHandler(type.toUpperCase()); + + redirectedMethods["trace"] = createProxyConsoleTraceHandler(); + + this._originalConsole = window.console; + window.console = redirectedMethods; + } + + reportUnhandledRejection(error) + { + let message = error.message; + let stack = error.stack; + let result = `Unhandled promise rejection in inspector page: ${message}\n`; + if (stack) { + let sanitizedStack = this.sanitizeStack(stack); + result += `\nStack Trace: ${sanitizedStack}\n`; + } + + // If the connection to the test page is not set up, then just dump to console and give up. + // Errors encountered this early can be debugged by loading Test.html in a normal browser page. + if (this._originalConsole && !this._testPageHasLoaded()) + this._originalConsole["error"](result); + + this.addResult(result); + this.completeTest(); + + // Stop default handler so we can empty InspectorBackend's message queue. + return true; + } + + reportUncaughtExceptionFromEvent(message, url, lineNumber, columnNumber) + { + // An exception thrown from a timer callback does not report a URL. + if (url === "undefined") + url = "global"; + + return this.reportUncaughtException({message, url, lineNumber, columnNumber}); + } + + reportUncaughtException({message, url, lineNumber, columnNumber, stack, code}) + { + let result; + let sanitizedURL = TestHarness.sanitizeURL(url); + let sanitizedStack = this.sanitizeStack(stack); + if (url || lineNumber || columnNumber) + result = `Uncaught exception in Inspector page: ${message} [${sanitizedURL}:${lineNumber}:${columnNumber}]\n`; + else + result = `Uncaught exception in Inspector page: ${message}\n`; + + if (stack) + result += `\nStack Trace:\n${sanitizedStack}\n`; + if (code) + result += `\nEvaluated Code:\n${code}`; + + // If the connection to the test page is not set up, then just dump to console and give up. + // Errors encountered this early can be debugged by loading Test.html in a normal browser page. + if (this._originalConsole && !this._testPageHasLoaded()) + this._originalConsole["error"](result); + + this.addResult(result); + this.completeTest(); + // Stop default handler so we can empty InspectorBackend's message queue. + return true; + } + + // Private + + _testPageHasLoaded() + { + return self._shouldResendResults; + } + + _resendResults() + { + console.assert(this._shouldResendResults); + this._shouldResendResults = false; + + if (this.dumpActivityToSystemConsole) + InspectorFrontendHost.unbufferedLog("_resendResults()"); + + for (let result of this._results) + this.evaluateInPage(`TestPage.addResult(unescape("${escape(result)}"))`); + } +}; + +FrontendTestHarness.Event = { + TestPageDidLoad: "frontend-test-test-page-did-load" +}; |