head.js (6135B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 /* All top-level definitions here are exports. */ 5 /* eslint no-unused-vars: [2, {"vars": "local"}] */ 6 7 "use strict"; 8 9 Services.scriptloader.loadSubScript( 10 "chrome://mochitests/content/browser/devtools/client/inspector/shared/test/head.js", 11 this 12 ); 13 14 const TEST_BASE = 15 "chrome://mochitests/content/browser/devtools/client/styleeditor/test/"; 16 const TEST_BASE_HTTP = 17 "http://example.com/browser/devtools/client/styleeditor/test/"; 18 const TEST_BASE_HTTPS = 19 "https://example.com/browser/devtools/client/styleeditor/test/"; 20 const TEST_HOST = "mochi.test:8888"; 21 22 /** 23 * Add a new test tab in the browser and load the given url. 24 * 25 * @param {string} url The url to be loaded in the new tab 26 * @param {Window} win The window to add the tab to (default: current window). 27 * @return a promise that resolves to the tab object when the url is loaded 28 */ 29 var addTab = function (url, win) { 30 info("Adding a new tab with URL: '" + url + "'"); 31 32 return new Promise(resolve => { 33 const targetWindow = win || window; 34 const targetBrowser = targetWindow.gBrowser; 35 36 const tab = (targetBrowser.selectedTab = BrowserTestUtils.addTab( 37 targetBrowser, 38 url 39 )); 40 BrowserTestUtils.browserLoaded(targetBrowser.selectedBrowser).then( 41 function () { 42 info("URL '" + url + "' loading complete"); 43 resolve(tab); 44 } 45 ); 46 }); 47 }; 48 49 var navigateToAndWaitForStyleSheets = async function (url, ui, editorCount) { 50 const onClear = ui.once("stylesheets-clear"); 51 await navigateTo(url); 52 await onClear; 53 await waitUntil(() => ui.editors.length === editorCount); 54 }; 55 56 var reloadPageAndWaitForStyleSheets = async function (ui, editorCount) { 57 info("Reloading the page."); 58 59 const onClear = ui.once("stylesheets-clear"); 60 let count = 0; 61 const onAllEditorAdded = new Promise(res => { 62 const off = ui.on("editor-added", editor => { 63 count++; 64 info(`Received ${editor.friendlyName} (${count}/${editorCount})`); 65 if (count == editorCount) { 66 res(); 67 off(); 68 } 69 }); 70 }); 71 72 await reloadBrowser(); 73 await onClear; 74 75 await onAllEditorAdded; 76 info("All expected editors added"); 77 }; 78 79 /** 80 * Open the style editor for the current tab. 81 */ 82 var openStyleEditor = async function (tab) { 83 if (!tab) { 84 tab = gBrowser.selectedTab; 85 } 86 const toolbox = await gDevTools.showToolboxForTab(tab, { 87 toolId: "styleeditor", 88 }); 89 const panel = toolbox.getPanel("styleeditor"); 90 const ui = panel.UI; 91 92 return { toolbox, panel, ui }; 93 }; 94 95 /** 96 * Creates a new tab in specified window navigates it to the given URL and 97 * opens style editor in it. 98 */ 99 var openStyleEditorForURL = async function (url, win) { 100 const tab = await addTab(url, win); 101 const result = await openStyleEditor(tab); 102 result.tab = tab; 103 return result; 104 }; 105 106 /** 107 * Send an async message to the frame script and get back the requested 108 * computed style property. 109 * 110 * @param {string} selector 111 * The selector used to obtain the element. 112 * @param {string} pseudo 113 * pseudo id to query, or null. 114 * @param {string} name 115 * name of the property. 116 */ 117 var getComputedStyleProperty = async function (args) { 118 return SpecialPowers.spawn( 119 gBrowser.selectedBrowser, 120 [args], 121 function ({ selector, pseudo, name }) { 122 const element = content.document.querySelector(selector); 123 const style = content.getComputedStyle(element, pseudo); 124 return style.getPropertyValue(name); 125 } 126 ); 127 }; 128 129 /** 130 * Wait for "at-rules-list-changed" events to settle on StyleEditorUI. 131 * Returns a promise that resolves the number of events caught while waiting. 132 * 133 * @param {StyleEditorUI} ui 134 * Current StyleEditorUI on which at-rules-list-changed events should be fired. 135 * @param {number} delay 136 */ 137 function waitForManyEvents(ui, delay) { 138 return new Promise(resolve => { 139 let timer; 140 let count = 0; 141 const onEvent = () => { 142 count++; 143 clearTimeout(timer); 144 145 // Wait for some time to catch subsequent events. 146 timer = setTimeout(() => { 147 // Remove the listener and resolve. 148 ui.off("at-rules-list-changed", onEvent); 149 resolve(count); 150 }, delay); 151 }; 152 ui.on("at-rules-list-changed", onEvent); 153 }); 154 } 155 156 /** 157 * Creates a new style sheet in the Style Editor 158 159 * @param {StyleEditorUI} ui 160 * Current StyleEditorUI on which to simulate pressing the + button. 161 * @param {Window} panelWindow 162 * The panelWindow property of the current Style Editor panel. 163 */ 164 function createNewStyleSheet(ui, panelWindow) { 165 info("Creating a new stylesheet now"); 166 167 return new Promise(resolve => { 168 ui.once("editor-added", editor => { 169 editor.getSourceEditor().then(resolve); 170 }); 171 172 waitForFocus(function () { 173 // create a new style sheet 174 const newButton = panelWindow.document.querySelector( 175 ".style-editor-newButton" 176 ); 177 ok(newButton, "'new' button exists"); 178 179 EventUtils.synthesizeMouseAtCenter(newButton, {}, panelWindow); 180 }, panelWindow); 181 }); 182 } 183 184 /** 185 * Returns the panel root element (StyleEditorUI._root) 186 * 187 * @param {StyleEditorPanel} panel 188 * @returns {Element} 189 */ 190 function getRootElement(panel) { 191 return panel.panelWindow.document.getElementById("style-editor-chrome"); 192 } 193 194 /** 195 * Returns the panel context menu element 196 * 197 * @param {StyleEditorPanel} panel 198 * @returns {Element} 199 */ 200 function getContextMenuElement(panel) { 201 return panel.panelWindow.document.getElementById("sidebar-context"); 202 } 203 204 /** 205 * Assert the number of rules displayed in UI 206 * 207 * @param {StyleSheetEditor} editor 208 * @param {number} expected 209 */ 210 async function assertRuleCount(editor, expected) { 211 // The rule count is displayed via l10n.setArgs which only applies the value 212 // asynchronously, so wait for it to be applied. 213 const element = editor.summary.querySelector(".stylesheet-rule-count"); 214 await waitFor(() => { 215 return parseInt(element.textContent, 10) === expected; 216 }); 217 is(parseInt(element.textContent, 10), expected, "the rule count is correct"); 218 }