diff options
Diffstat (limited to 'devtools/client/shared/test/head.js')
-rw-r--r-- | devtools/client/shared/test/head.js | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/devtools/client/shared/test/head.js b/devtools/client/shared/test/head.js new file mode 100644 index 0000000000..47731bc74a --- /dev/null +++ b/devtools/client/shared/test/head.js @@ -0,0 +1,211 @@ +/* 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/. */ +/* eslint no-unused-vars: [2, {"vars": "local", "args": "none"}] */ + +"use strict"; + +// shared-head.js handles imports, constants, and utility functions +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/devtools/client/shared/test/shared-head.js", + this +); + +const { DOMHelpers } = require("resource://devtools/shared/dom-helpers.js"); +const { + Hosts, +} = require("resource://devtools/client/framework/toolbox-hosts.js"); + +const TEST_URI_ROOT = "http://example.com/browser/devtools/client/shared/test/"; +const TEST_URI_ROOT_SSL = + "https://example.com/browser/devtools/client/shared/test/"; + +const EXAMPLE_URL = + "chrome://mochitests/content/browser/devtools/client/shared/test/"; + +function catchFail(func) { + return function () { + try { + return func.apply(null, arguments); + } catch (ex) { + ok(false, ex); + console.error(ex); + finish(); + throw ex; + } + }; +} + +/** + * Polls a given function waiting for the given value. + * + * @param object options + * Options object with the following properties: + * - validator + * A validator function that should return the expected value. This is + * called every few milliseconds to check if the result is the expected + * one. When the returned result is the expected one, then the |success| + * function is called and polling stops. If |validator| never returns + * the expected value, then polling timeouts after several tries and + * a failure is recorded - the given |failure| function is invoked. + * - success + * A function called when the validator function returns the expected + * value. + * - failure + * A function called if the validator function timeouts - fails to return + * the expected value in the given time. + * - name + * Name of test. This is used to generate the success and failure + * messages. + * - timeout + * Timeout for validator function, in milliseconds. Default is 5000 ms. + * - value + * The expected value. If this option is omitted then the |validator| + * function must return a trueish value. + * Each of the provided callback functions will receive two arguments: + * the |options| object and the last value returned by |validator|. + */ +function waitForValue(options) { + const start = Date.now(); + const timeout = options.timeout || 5000; + let lastValue; + + function wait(validatorFn, successFn, failureFn) { + if (Date.now() - start > timeout) { + // Log the failure. + ok(false, "Timed out while waiting for: " + options.name); + const expected = + "value" in options ? "'" + options.value + "'" : "a trueish value"; + info("timeout info :: got '" + lastValue + "', expected " + expected); + failureFn(options, lastValue); + return; + } + + lastValue = validatorFn(options, lastValue); + const successful = + "value" in options ? lastValue == options.value : lastValue; + if (successful) { + ok(true, options.name); + successFn(options, lastValue); + } else { + setTimeout(() => { + wait(validatorFn, successFn, failureFn); + }, 100); + } + } + + wait(options.validator, options.success, options.failure); +} + +function oneTimeObserve(name, callback) { + return new Promise(resolve => { + const func = function () { + Services.obs.removeObserver(func, name); + if (callback) { + callback(); + } + resolve(); + }; + Services.obs.addObserver(func, name); + }); +} + +const createHost = async function ( + type = "bottom", + src = CHROME_URL_ROOT + "dummy.html" +) { + const host = new Hosts[type](gBrowser.selectedTab); + const iframe = await host.create(); + + await new Promise(resolve => { + iframe.setAttribute("src", src); + DOMHelpers.onceDOMReady(iframe.contentWindow, resolve); + }); + + // Popup tests fail very frequently on Linux + webrender because they run + // too early. + await waitForPresShell(iframe); + + return { host, win: iframe.contentWindow, doc: iframe.contentDocument }; +}; + +/** + * Open and close the toolbox in the current browser tab, several times, waiting + * some amount of time in between. + * @param {Number} nbOfTimes + * @param {Number} usageTime in milliseconds + * @param {String} toolId + */ +async function openAndCloseToolbox(nbOfTimes, usageTime, toolId) { + for (let i = 0; i < nbOfTimes; i++) { + info("Opening toolbox " + (i + 1)); + + const tab = gBrowser.selectedTab; + const toolbox = await gDevTools.showToolboxForTab(tab, { toolId }); + + // We use a timeout to check the toolbox's active time + await new Promise(resolve => setTimeout(resolve, usageTime)); + + info("Closing toolbox " + (i + 1)); + await toolbox.destroy(); + } +} + +/** + * 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); + }); +} + +/** + * Show the presets list sidebar in the cssfilter widget popup + * @param {CSSFilterWidget} widget + * @return {Promise} + */ +function showFilterPopupPresets(widget) { + const onRender = widget.once("render"); + widget._togglePresets(); + return onRender; +} + +/** + * Show presets list and create a sample preset with the name and value provided + * @param {CSSFilterWidget} widget + * @param {string} name + * @param {string} value + * @return {Promise} + */ +const showFilterPopupPresetsAndCreatePreset = async function ( + widget, + name, + value +) { + await showFilterPopupPresets(widget); + + let onRender = widget.once("render"); + widget.setCssValue(value); + await onRender; + + const footer = widget.el.querySelector(".presets-list .footer"); + footer.querySelector("input").value = name; + + onRender = widget.once("render"); + widget._savePreset({ + preventDefault: () => {}, + }); + + await onRender; +}; |