tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 });