head.js (5892B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 /* eslint no-unused-vars: [2, {"vars": "local", "args": "none"}] */ 5 6 "use strict"; 7 8 // shared-head.js handles imports, constants, and utility functions 9 Services.scriptloader.loadSubScript( 10 "chrome://mochitests/content/browser/devtools/client/shared/test/shared-head.js", 11 this 12 ); 13 14 const { DOMHelpers } = require("resource://devtools/shared/dom-helpers.js"); 15 const { 16 Hosts, 17 } = require("resource://devtools/client/framework/toolbox-hosts.js"); 18 19 const TEST_URI_ROOT = "http://example.com/browser/devtools/client/shared/test/"; 20 const TEST_URI_ROOT_SSL = 21 "https://example.com/browser/devtools/client/shared/test/"; 22 23 const EXAMPLE_URL = 24 "chrome://mochitests/content/browser/devtools/client/shared/test/"; 25 26 function catchFail(func) { 27 return function () { 28 try { 29 return func.apply(null, arguments); 30 } catch (ex) { 31 ok(false, ex); 32 console.error(ex); 33 finish(); 34 throw ex; 35 } 36 }; 37 } 38 39 /** 40 * Polls a given function waiting for the given value. 41 * 42 * @param object options 43 * Options object with the following properties: 44 * - validator 45 * A validator function that should return the expected value. This is 46 * called every few milliseconds to check if the result is the expected 47 * one. When the returned result is the expected one, then the |success| 48 * function is called and polling stops. If |validator| never returns 49 * the expected value, then polling timeouts after several tries and 50 * a failure is recorded - the given |failure| function is invoked. 51 * - success 52 * A function called when the validator function returns the expected 53 * value. 54 * - failure 55 * A function called if the validator function timeouts - fails to return 56 * the expected value in the given time. 57 * - name 58 * Name of test. This is used to generate the success and failure 59 * messages. 60 * - timeout 61 * Timeout for validator function, in milliseconds. Default is 5000 ms. 62 * - value 63 * The expected value. If this option is omitted then the |validator| 64 * function must return a trueish value. 65 * Each of the provided callback functions will receive two arguments: 66 * the |options| object and the last value returned by |validator|. 67 */ 68 function waitForValue(options) { 69 const start = Date.now(); 70 const timeout = options.timeout || 5000; 71 let lastValue; 72 73 function wait(validatorFn, successFn, failureFn) { 74 if (Date.now() - start > timeout) { 75 // Log the failure. 76 ok(false, "Timed out while waiting for: " + options.name); 77 const expected = 78 "value" in options ? "'" + options.value + "'" : "a trueish value"; 79 info("timeout info :: got '" + lastValue + "', expected " + expected); 80 failureFn(options, lastValue); 81 return; 82 } 83 84 lastValue = validatorFn(options, lastValue); 85 const successful = 86 "value" in options ? lastValue == options.value : lastValue; 87 if (successful) { 88 ok(true, options.name); 89 successFn(options, lastValue); 90 } else { 91 setTimeout(() => { 92 wait(validatorFn, successFn, failureFn); 93 }, 100); 94 } 95 } 96 97 wait(options.validator, options.success, options.failure); 98 } 99 100 function oneTimeObserve(name, callback) { 101 return new Promise(resolve => { 102 const func = function () { 103 Services.obs.removeObserver(func, name); 104 if (callback) { 105 callback(); 106 } 107 resolve(); 108 }; 109 Services.obs.addObserver(func, name); 110 }); 111 } 112 113 const createHost = async function ( 114 type = "bottom", 115 src = CHROME_URL_ROOT + "dummy.html" 116 ) { 117 const host = new Hosts[type](gBrowser.selectedTab); 118 const iframe = await host.create(); 119 120 await new Promise(resolve => { 121 iframe.setAttribute("src", src); 122 DOMHelpers.onceDOMReady(iframe.contentWindow, resolve); 123 }); 124 125 // Popup tests fail very frequently on Linux + webrender because they run 126 // too early. 127 await waitForPresShell(iframe); 128 129 return { host, win: iframe.contentWindow, doc: iframe.contentDocument }; 130 }; 131 132 /** 133 * Open and close the toolbox in the current browser tab, several times, waiting 134 * some amount of time in between. 135 * 136 * @param {number} nbOfTimes 137 * @param {number} usageTime in milliseconds 138 * @param {string} toolId 139 */ 140 async function openAndCloseToolbox(nbOfTimes, usageTime, toolId) { 141 for (let i = 0; i < nbOfTimes; i++) { 142 info("Opening toolbox " + (i + 1)); 143 144 const tab = gBrowser.selectedTab; 145 const toolbox = await gDevTools.showToolboxForTab(tab, { toolId }); 146 147 // We use a timeout to check the toolbox's active time 148 await new Promise(resolve => setTimeout(resolve, usageTime)); 149 150 info("Closing toolbox " + (i + 1)); 151 await toolbox.destroy(); 152 } 153 } 154 155 /** 156 * Show the presets list sidebar in the cssfilter widget popup 157 * 158 * @param {CSSFilterWidget} widget 159 * @return {Promise} 160 */ 161 function showFilterPopupPresets(widget) { 162 const onRender = widget.once("render"); 163 widget._togglePresets(); 164 return onRender; 165 } 166 167 /** 168 * Show presets list and create a sample preset with the name and value provided 169 * 170 * @param {CSSFilterWidget} widget 171 * @param {string} name 172 * @param {string} value 173 * @return {Promise} 174 */ 175 const showFilterPopupPresetsAndCreatePreset = async function ( 176 widget, 177 name, 178 value 179 ) { 180 await showFilterPopupPresets(widget); 181 182 let onRender = widget.once("render"); 183 widget.setCssValue(value); 184 await onRender; 185 186 const footer = widget.el.querySelector(".presets-list .footer"); 187 footer.querySelector("input").value = name; 188 189 onRender = widget.once("render"); 190 widget._savePreset({ 191 preventDefault: () => {}, 192 }); 193 194 await onRender; 195 };