diff options
Diffstat (limited to 'devtools/server/tests/browser/head.js')
-rw-r--r-- | devtools/server/tests/browser/head.js | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/devtools/server/tests/browser/head.js b/devtools/server/tests/browser/head.js new file mode 100644 index 000000000..1e7f09d95 --- /dev/null +++ b/devtools/server/tests/browser/head.js @@ -0,0 +1,203 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var Cc = Components.classes; +var Ci = Components.interfaces; +var Cu = Components.utils; + +const {console} = Cu.import("resource://gre/modules/Console.jsm", {}); +const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {}); +const {DebuggerClient} = require("devtools/shared/client/main"); +const {DebuggerServer} = require("devtools/server/main"); +const {defer} = require("promise"); +const DevToolsUtils = require("devtools/shared/DevToolsUtils"); +const Services = require("Services"); + +const PATH = "browser/devtools/server/tests/browser/"; +const MAIN_DOMAIN = "http://test1.example.org/" + PATH; +const ALT_DOMAIN = "http://sectest1.example.org/" + PATH; +const ALT_DOMAIN_SECURED = "https://sectest1.example.org:443/" + PATH; + +// All tests are asynchronous. +waitForExplicitFinish(); + +/** + * Add a new test tab in the browser and load the given url. + * @param {String} url The url to be loaded in the new tab + * @return a promise that resolves to the new browser that the document + * is loaded in. Note that we cannot return the document + * directly, since this would be a CPOW in the e10s case, + * and Promises cannot be resolved with CPOWs (see bug 1233497). + */ +var addTab = Task.async(function* (url) { + info(`Adding a new tab with URL: ${url}`); + let tab = gBrowser.selectedTab = gBrowser.addTab(url); + yield BrowserTestUtils.browserLoaded(tab.linkedBrowser); + + info(`Tab added and URL ${url} loaded`); + + return tab.linkedBrowser; +}); + +function* initAnimationsFrontForUrl(url) { + const {AnimationsFront} = require("devtools/shared/fronts/animation"); + const {InspectorFront} = require("devtools/shared/fronts/inspector"); + + yield addTab(url); + + initDebuggerServer(); + let client = new DebuggerClient(DebuggerServer.connectPipe()); + let form = yield connectDebuggerClient(client); + let inspector = InspectorFront(client, form); + let walker = yield inspector.getWalker(); + let animations = AnimationsFront(client, form); + + return {inspector, walker, animations, client}; +} + +function initDebuggerServer() { + try { + // Sometimes debugger server does not get destroyed correctly by previous + // tests. + DebuggerServer.destroy(); + } catch (e) { + info(`DebuggerServer destroy error: ${e}\n${e.stack}`); + } + DebuggerServer.init(); + DebuggerServer.addBrowserActors(); +} + +/** + * Connect a debugger client. + * @param {DebuggerClient} + * @return {Promise} Resolves to the selected tabActor form when the client is + * connected. + */ +function connectDebuggerClient(client) { + return client.connect() + .then(() => client.listTabs()) + .then(tabs => { + return tabs.tabs[tabs.selected]; + }); +} + +/** + * Wait for eventName on target. + * @param {Object} target An observable object that either supports on/off or + * addEventListener/removeEventListener + * @param {String} eventName + * @param {Boolean} useCapture Optional, for addEventListener/removeEventListener + * @return A promise that resolves when the event has been handled + */ +function once(target, eventName, useCapture = false) { + info("Waiting for event: '" + eventName + "' on " + target + "."); + + return new Promise(resolve => { + + for (let [add, remove] of [ + ["addEventListener", "removeEventListener"], + ["addListener", "removeListener"], + ["on", "off"] + ]) { + if ((add in target) && (remove in target)) { + target[add](eventName, function onEvent(...aArgs) { + info("Got event: '" + eventName + "' on " + target + "."); + target[remove](eventName, onEvent, useCapture); + resolve(...aArgs); + }, useCapture); + break; + } + } + }); +} + +/** + * Forces GC, CC and Shrinking GC to get rid of disconnected docshells and + * windows. + */ +function forceCollections() { + Cu.forceGC(); + Cu.forceCC(); + Cu.forceShrinkingGC(); +} + +/** + * Get a mock tabActor from a given window. + * This is sometimes useful to test actors or classes that use the tabActor in + * isolation. + * @param {DOMWindow} win + * @return {Object} + */ +function getMockTabActor(win) { + return { + window: win, + isRootActor: true + }; +} + +registerCleanupFunction(function tearDown() { + while (gBrowser.tabs.length > 1) { + gBrowser.removeCurrentTab(); + } +}); + +function idleWait(time) { + return DevToolsUtils.waitForTime(time); +} + +function busyWait(time) { + let start = Date.now(); + let stack; + while (Date.now() - start < time) { stack = Components.stack; } +} + +/** + * Waits until a predicate returns true. + * + * @param function predicate + * Invoked once in a while until it returns true. + * @param number interval [optional] + * How often the predicate is invoked, in milliseconds. + */ +function waitUntil(predicate, interval = 10) { + if (predicate()) { + return Promise.resolve(true); + } + return new Promise(resolve => { + setTimeout(function () { + waitUntil(predicate).then(() => resolve(true)); + }, interval); + }); +} + +function waitForMarkerType(front, types, predicate, + unpackFun = (name, data) => data.markers, + eventName = "timeline-data") +{ + types = [].concat(types); + predicate = predicate || function () { return true; }; + let filteredMarkers = []; + let { promise, resolve } = defer(); + + info("Waiting for markers of type: " + types); + + function handler(name, data) { + if (typeof name === "string" && name !== "markers") { + return; + } + + let markers = unpackFun(name, data); + info("Got markers: " + JSON.stringify(markers, null, 2)); + + filteredMarkers = filteredMarkers.concat(markers.filter(m => types.indexOf(m.name) !== -1)); + + if (types.every(t => filteredMarkers.some(m => m.name === t)) && predicate(filteredMarkers)) { + front.off(eventName, handler); + resolve(filteredMarkers); + } + } + front.on(eventName, handler); + + return promise; +} |