tor-browser

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

test_selectormatcheselement_host.html (5510B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4  <title>Test for CSSStyleRule::selectorMatchesElement on :host rules</title>
      5  <script src="/tests/SimpleTest/SimpleTest.js"></script>
      6  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
      7 </head>
      8 <body>
      9  <div id="host"></div>
     10  <script>
     11    /***** Add Shadow DOM *****/
     12    const topLevelHostEl = document.getElementById("host");
     13    const topShadow = topLevelHostEl.attachShadow({
     14      mode: "open"
     15    });
     16    const topLevelShadowSectionEl = document.createElement("section");
     17    topLevelShadowSectionEl.id = "top-level-shadow-section";
     18    const nestedHostEl = document.createElement("div");
     19    nestedHostEl.id = "nested-host";
     20 
     21    topLevelShadowSectionEl.append("top shadow dom section",)
     22    topShadow.append(topLevelShadowSectionEl, nestedHostEl);
     23 
     24    const sharedStyleSheet  = new CSSStyleSheet();
     25    sharedStyleSheet.replaceSync(`
     26      section, [test-rule-shared] {
     27        color: var(--a);
     28      }
     29      :host, [test-rule-shared] {
     30        --a: red;
     31      }`);
     32 
     33    const topLevelStyleSheet  = new CSSStyleSheet();
     34    topLevelStyleSheet.replaceSync(`
     35      :where(section), [test-rule] {
     36        background-color: var(--b);
     37      }
     38      :host, [test-rule] {
     39        --b: gold;
     40      }`);
     41 
     42    topShadow.adoptedStyleSheets = [sharedStyleSheet, topLevelStyleSheet];
     43 
     44 
     45    const nestedShadow = nestedHostEl.attachShadow({
     46      mode: "open"
     47    });
     48    const nestedShadowSectionEl = document.createElement("section");
     49    nestedShadowSectionEl.textContent = "nested shadow dom section";
     50    nestedShadowSectionEl.id = "nested-shadow-dom-section";
     51    nestedShadow.append(nestedShadowSectionEl);
     52 
     53    const nestedStyleSheet  = new CSSStyleSheet();
     54    nestedStyleSheet.replaceSync(`
     55      :is(section), [test-rule-nested] {
     56        border-color: var(--c);
     57      }
     58      :host, [test-rule-nested] {
     59        --c: lime;
     60      }`);
     61    nestedShadow.adoptedStyleSheets = [sharedStyleSheet, nestedStyleSheet];
     62 
     63    /***** Test *****/
     64    add_task(async () => {
     65      info("Checking rules on top level shadow section el");
     66      checkRulesAndSelectors(topLevelShadowSectionEl, [{
     67        selectorText: `:where(section), [test-rule]`,
     68        selectorMatches: [true, false]
     69      },{
     70        selectorText: `section, [test-rule-shared]`,
     71        selectorMatches: [true, false]
     72      }]);
     73 
     74      info("Checking rules on top level host");
     75      checkRulesAndSelectors(topLevelHostEl, [{
     76        selectorText: `:host, [test-rule-shared]`,
     77        selectorMatches: [true, false]
     78      },{
     79        selectorText: `:host, [test-rule]`,
     80        selectorMatches: [true, false]
     81      }]);
     82 
     83      info("Checking rules on nested shadow section el");
     84      checkRulesAndSelectors(nestedShadowSectionEl, [{
     85        selectorText: `section, [test-rule-shared]`,
     86        selectorMatches: [true, false]
     87      },{
     88        selectorText: `:is(section), [test-rule-nested]`,
     89        selectorMatches: [true, false]
     90      }]);
     91 
     92      info("Checking rules on nested host");
     93      checkRulesAndSelectors(nestedHostEl, [{
     94        selectorText: `:host, [test-rule-shared]`,
     95        selectorMatches: [true, false]
     96      },{
     97        selectorText: `:host, [test-rule-nested]`,
     98        selectorMatches: [true, false]
     99      }]);
    100 
    101      info("Check that non-shared rule selectors don't match for non-matching elements");
    102      const nonSharedTopLevelHostRules = getNonUAMatchingRules(topLevelHostEl)
    103        .filter(rule => rule.parentStyleSheet !== sharedStyleSheet);
    104      is(nonSharedTopLevelHostRules.length, 1, "top level host only has 1 non shared rule");
    105      is(
    106        nonSharedTopLevelHostRules[0].selectorMatchesElement(0, nestedHostEl),
    107        false,
    108        "non-shared top level host rule does not match nested host"
    109      );
    110 
    111      const nonSharedNestedHostRules = getNonUAMatchingRules(nestedHostEl)
    112        .filter(rule => rule.parentStyleSheet !== sharedStyleSheet);
    113      is(nonSharedNestedHostRules.length, 1, "nested host only has 1 non shared rule");
    114      is(
    115        nonSharedNestedHostRules[0].selectorMatchesElement(0, topLevelHostEl),
    116        false,
    117        "non-shared nested host rule does not match top level host"
    118      );
    119    });
    120 
    121    function checkRulesAndSelectors (element, expectedData) {
    122      const rules = getNonUAMatchingRules(element);
    123      is(rules.length, expectedData.length, `Got expected number of rules for #${element.id}`);
    124      for (let i = 0; i < expectedData.length; i++) {
    125        const rule = rules[i];
    126        const expected = expectedData[i];
    127        is(rule.selectorText, expected.selectorText, `Got expected rule at index ${i} for #${element.id}`);
    128        for (let j = 0; j < expected.selectorMatches.length; j++) {
    129          const selectorMatch = expected.selectorMatches[j];
    130          is(
    131            rule.selectorMatchesElement(j, element),
    132            selectorMatch,
    133            `"${rule.selectorText}" selector part at index ${j} ${selectorMatch ? "matches": "does not match"} #${element.id}`
    134          );
    135        }
    136      }
    137    }
    138 
    139    function getNonUAMatchingRules(element) {
    140      return SpecialPowers.InspectorUtils.getMatchingCSSRules(element)
    141        .filter(rule => {
    142          let selector = "";
    143          // Accessing selectorText does throw for some rules (these aren't the ones
    144          // we're interested in, so it's fine)
    145          try {
    146            selector = rule.selectorText;
    147          } catch (e) {}
    148          return selector.includes("[test-rule");
    149        })
    150    }
    151 
    152  </script>
    153 </body>
    154 </html>