tor-browser

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

browser_rules_selector_warnings.js (4713B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 // Test that selector warnings are displayed in the rule-view.
      7 const TEST_URI = `
      8  <!DOCTYPE html>
      9  <style>
     10    main, :scope ~ * {
     11      outline-color: tomato;
     12    }
     13 
     14    main, :has(form) {
     15      /* /!\ space between & and : is important */
     16      & :has(input),
     17      & :has(select),
     18      &:has(button) {
     19        background: gold;
     20      }
     21    }
     22  </style>
     23  <body>
     24    <main>
     25      <form>
     26        <input>
     27      </form>
     28    </main>
     29  </body>`;
     30 
     31 const UNCONSTRAINED_HAS_WARNING_MESSAGE =
     32  "This selector uses unconstrained :has(), which can be slow";
     33 const SIBLING_COMTINATOR_AFTER_SCOPE_WARNING_MESSAGE =
     34  "Sibling selectors after :scope will never match anything";
     35 
     36 add_task(async function () {
     37  await addTab(
     38    "https://example.com/document-builder.sjs?html=" +
     39      encodeURIComponent(TEST_URI)
     40  );
     41  const { inspector, view } = await openRuleView();
     42 
     43  await selectNode("main", inspector);
     44  const { ancestorDataEl, selectorText } = getRuleViewRuleEditor(view, 1);
     45 
     46  info(
     47    "Check that unconstrained :has() warnings are displayed for the rules selectors"
     48  );
     49  let ruleSelectors = Array.from(
     50    selectorText.querySelectorAll(".ruleview-selector")
     51  );
     52 
     53  await assertSelectorWarnings({
     54    view,
     55    selectorEl: ruleSelectors[0],
     56    selectorText: "& :has(input)",
     57    expectedWarnings: [UNCONSTRAINED_HAS_WARNING_MESSAGE],
     58  });
     59  await assertSelectorWarnings({
     60    view,
     61    selectorEl: ruleSelectors[1],
     62    selectorText: "& :has(select)",
     63    expectedWarnings: [UNCONSTRAINED_HAS_WARNING_MESSAGE],
     64  });
     65  // Warning is not displayed when the selector does not have warnings
     66  await assertSelectorWarnings({
     67    view,
     68    selectorEl: ruleSelectors[2],
     69    selectorText: "&:has(button)",
     70    expectedWarnings: [],
     71  });
     72 
     73  info(
     74    "Check that unconstrained :has() warnings are displayed for the parent rules selectors"
     75  );
     76  const parentRuleSelectors = Array.from(
     77    ancestorDataEl.querySelectorAll(".ruleview-selector")
     78  );
     79  await assertSelectorWarnings({
     80    view,
     81    selectorEl: parentRuleSelectors[0],
     82    selectorText: "main",
     83    expectedWarnings: [],
     84  });
     85  await assertSelectorWarnings({
     86    view,
     87    selectorEl: parentRuleSelectors[1],
     88    selectorText: ":has(form)",
     89    expectedWarnings: [UNCONSTRAINED_HAS_WARNING_MESSAGE],
     90  });
     91 
     92  const scopeSiblingRuleEditor = getRuleViewRuleEditor(view, 3);
     93  ruleSelectors = Array.from(
     94    scopeSiblingRuleEditor.selectorText.querySelectorAll(".ruleview-selector")
     95  );
     96  // Warning is not displayed when the selector does not have warnings
     97  await assertSelectorWarnings({
     98    view,
     99    selectorEl: ruleSelectors[0],
    100    selectorText: "main",
    101    expectedWarnings: [],
    102  });
    103  await assertSelectorWarnings({
    104    view,
    105    selectorEl: ruleSelectors[1],
    106    selectorText: ":scope ~ *",
    107    expectedWarnings: [SIBLING_COMTINATOR_AFTER_SCOPE_WARNING_MESSAGE],
    108  });
    109 });
    110 
    111 async function assertSelectorWarnings({
    112  view,
    113  selectorEl,
    114  selectorText,
    115  expectedWarnings,
    116 }) {
    117  is(
    118    selectorEl.textContent,
    119    selectorText,
    120    "Passed selector element is the expected one"
    121  );
    122 
    123  const selectorWarningsContainerEl = selectorEl.querySelector(
    124    ".ruleview-selector-warnings"
    125  );
    126 
    127  if (expectedWarnings.length === 0) {
    128    Assert.strictEqual(
    129      selectorWarningsContainerEl,
    130      null,
    131      `"${selectorText}" does not have warnings`
    132    );
    133    return;
    134  }
    135 
    136  Assert.notStrictEqual(
    137    selectorWarningsContainerEl,
    138    null,
    139    `"${selectorText}" does have warnings`
    140  );
    141 
    142  is(
    143    selectorWarningsContainerEl
    144      .getAttribute("data-selector-warning-kind")
    145      ?.split(",")?.length || 0,
    146    expectedWarnings.length,
    147    `"${selectorText}" has expected number of warnings`
    148  );
    149 
    150  // Ensure that the element can be targetted from EventUtils.
    151  selectorWarningsContainerEl.scrollIntoView();
    152 
    153  const tooltip = view.tooltips.getTooltip("interactiveTooltip");
    154  const onTooltipReady = tooltip.once("shown");
    155  EventUtils.synthesizeMouseAtCenter(
    156    selectorWarningsContainerEl,
    157    { type: "mousemove" },
    158    selectorWarningsContainerEl.ownerDocument.defaultView
    159  );
    160  await onTooltipReady;
    161 
    162  const lis = Array.from(tooltip.panel.querySelectorAll("li")).map(
    163    li => li.textContent
    164  );
    165  Assert.deepEqual(lis, expectedWarnings, "Tooltip has expected items");
    166 
    167  info("Hide the tooltip");
    168  const onHidden = tooltip.once("hidden");
    169  // Move the mouse elsewhere to hide the tooltip
    170  EventUtils.synthesizeMouse(
    171    selectorWarningsContainerEl.ownerDocument.body,
    172    1,
    173    1,
    174    { type: "mousemove" },
    175    selectorWarningsContainerEl.ownerDocument.defaultView
    176  );
    177  await onHidden;
    178 }