browser_dbg-inspector-integration.js (8189B)
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 5 // Tests that clicking the DOM node button in any ObjectInspect 6 // opens the Inspector panel 7 8 "use strict"; 9 10 add_task(async function () { 11 // Ensures the end panel is wide enough to show the inspector icon 12 await pushPref("devtools.debugger.end-panel-size", 600); 13 // Disable 3-pane inspector as it might trigger unwanted server communication. 14 await pushPref("devtools.inspector.three-pane-enabled", false); 15 16 const dbg = await initDebugger("doc-script-switching.html"); 17 const { toolbox } = dbg; 18 const highlighterTestFront = await getHighlighterTestFront(toolbox); 19 const highlighter = toolbox.getHighlighter(); 20 21 // Bug 1562165: the WhyPaused element is displayed for a few hundred ms when adding an 22 // expression, which can break synthesizeMouseAtCenter. So here we wait for the 23 // whyPaused element to be displayed then hidden before testing the highlight feature. 24 const onWhyPausedDisplayed = waitUntil(() => 25 dbg.win.document.querySelector(".why-paused:not(.hidden)") 26 ); 27 await addExpression(dbg, "window.document.querySelector('button')"); 28 // TODO: Remove when Bug 1562165 lands. 29 await onWhyPausedDisplayed; 30 // TODO: Remove when Bug 1562165 lands. 31 await waitUntil(() => dbg.win.document.querySelector(".why-paused.hidden")); 32 33 info( 34 "Check that hovering over DOM element highlights the node in content panel" 35 ); 36 let onNodeHighlight = highlighter.waitForHighlighterShown(); 37 38 info("Mouseover the open in inspector button"); 39 const inspectorNode = await waitFor(() => findElement(dbg, "openInspector")); 40 const view = inspectorNode.ownerDocument.defaultView; 41 EventUtils.synthesizeMouseAtCenter( 42 inspectorNode, 43 { type: "mouseover" }, 44 view 45 ); 46 47 info("Wait for highligther to be shown"); 48 const { nodeFront } = await onNodeHighlight; 49 is(nodeFront.displayName, "button", "The correct node was highlighted"); 50 51 info("Check that moving the mouse away from the node hides the highlighter"); 52 let onNodeUnhighlight = highlighter.waitForHighlighterHidden(); 53 const nonHighlightEl = inspectorNode.closest(".object-node"); 54 EventUtils.synthesizeMouseAtCenter( 55 nonHighlightEl, 56 { type: "mouseover" }, 57 view 58 ); 59 60 await onNodeUnhighlight; 61 isVisible = await highlighterTestFront.isHighlighting(); 62 is(isVisible, false, "The highlighter is not displayed anymore"); 63 64 info("Check we don't have zombie highlighters when briefly hovering a node"); 65 onNodeHighlight = highlighter.waitForHighlighterShown(); 66 onNodeUnhighlight = highlighter.waitForHighlighterHidden(); 67 68 // Move hover the node and then, right after, move out. 69 EventUtils.synthesizeMouseAtCenter( 70 inspectorNode, 71 { type: "mousemove" }, 72 view 73 ); 74 EventUtils.synthesizeMouseAtCenter( 75 nonHighlightEl, 76 { type: "mousemove" }, 77 view 78 ); 79 80 await Promise.all([onNodeHighlight, onNodeUnhighlight]); 81 isVisible = await highlighterTestFront.isHighlighting(); 82 is(isVisible, false, "The highlighter is not displayed anymore - no zombie"); 83 84 info("Ensure panel changes when button is clicked"); 85 // Loading the inspector panel at first, to make it possible to listen for 86 // new node selections 87 const inspector = await toolbox.loadTool("inspector"); 88 const onInspectorSelected = toolbox.once("inspector-selected"); 89 const onInspectorUpdated = inspector.once("inspector-updated"); 90 const onNewNode = toolbox.selection.once("new-node-front"); 91 92 inspectorNode.click(); 93 94 await onInspectorSelected; 95 await onInspectorUpdated; 96 const inspectorNodeFront = await onNewNode; 97 98 ok(true, "Inspector selected and new node got selected"); 99 is( 100 inspectorNodeFront.displayName, 101 "button", 102 "The expected node was selected" 103 ); 104 }); 105 106 add_task(async function () { 107 // Disable 3-pane inspector as it might trigger unwanted server communication. 108 await pushPref("devtools.inspector.three-pane-enabled", false); 109 110 // It's important to pause in the iframe thread so we can assert the fix for Bug 1837480. 111 const iframeUrl = EXAMPLE_URL + "doc-event-handler.html"; 112 const dbg = await initDebuggerWithAbsoluteURL( 113 `https://example.org/document-builder.sjs?html=top<iframe src="${iframeUrl}"><iframe>` 114 ); 115 const { toolbox } = dbg; 116 117 // Pause in the iframe document (`synthesizeClick` has a debugger statement) 118 const iframeBc = await SpecialPowers.spawn( 119 gBrowser.selectedBrowser, 120 [], 121 () => content.document.querySelector("iframe").browsingContext 122 ); 123 SpecialPowers.spawn(iframeBc, [], () => 124 content.wrappedJSObject.synthesizeClick() 125 ); 126 127 await waitForPaused(dbg); 128 129 findElement(dbg, "frame", 2).focus(); 130 clickElement(dbg, "frame", 2); 131 await waitForPaused(dbg); 132 await waitForSelectedSource(dbg, "doc-event-handler.html"); 133 134 // Wait for all the updates to the document to complete to make all 135 // token elements have been rendered 136 await waitForDocumentLoadComplete(dbg); 137 138 // Wait for the iframe thread to be paused 139 const iframeThread = dbg.selectors 140 .getThreads() 141 .find(({ url }) => url === iframeUrl); 142 await waitForPausedThread(dbg, iframeThread.actor); 143 144 // Hover over the token to launch preview popup 145 await tryHovering(dbg, 5, 8, "popup"); 146 147 info("Wait for top level node to expand and child nodes to load"); 148 await waitUntil( 149 () => dbg.win.document.querySelectorAll(".preview-popup .node").length > 1 150 ); 151 152 info("Mouseover the open in inspector button"); 153 const openInspectorEl = await waitForElement(dbg, "openInspector"); 154 openInspectorEl.scrollIntoView(); 155 const view = openInspectorEl.ownerDocument.defaultView; 156 EventUtils.synthesizeMouseAtCenter( 157 openInspectorEl, 158 { type: "mouseover" }, 159 view 160 ); 161 162 info("Wait for highligther to be shown"); 163 // We don't want to involve directly the highlighters object as they trigger the inspector 164 // initialization and might interfere with what we're trying to assert here. 165 // So instead of event, we'll watch for the actual highlighter dom element to be 166 // visible on the page. 167 await SpecialPowers.spawn(iframeBc, [], () => { 168 const doc = content.document; 169 return ContentTaskUtils.waitForCondition(() => { 170 // Highlighters are rendered in the shadow DOM, let's get the shadow roots first 171 const roots = doc.getConnectedShadowRoots(); 172 const getBoxModelHighlighterInfoBarEl = root => 173 root.querySelector( 174 ".highlighter-container.box-model #box-model-infobar-container" 175 ); 176 const boxModelRoot = roots.find(root => 177 getBoxModelHighlighterInfoBarEl(root) 178 ); 179 if (!boxModelRoot) { 180 return false; 181 } 182 const boxModelInfoBarEl = getBoxModelHighlighterInfoBarEl(boxModelRoot); 183 return ( 184 // wait for the infobar to be displayed 185 !boxModelInfoBarEl.hasAttribute("hidden") && 186 // and make sure it's shown for the hovered element 187 boxModelInfoBarEl.querySelector(".box-model-infobar-id") 188 ?.textContent === "#clicky" 189 ); 190 }, "wait for hihglighter to be visible"); 191 }); 192 193 // Wait for a bit and check that the same thread is still selected 194 await wait(1000); 195 ok(dbg.selectors.getIsCurrentThreadPaused(), "current thread is paused"); 196 ok( 197 findElement(dbg, "threadsPaneItemPause", 2).classList.contains("selected"), 198 `iframe thread is still selected` 199 ); 200 201 // The highlighter should have loaded the inspector, we can directly use getPanel without 202 // calling loadTool first (and we shouldn't as the check on the highlighter covers 203 // a fix for Bug 1837480) 204 const inspector = await toolbox.getPanel("inspector"); 205 const onInspectorSelected = toolbox.once("inspector-selected"); 206 const onInspectorUpdated = inspector.once("inspector-updated"); 207 const onNewNode = toolbox.selection.once("new-node-front"); 208 209 // Click the first inspector button to view node in inspector 210 openInspectorEl.click(); 211 212 await onInspectorSelected; 213 await onInspectorUpdated; 214 await onNewNode; 215 216 ok(true, "Inspector selected and new node got selected"); 217 });