head.js (7623B)
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"}] */ 5 6 "use strict"; 7 8 // Import the inspector's head.js first (which itself imports shared-head.js). 9 Services.scriptloader.loadSubScript( 10 "chrome://mochitests/content/browser/devtools/client/inspector/test/head.js", 11 this 12 ); 13 14 var nodeConstants = require("resource://devtools/shared/dom-node-constants.js"); 15 16 /** 17 * The font-inspector doesn't participate in the inspector's update mechanism 18 * (i.e. it doesn't call inspector.updating() when updating), so simply calling 19 * the default selectNode isn't enough to guaranty that the panel has finished 20 * updating. We also need to wait for the fontinspector-updated event. 21 * 22 * @param {string | NodeFront} selector 23 * @param {InspectorPanel} inspector 24 * The instance of InspectorPanel currently loaded in the toolbox. 25 * @param {string} reason 26 * Defaults to "test" which instructs the inspector not to highlight the 27 * node upon selection. 28 */ 29 var _selectNode = selectNode; 30 selectNode = async function (node, inspector, reason) { 31 // Ensure node is a NodeFront and not a selector (which is also accepted as 32 // an argument to selectNode). 33 node = await getNodeFront(node, inspector); 34 35 // The FontInspector will fallback to the parent node when a text node is 36 // selected. 37 const isTextNode = node.nodeType == nodeConstants.TEXT_NODE; 38 const expectedNode = isTextNode ? node.parentNode() : node; 39 40 const onEditorUpdated = inspector.once("fonteditor-updated"); 41 const onFontInspectorUpdated = new Promise(resolve => { 42 inspector.on("fontinspector-updated", function onUpdated(eventNode) { 43 if (eventNode === expectedNode) { 44 inspector.off("fontinspector-updated", onUpdated); 45 resolve(); 46 } 47 }); 48 }); 49 await _selectNode(node, inspector, reason); 50 51 // Wait for both the font inspector and font editor before proceeding. 52 await Promise.all([onFontInspectorUpdated, onEditorUpdated]); 53 }; 54 55 /** 56 * Adds a new tab with the given URL, opens the inspector and selects the 57 * font-inspector tab. 58 * 59 * @return {Promise} resolves to a {tab, toolbox, inspector, view} object 60 */ 61 var openFontInspectorForURL = async function (url) { 62 const tab = await addTab(url); 63 const { toolbox, inspector } = await openInspector(); 64 65 // Call selectNode again here to force a fontinspector update since we don't 66 // know if the fontinspector-updated event has been sent while the inspector 67 // was being opened or not. 68 await selectNode("body", inspector); 69 70 return { 71 tab, 72 toolbox, 73 inspector, 74 view: inspector.getPanel("fontinspector"), 75 }; 76 }; 77 78 /** 79 * Focus the preview input, clear it, type new text into it and wait for the 80 * preview images to be updated. 81 * 82 * @param {FontInspector} view - The FontInspector instance. 83 * @param {string} text - The text to preview. 84 */ 85 async function updatePreviewText(view, text) { 86 info(`Changing the preview text to '${text}'`); 87 88 const doc = view.document; 89 const input = doc.querySelector("#font-preview-input-container input"); 90 input.focus(); 91 92 info("Blanking the input field."); 93 while (input.value.length) { 94 const update = view.inspector.once("fontinspector-updated"); 95 EventUtils.sendKey("BACK_SPACE", doc.defaultView); 96 await update; 97 } 98 99 if (text) { 100 info(`Typing "${text}" into the input field.`); 101 const update = view.inspector.once("fontinspector-updated"); 102 EventUtils.sendString(text, doc.defaultView); 103 await update; 104 } 105 106 is(input.value, text, `The input now contains "${text}".`); 107 } 108 109 /** 110 * Get all of the elements with names of fonts used on the currently selected element. 111 * 112 * @param {Document} viewDoc 113 * @return {NodeList} 114 */ 115 function getUsedFontsEls(viewDoc) { 116 return viewDoc.querySelectorAll( 117 "#font-editor .font-control-used-fonts .font-name" 118 ); 119 } 120 121 /** 122 * Get all of the elements with groups of fonts used on the currently selected element. 123 * 124 * @param {Document} viewDoc 125 * @return {NodeList} 126 */ 127 function getUsedFontGroupsEls(viewDoc) { 128 return viewDoc.querySelectorAll( 129 "#font-editor .font-control-used-fonts .font-group" 130 ); 131 } 132 133 /** 134 * Get the DOM element for the accordion widget that contains the fonts used elsewhere in 135 * the document. 136 * 137 * @param {Document} viewDoc 138 * @return {DOMNode} 139 */ 140 function getFontsAccordion(viewDoc) { 141 return viewDoc.querySelector("#font-container .accordion"); 142 } 143 144 /** 145 * Expand a given accordion widget. 146 * 147 * @param {DOMNode} accordion 148 */ 149 async function expandAccordion(accordion) { 150 const isExpanded = () => accordion.querySelector(".fonts-list"); 151 if (isExpanded()) { 152 return; 153 } 154 155 const onExpanded = BrowserTestUtils.waitForCondition( 156 isExpanded, 157 "Waiting for other fonts section" 158 ); 159 accordion.querySelector(".theme-twisty").click(); 160 await onExpanded; 161 } 162 163 /** 164 * Expand the fonts accordion. 165 * 166 * @param {Document} viewDoc 167 */ 168 async function expandFontsAccordion(viewDoc) { 169 info("Expanding the other fonts section"); 170 await expandAccordion(getFontsAccordion(viewDoc)); 171 } 172 173 /** 174 * Get all of the <li> elements for the fonts used elsewhere in the document. 175 * 176 * @param {Document} viewDoc 177 * @return {NodeList} 178 */ 179 function getAllFontsEls(viewDoc) { 180 return getFontsAccordion(viewDoc).querySelectorAll(".fonts-list > li"); 181 } 182 183 /** 184 * Given a font element, return its name. 185 * 186 * @param {DOMNode} fontEl 187 * The font element. 188 * @return {string} 189 * The name of the font as shown in the UI. 190 */ 191 function getName(fontEl) { 192 return fontEl.querySelector(".font-name").textContent; 193 } 194 195 /** 196 * Given a font element, return the font's URL. 197 * 198 * @param {DOMNode} fontEl 199 * The font element. 200 * @return {string} 201 * The URL where the font was loaded from as shown in the UI. 202 */ 203 function getURL(fontEl) { 204 return fontEl.querySelector(".font-origin").textContent; 205 } 206 207 /** 208 * Given a font element, return its family name. 209 * 210 * @param {DOMNode} fontEl 211 * The font element. 212 * @return {string} 213 * The name of the font family as shown in the UI. 214 */ 215 function getFamilyName(fontEl) { 216 return fontEl.querySelector(".font-family-name").textContent; 217 } 218 219 /** 220 * Get the value and unit of a CSS font property or font axis from the font editor. 221 * 222 * @param {Document} viewDoc 223 * Host document of the font inspector panel. 224 * @param {string} name 225 * Font property name or axis tag 226 * @return {object} 227 * Object with the value and unit of the given font property or axis tag 228 * from the corresponding input fron the font editor. 229 * @example 230 * { 231 * value: {String|null} 232 * unit: {String|null} 233 * } 234 */ 235 function getPropertyValue(viewDoc, name) { 236 const selector = `#font-editor .font-value-input[name=${name}]`; 237 return { 238 // Ensure value input exists before querying its value 239 value: 240 viewDoc.querySelector(selector) && 241 parseFloat(viewDoc.querySelector(selector).value), 242 // Ensure unit dropdown exists before querying its value 243 unit: 244 viewDoc.querySelector(selector + ` ~ .font-value-select`) && 245 viewDoc.querySelector(selector + ` ~ .font-value-select`).value, 246 }; 247 } 248 249 /** 250 * Given a font element, check whether its font source is remote. 251 * 252 * @param {DOMNode} fontEl 253 * The font element. 254 * @return {boolean} 255 */ 256 function isRemote(fontEl) { 257 return fontEl.querySelector(".font-origin").classList.contains("remote"); 258 }