summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/css/css-cascade/at-scope-relative-syntax.html
blob: 274d9afbebec2be5532a6a55ca1b605a2dbe6559 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<!doctype html>
<title>@scope and Nesting: Parsing inner style rules with relative selector syntax</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-6/#scoped-rules">
<link rel="help" href="https://drafts.csswg.org/css-nesting/#nesting">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<main id=main></main>
<script>
  function create_rule_string(prelude, inner) {
    if (prelude.length === 0) {
      return `${inner} {}`;
    }
    let outermost = prelude[0];
    let rest = create_rule_string(prelude.slice(1), inner);
    return `${outermost} { ${rest} }`;
  }

  function create_rule_by_string(style, prelude, inner) {
    style.textContent = create_rule_string(prelude, inner);
  }

  function create_rule_by_insertion(style, prelude, inner) {
    let current = style.sheet;
    for (const p of prelude) {
      let idx = current.insertRule(`${p} {}`);
      current = current.cssRules[idx];
    }
    current.insertRule(`${inner} {}`);
  }

  function innermost_selector(depth, rules) {
    let r = rules;
    let d = depth + 1;
    while (d != 0) {
      assert_equals(r.cssRules.length, 1);
      r = r.cssRules[0];
      d--;
    }
    return r.selectorText;
  }

  const create_method = {
    "string": create_rule_by_string,
    "insertRule": create_rule_by_insertion,
  };

  function test_inner(prelude, method, actual, expected) {
    if (expected === undefined) {
      expected = actual;
    }
    test(t => {
      t.add_cleanup(() => main.replaceChildren());
      const style = document.createElement('style');
      main.append(style);
      create_method[method](style, prelude, actual);
      const innerSelector = innermost_selector(prelude.length, style.sheet);
      assert_equals(innerSelector, expected);
    }, `${actual} in ${prelude} created by ${method} valid`);
  }

  for (const method of Object.keys(create_method)) {
    test_inner(['@scope' , '.nest'], method, '> .foo', '& > .foo');
    test_inner(['.nest', '@scope'], method, '> .foo', ':scope > .foo');

    test_inner(['@scope' , '.nest', '@media screen'], method, '> .foo', '& > .foo');
    test_inner(['.nest', '@scope', '@media screen'], method, '> .foo', ':scope > .foo');
  }
</script>