diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
commit | 0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d (patch) | |
tree | a31f07c9bcca9d56ce61e9a1ffd30ef350d513aa /testing/web-platform/tests/css/css-nesting/cssom.html | |
parent | Initial commit. (diff) | |
download | firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.tar.xz firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.zip |
Adding upstream version 115.8.0esr.upstream/115.8.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/css/css-nesting/cssom.html')
-rw-r--r-- | testing/web-platform/tests/css/css-nesting/cssom.html | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/testing/web-platform/tests/css/css-nesting/cssom.html b/testing/web-platform/tests/css/css-nesting/cssom.html new file mode 100644 index 0000000000..b5bd80d1b4 --- /dev/null +++ b/testing/web-platform/tests/css/css-nesting/cssom.html @@ -0,0 +1,187 @@ +<!doctype html> +<title>Simple CSSOM manipulation of subrules</title> +<link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-nesting-1/"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<style id="ss"></style> + +<script> + test(() => { + let [ss] = document.styleSheets; + assert_equals(ss.cssRules.length, 0); + ss.insertRule('.a { color: red; }'); + assert_equals(ss.cssRules.length, 1); + assert_equals(ss.cssRules[0].cssText, '.a { color: red; }'); + + // Test inserting sub-cssRules, at various positions. + ss.cssRules[0].insertRule('& .b { color: green; }'); + ss.cssRules[0].insertRule('& .c { color: blue; }', 1); + ss.cssRules[0].insertRule('& .d { color: hotpink; }', 1); + assert_equals(ss.cssRules[0].cssText, +`.a { + color: red; + & .b { color: green; } + & .d { color: hotpink; } + & .c { color: blue; } +}`, 'inserting should work'); + + // Test deleting a rule. + ss.cssRules[0].deleteRule(1); + assert_equals(ss.cssRules[0].cssText, +`.a { + color: red; + & .b { color: green; } + & .c { color: blue; } +}`, 'deleting should work'); + }); + + // Test that out-of-bounds throws exceptions and does not affect the stylesheet. + const sampleSheetText = +`.a { + color: red; + & .b { color: green; } + & .c { color: blue; } +}`; + + test(() => { + document.getElementById('ss').innerHTML = sampleSheetText; + let [ss] = document.styleSheets; + assert_throws_dom('IndexSizeError', () => { ss.cssRules[0].insertRule('& .broken {}', 3); }); + assert_equals(ss.cssRules[0].cssText, sampleSheetText, 'unchanged after no-insert'); + }); + + test(() => { + document.getElementById('ss').innerHTML = sampleSheetText; + let [ss] = document.styleSheets; + assert_throws_dom('IndexSizeError', () => { ss.cssRules[0].insertRule('& .broken {}', -1); }); + assert_equals(ss.cssRules[0].cssText, sampleSheetText, 'unchanged after no-insert'); + }); + + test(() => { + document.getElementById('ss').innerHTML = sampleSheetText; + let [ss] = document.styleSheets; + assert_throws_dom('IndexSizeError', () => { ss.cssRules[0].deleteRule(5); }); + assert_equals(ss.cssRules[0].cssText, sampleSheetText, 'unchanged after no-delete'); + }); + + test(() => { + document.getElementById('ss').innerHTML = sampleSheetText; + let [ss] = document.styleSheets; + assert_equals(ss.cssRules[0].cssRules[2], undefined, 'subscript out-of-bounds returns undefined'); + assert_equals(ss.cssRules[0].cssRules.item(2), null, 'item() out-of-bounds returns null'); + assert_equals(ss.cssRules[0].cssText, sampleSheetText, 'unchanged after no-access'); + }); + + // Test that inserting an invalid rule throws an exception. + test(() => { + document.getElementById('ss').innerHTML = sampleSheetText; + let [ss] = document.styleSheets; + let exception; + assert_throws_dom('SyntaxError', () => { ss.cssRules[0].insertRule('% {}'); }); + assert_equals(ss.cssRules[0].cssText, sampleSheetText, 'unchanged after invalid rule'); + }); + + // Test that we can get out single rule through .cssRules. + test(() => { + document.getElementById('ss').innerHTML = sampleSheetText; + let [ss] = document.styleSheets; + assert_equals(ss.cssRules[0].cssRules[1].cssText, '& .c { color: blue; }'); + }); + + // Test that we can insert a @supports rule, that it serializes in the right place + // and has the right parent. Note that the indentation is broken per-spec. + test(() => { + document.getElementById('ss').innerHTML = sampleSheetText; + let [ss] = document.styleSheets; + ss.cssRules[0].insertRule('@supports selector(&) { & div { font-size: 10px; }}', 1); + assert_equals(ss.cssRules[0].cssText, +`.a { + color: red; + & .b { color: green; } + @supports selector(&) { + & div { font-size: 10px; } +} + & .c { color: blue; } +}`, '@supports is added'); + + assert_equals(ss.cssRules[0].cssRules[1].parentRule, ss.cssRules[0]); + ss.cssRules[0].deleteRule(1); + assert_equals(ss.cssRules[0].cssText, sampleSheetText); + }); + + // Nested rules are not part of declaration lists, and thus should not + // be possible to insert with .style. + test(() => { + document.getElementById('ss').innerHTML = sampleSheetText; + let [ss] = document.styleSheets; + ss.cssRules[0].style = 'color: olivedrab; &.d { color: peru; }'; + assert_equals(ss.cssRules[0].cssText, +`.a { + color: olivedrab; + & .b { color: green; } + & .c { color: blue; } +}`, 'color is changed, new rule is ignored'); + }); + + // We cannot insert anything starting with an tag, as that would cause + // the serialized rule not to parse back. Compounds starting with a tag + // that are _not_ the first compound in a complex selector are OK, though, + // as are complex selectors that are not the first in the list. + test(() => { + document.getElementById('ss').innerHTML = sampleSheetText; + let [ss] = document.styleSheets; + ss.cssRules[0].cssRules[0].selectorText = 'div.b .c &'; // Ignored. + ss.cssRules[0].cssRules[1].selectorText = '.c div.b &, div &'; // Allowed. + assert_throws_dom('SyntaxError', () => { ss.cssRules[0].insertRule('div & {}'); }); + assert_equals(ss.cssRules[0].cssText, +`.a { + color: red; + & .b { color: green; } + .c div.b &, div & { color: blue; } +}`, 'one rule is kept unchanged, the other is changed'); + }); + + // Rules that are dropped in forgiving parsing but that contain &, + // must still be serialized out as they were. + test(() => { + const text = '.a { :is(!& .foo, .b) { color: green; } }'; + document.getElementById('ss').innerHTML = text; + let [ss] = document.styleSheets; + assert_equals(ss.cssRules[0].cssText, +`.a { + :is(!& .foo, .b) { color: green; } +}`, 'invalid rule containing ampersand is kept in serialization'); + }); + + test((t) => { + let main = document.createElement('main'); + main.innerHTML = ` + <style> + .a { + & { z-index:1; } + & #inner1 { z-index:1; } + .stuff, :is(&) #inner2 { z-index:1; } + } + </style> + <div id="outer" class="b"> + <div id="inner1"></div> + <div id="inner2"></div> + </div> + `; + document.documentElement.append(main); + t.add_cleanup(() => main.remove()); + + assert_equals(getComputedStyle(outer).zIndex, 'auto'); + assert_equals(getComputedStyle(inner1).zIndex, 'auto'); + assert_equals(getComputedStyle(inner2).zIndex, 'auto'); + + // .a => .b + main.firstElementChild.sheet.cssRules[0].selectorText = '.b'; + + assert_equals(getComputedStyle(outer).zIndex, '1'); + assert_equals(getComputedStyle(inner1).zIndex, '1'); + assert_equals(getComputedStyle(inner2).zIndex, '1'); + }, 'Mutating the selectorText of outer rule invalidates inner rules'); +</script> |