tor-browser

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

browser_inspector_breadcrumbs.js (9283B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 "use strict";
      4 
      5 // Test that the breadcrumbs widget content is correct.
      6 
      7 const TEST_URI = URL_ROOT + "doc_inspector_breadcrumbs.html";
      8 const NODES = [
      9  {
     10    selector: "#i1111",
     11    ids: "i1 i11 i111 i1111",
     12    nodeName: "div",
     13    title: "div#i1111",
     14  },
     15  { selector: "#i22", ids: "i2 i22", nodeName: "div", title: "div#i22" },
     16  {
     17    selector: "#i2111",
     18    ids: "i2 i21 i211 i2111",
     19    nodeName: "div",
     20    title: "div#i2111",
     21  },
     22  {
     23    selector: "#i21",
     24    ids: "i2 i21 i211 i2111",
     25    nodeName: "div",
     26    title: "div#i21",
     27  },
     28  {
     29    selector: "#i22211",
     30    ids: "i2 i22 i222 i2221 i22211",
     31    nodeName: "div",
     32    title: "div#i22211",
     33  },
     34  {
     35    selector: "#i22",
     36    ids: "i2 i22 i222 i2221 i22211",
     37    nodeName: "div",
     38    title: "div#i22",
     39  },
     40  { selector: "#i3", ids: "i3", nodeName: "article", title: "article#i3" },
     41  {
     42    selector: "clipPath",
     43    ids: "vector clip",
     44    nodeName: "clipPath",
     45    title: "clipPath#clip",
     46  },
     47 ];
     48 
     49 add_task(async function () {
     50  const { inspector } = await openInspectorForURL(TEST_URI);
     51  const breadcrumbs = inspector.panelDoc.getElementById(
     52    "inspector-breadcrumbs"
     53  );
     54  const container = breadcrumbs.querySelector(".html-arrowscrollbox-inner");
     55 
     56  for (const node of NODES) {
     57    info("Testing node " + node.selector);
     58 
     59    info("Selecting node and waiting for breadcrumbs to update");
     60    const breadcrumbsUpdated = inspector.once("breadcrumbs-updated");
     61    await selectNode(node.selector, inspector);
     62    await breadcrumbsUpdated;
     63 
     64    info("Performing checks for node " + node.selector);
     65    const buttonsLabelIds = node.ids.split(" ");
     66 
     67    // html > body > …
     68    is(
     69      container.childNodes.length,
     70      buttonsLabelIds.length + 2,
     71      "Node " + node.selector + ": Items count"
     72    );
     73 
     74    for (let i = 2; i < container.childNodes.length; i++) {
     75      const expectedId = "#" + buttonsLabelIds[i - 2];
     76      const button = container.childNodes[i];
     77      const labelId = button.querySelector(".breadcrumbs-widget-item-id");
     78      is(
     79        labelId.textContent,
     80        expectedId,
     81        "Node " + node.selector + ": button " + i + " matches"
     82      );
     83    }
     84 
     85    const pressedButton = container.querySelector(
     86      `button[aria-pressed="true"]`
     87    );
     88    const labelId = pressedButton.querySelector(".breadcrumbs-widget-item-id");
     89    const id = inspector.selection.nodeFront.id;
     90    is(
     91      labelId.textContent,
     92      "#" + id,
     93      "Node " + node.selector + ": selection matches"
     94    );
     95 
     96    const labelTag = pressedButton.querySelector(
     97      ".breadcrumbs-widget-item-tag"
     98    );
     99    is(
    100      labelTag.textContent,
    101      node.nodeName,
    102      "Node " + node.selector + " has the expected tag name"
    103    );
    104 
    105    is(
    106      pressedButton.getAttribute("title"),
    107      node.title,
    108      "Node " + node.selector + " has the expected tooltip"
    109    );
    110  }
    111 
    112  await testPseudoElements(inspector, container);
    113  await testComments(inspector, container);
    114 });
    115 
    116 async function testPseudoElements(inspector, container) {
    117  info("Checking for pseudo elements");
    118 
    119  const checkBreadcrumbContent = async (nodeFront, expected, desc) => {
    120    const onBreadcrumbsUpdated = inspector.once("breadcrumbs-updated");
    121    await selectNode(nodeFront, inspector);
    122    await onBreadcrumbsUpdated;
    123    Assert.deepEqual(
    124      [...container.childNodes].map(el => el.textContent),
    125      expected,
    126      desc
    127    );
    128  };
    129 
    130  const pseudoParent = await getNodeFront("#pseudo-container", inspector);
    131  const children = await inspector.walker.children(pseudoParent);
    132  is(children.nodes.length, 2, "Pseudo children returned from walker");
    133 
    134  const beforeElement = children.nodes[0];
    135  await checkBreadcrumbContent(
    136    beforeElement,
    137    ["html", "body", "div#pseudo-container", "::before"],
    138    "::before shows up in breadcrumb"
    139  );
    140 
    141  const afterElement = children.nodes[1];
    142  await checkBreadcrumbContent(
    143    afterElement,
    144    ["html", "body", "div#pseudo-container", "::after"],
    145    "::after shows up in breadcrumb"
    146  );
    147 
    148  const dialogNodeFront = await getNodeFront("dialog", inspector);
    149  const dialogChildren = await inspector.walker.children(dialogNodeFront);
    150  is(
    151    dialogChildren.nodes.length,
    152    2,
    153    "Expected number of children for the dialog element"
    154  );
    155  const backdropElement = dialogChildren.nodes[0];
    156  await checkBreadcrumbContent(
    157    backdropElement,
    158    ["html", "body", "dialog", "::backdrop"],
    159    ":backdrop shows up in breadcrumb"
    160  );
    161 
    162  info("Check rules on ::view-transition");
    163  const htmlNodeFront = await getNodeFront("html", inspector);
    164  const onMarkupMutation = inspector.once("markupmutation");
    165  await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async () => {
    166    const document = content.document;
    167    content.testTransition = document.startViewTransition();
    168    await content.testTransition;
    169  });
    170  await onMarkupMutation;
    171 
    172  const htmlChildren = await inspector.markup.walker.children(htmlNodeFront);
    173  const viewTransitionNodeFront = htmlChildren.nodes[2];
    174 
    175  is(
    176    viewTransitionNodeFront.getAttribute("type"),
    177    ":view-transition",
    178    "Got expected ::view-transition node front"
    179  );
    180 
    181  await checkBreadcrumbContent(
    182    viewTransitionNodeFront,
    183    ["html", "::view-transition"],
    184    "::view-transition shows up in breadcrumb"
    185  );
    186 
    187  const viewTransitionChildren = await inspector.markup.walker.children(
    188    viewTransitionNodeFront
    189  );
    190  const viewTransitionGroupNodeFront = viewTransitionChildren.nodes[0];
    191  is(
    192    viewTransitionGroupNodeFront.getAttribute("type"),
    193    ":view-transition-group",
    194    "Got expected ::view-transition-group node front"
    195  );
    196 
    197  await checkBreadcrumbContent(
    198    viewTransitionGroupNodeFront,
    199    ["html", "::view-transition", "::view-transition-group(root)"],
    200    "::view-transition-group(root) shows up in breadcrumb"
    201  );
    202 
    203  const viewTransitionGroupChildren = await inspector.markup.walker.children(
    204    viewTransitionGroupNodeFront
    205  );
    206  const viewTransitionImagePairNodeFront = viewTransitionGroupChildren.nodes[0];
    207  is(
    208    viewTransitionImagePairNodeFront.getAttribute("type"),
    209    ":view-transition-image-pair",
    210    "Got expected ::view-transition-image-pair node front"
    211  );
    212 
    213  await checkBreadcrumbContent(
    214    viewTransitionImagePairNodeFront,
    215    [
    216      "html",
    217      "::view-transition",
    218      "::view-transition-group(root)",
    219      "::view-transition-image-pair(root)",
    220    ],
    221    "::view-transition-image-pair(root) shows up in breadcrumb"
    222  );
    223 
    224  const viewTransitionImagePairChildren =
    225    await inspector.markup.walker.children(viewTransitionImagePairNodeFront);
    226  const [viewTransitionOldNodeFront, viewTransitionNewNodeFront] =
    227    viewTransitionImagePairChildren.nodes;
    228  is(
    229    viewTransitionOldNodeFront.getAttribute("type"),
    230    ":view-transition-old",
    231    "Got expected ::view-transition-old node front"
    232  );
    233  is(
    234    viewTransitionNewNodeFront.getAttribute("type"),
    235    ":view-transition-new",
    236    "Got expected ::view-transition-new node front"
    237  );
    238 
    239  await checkBreadcrumbContent(
    240    viewTransitionOldNodeFront,
    241    [
    242      "html",
    243      "::view-transition",
    244      "::view-transition-group(root)",
    245      "::view-transition-image-pair(root)",
    246      "::view-transition-old(root)",
    247    ],
    248    "::view-transition-old(root) shows up in breadcrumb"
    249  );
    250 
    251  await checkBreadcrumbContent(
    252    viewTransitionNewNodeFront,
    253    [
    254      "html",
    255      "::view-transition",
    256      "::view-transition-group(root)",
    257      "::view-transition-image-pair(root)",
    258      "::view-transition-new(root)",
    259    ],
    260    "::view-transition-new(root) shows up in breadcrumb"
    261  );
    262 
    263  // Cancel transition
    264  await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async () => {
    265    content.testTransition.skipTransition();
    266    delete content.testTransition;
    267  });
    268 }
    269 
    270 async function testComments(inspector, container) {
    271  info("Checking for comment elements");
    272 
    273  const breadcrumbs = inspector.breadcrumbs;
    274  const pressedButtonIndex = 2;
    275  const button = container.childNodes[pressedButtonIndex];
    276 
    277  let onBreadcrumbsUpdated = inspector.once("breadcrumbs-updated");
    278  button.click();
    279  await onBreadcrumbsUpdated;
    280 
    281  is(breadcrumbs.currentIndex, pressedButtonIndex, "New button is selected");
    282  ok(
    283    breadcrumbs.outer.hasAttribute("aria-activedescendant"),
    284    "Active descendant must be set"
    285  );
    286 
    287  const comment = [...inspector.markup._containers].find(
    288    ([node]) => node.nodeType === Node.COMMENT_NODE
    289  )[0];
    290 
    291  let onInspectorUpdated = inspector.once("inspector-updated");
    292  inspector.selection.setNodeFront(comment);
    293  await onInspectorUpdated;
    294 
    295  is(
    296    breadcrumbs.currentIndex,
    297    -1,
    298    "When comment is selected no breadcrumb should be pressed"
    299  );
    300  ok(
    301    !breadcrumbs.outer.hasAttribute("aria-activedescendant"),
    302    "Active descendant must not be set"
    303  );
    304 
    305  onInspectorUpdated = inspector.once("inspector-updated");
    306  onBreadcrumbsUpdated = inspector.once("breadcrumbs-updated");
    307  button.click();
    308  await Promise.all([onInspectorUpdated, onBreadcrumbsUpdated]);
    309 
    310  is(
    311    breadcrumbs.currentIndex,
    312    pressedButtonIndex,
    313    "Same button is selected again"
    314  );
    315  ok(
    316    breadcrumbs.outer.hasAttribute("aria-activedescendant"),
    317    "Active descendant must be set again"
    318  );
    319 }