browser_fontinspector_reveal-in-page.js (5825B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 "use strict"; 4 5 // Test that fonts usage can be revealed in the page using the FontsHighlighter. 6 7 const TEST_URI = URL_ROOT + "doc_browser_fontinspector.html"; 8 9 add_task(async function () { 10 // Make sure the toolbox is tall enough to accomodate all fonts, otherwise mouseover 11 // events simulation will fail. 12 await pushPref("devtools.toolbox.footer.height", 500); 13 14 const { inspector, view } = await openFontInspectorForURL(TEST_URI); 15 await testFontHighlighting(view, inspector); 16 17 info("Check that highlighting still works after reloading the page"); 18 await reloadBrowser(); 19 20 await testFontHighlighting(view, inspector); 21 22 info("Check that highlighting works for iframe nodes"); 23 await testFontHighlightingInIframe(view, inspector); 24 }); 25 26 async function testFontHighlighting(view, inspector) { 27 await selectNode("body", inspector); 28 // The number of window selection change events we expect to get as we hover over each 29 // font in the list. Waiting for those events is how we know that text-runs were 30 // highlighted in the page. 31 const expectedSelectionChangeEvents = [1, 1, 1, 1, 1]; 32 33 const viewDoc = view.document; 34 35 // Wait for the view to have all the expected used fonts. 36 const fontEls = ( 37 await waitFor(() => { 38 const els = getUsedFontsEls(viewDoc); 39 40 // TODO: We should expect an exact match, but after removing client side 41 // throttling there is sometimes a 6th font picked up on reload for this 42 // test page. 43 if (els.length < expectedSelectionChangeEvents.length) { 44 return false; 45 } 46 47 return [...els]; 48 }) 49 ).filter(el => { 50 // TODO: After removing client-side throttling, the test will request fonts 51 // too quickly on reload and will sometimes pickup an extra font such as 52 // "Helvetica" on macos. This font will not match any element on the page, 53 // ignore it for now. 54 const expectedFonts = ["ostrich", "arial", "liberation"]; 55 const font = el.textContent.toLowerCase(); 56 return expectedFonts.some(f => font.includes(f)); 57 }); 58 59 // See TODO above, we temporarily filter out unwanted fonts picked up on 60 // reload. 61 ok( 62 !!fontEls.length, 63 "After filtering out unwanted fonts, we still have fonts to test" 64 ); 65 66 info("Expand the details element so all fonts are visible"); 67 const showMoreEl = viewDoc.querySelector("summary:has(.label-open)"); 68 if (showMoreEl) { 69 EventUtils.synthesizeMouseAtCenter(showMoreEl, {}, viewDoc.defaultView); 70 } 71 72 for (let i = 0; i < fontEls.length; i++) { 73 info( 74 `Mousing over and out of font number ${i} ("${fontEls[i].textContent}") in the list` 75 ); 76 77 const expectedEvents = expectedSelectionChangeEvents[i]; 78 79 // Simulating a mouse over event on the font name and expecting a selectionchange. 80 const nameEl = fontEls[i]; 81 let onEvents = waitForNSelectionEvents( 82 gBrowser.selectedBrowser, 83 expectedEvents 84 ); 85 EventUtils.synthesizeMouse( 86 nameEl, 87 2, 88 2, 89 { type: "mouseover" }, 90 viewDoc.defaultView 91 ); 92 await onEvents; 93 94 ok(true, `${expectedEvents} selectionchange events detected on mouseover`); 95 96 // Simulating a mouse out event on the font name and expecting a selectionchange. 97 const otherEl = viewDoc.querySelector("body"); 98 onEvents = waitForNSelectionEvents(gBrowser.selectedBrowser, 1); 99 EventUtils.synthesizeMouse( 100 otherEl, 101 2, 102 2, 103 { type: "mouseover" }, 104 viewDoc.defaultView 105 ); 106 await onEvents; 107 108 ok(true, "1 selectionchange events detected on mouseout"); 109 } 110 } 111 112 async function testFontHighlightingInIframe(view, inspector) { 113 await selectNodeInFrames(["iframe", "div"], inspector); 114 115 const viewDoc = view.document; 116 117 // Wait for the view to have all the expected used fonts. 118 const fontEls = await waitFor(() => { 119 const els = getUsedFontsEls(viewDoc); 120 121 if (!els.length) { 122 return false; 123 } 124 125 return [...els]; 126 }); 127 128 is(fontEls.length, 1, "There's only one font used in the iframe document"); 129 ok( 130 // On Linux, Times New Roman does not exist. Liberation Serif is used instead. 131 ["Times New Roman", "Liberation Serif"].includes(fontEls[0].innerText), 132 "The expected font is displayed" 133 ); 134 135 const iframeBrowsingContext = await SpecialPowers.spawn( 136 gBrowser.selectedBrowser, 137 [], 138 () => content.document.querySelector("iframe").browsingContext 139 ); 140 141 info(`Mousing over and out of the font in the list`); 142 143 // Simulating a mouse over event on the font name and expecting a selectionchange. 144 const nameEl = fontEls[0]; 145 let onEvents = waitForNSelectionEvents(iframeBrowsingContext, 1); 146 EventUtils.synthesizeMouse( 147 nameEl, 148 2, 149 2, 150 { type: "mouseover" }, 151 viewDoc.defaultView 152 ); 153 await onEvents; 154 155 ok(true, `A selectionchange events detected on mouseover`); 156 157 // Simulating a mouse out event on the font name and expecting a selectionchange. 158 const otherEl = viewDoc.querySelector("body"); 159 onEvents = waitForNSelectionEvents(iframeBrowsingContext, 1); 160 EventUtils.synthesizeMouse( 161 otherEl, 162 2, 163 2, 164 { type: "mouseover" }, 165 viewDoc.defaultView 166 ); 167 await onEvents; 168 169 ok(true, "1 selectionchange events detected on mouseout"); 170 } 171 172 async function waitForNSelectionEvents(browser, numberOfTimes) { 173 await SpecialPowers.spawn(browser, [numberOfTimes], async function (n) { 174 const win = content.wrappedJSObject; 175 176 await new Promise(resolve => { 177 let received = 0; 178 win.document.addEventListener("selectionchange", function listen() { 179 received++; 180 181 if (received === n) { 182 win.document.removeEventListener("selectionchange", listen); 183 resolve(); 184 } 185 }); 186 }); 187 }); 188 }