Source code

Revision control

Copy as Markdown

Other Tools

/* 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(
this
);
const { DOMHelpers } = require("resource://devtools/shared/dom-helpers.js");
const {
Hosts,
const TEST_URI_ROOT_SSL =
const EXAMPLE_URL =
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;
};