trisquel-icecat/icecat/testing/web-platform/tests/css/css-cascade/scope-nesting.html

545 lines
14 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<title>@scope - nesting (&)</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-6/#scope-atrule">
<link rel="help" href="https://drafts.csswg.org/css-nesting-1/#nest-selector">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<main id=main></main>
<template id=test_nest_scope_end>
<div>
<style>
@scope (.a) to (& > &) {
* { z-index:1; }
}
</style>
<div class=a> <!-- This scope is limited by the element below. -->
<div class=a> <!-- This scope is limited by its own root. -->
<div id=below></div>
</div>
</div>
</div>
<div id=outside></div>
</template>
<script>
test((t) => {
t.add_cleanup(() => main.replaceChildren());
main.append(test_nest_scope_end.content.cloneNode(true));
assert_equals(getComputedStyle(below).zIndex, 'auto');
assert_equals(getComputedStyle(outside).zIndex, 'auto');
}, 'Nesting-selector in <scope-end>');
</script>
<template id=test_nest_scope_end_implicit_scope>
<div>
<style>
/* (.b) behaves like (:scope .b), due :scope being prepended
implicitly. */
@scope (.a) to (.b) {
:scope { z-index:1; }
}
/* Should not match, since <scope-end> refers to the scope itself. */
@scope (.a) to (.b:scope) {
:scope { z-index:42; }
}
</style>
<div class="a b">
<div class=b>
<div id=below></div>
</div>
</div>
</div>
<div id=outside></div>
</template>
<script>
test((t) => {
t.add_cleanup(() => main.replaceChildren());
main.append(test_nest_scope_end_implicit_scope.content.cloneNode(true));
let a = document.querySelector('.a');
let b = document.querySelector('.a > .b');
assert_equals(getComputedStyle(a).zIndex, '1');
assert_equals(getComputedStyle(b).zIndex, 'auto');
assert_equals(getComputedStyle(below).zIndex, 'auto');
assert_equals(getComputedStyle(outside).zIndex, 'auto');
}, 'Implicit :scope in <scope-end>');
</script>
<template id=test_relative_selector_scope_end>
<div>
<style>
@scope (.a) to (> .b) {
*, :scope { z-index:1; }
}
</style>
<div class="a b">
<div class=b>
<div id=below></div>
</div>
</div>
</div>
<div id=outside></div>
</template>
<script>
test((t) => {
t.add_cleanup(() => main.replaceChildren());
main.append(test_relative_selector_scope_end.content.cloneNode(true));
let a = document.querySelector('.a');
let b = document.querySelector('.a > .b');
assert_equals(getComputedStyle(a).zIndex, '1');
assert_equals(getComputedStyle(b).zIndex, 'auto');
assert_equals(getComputedStyle(below).zIndex, 'auto');
assert_equals(getComputedStyle(outside).zIndex, 'auto');
}, 'Relative selectors in <scope-end>');
</script>
<template id=test_inner_nest>
<div>
<style>
@scope (.a) {
& + & {
z-index:1;
}
}
</style>
<div class=a>
<div id=inner1 class=a></div>
<div id=inner2 class=a></div>
</div>
</div>
</template>
<script>
test((t) => {
t.add_cleanup(() => main.replaceChildren());
main.append(test_inner_nest.content.cloneNode(true));
assert_equals(getComputedStyle(inner1).zIndex, 'auto');
assert_equals(getComputedStyle(inner2).zIndex, '1');
}, 'Nesting-selector in the scope\'s <stylesheet>');
</script>
<template id=test_parent_in_pseudo_scope>
<div>
<style>
@scope (#div) {
:scope {
z-index: 1;
& {
z-index: 2;
}
}
}
</style>
<div id=div></div>
</div>
</template>
<script>
test((t) => {
t.add_cleanup(() => main.replaceChildren());
main.append(test_parent_in_pseudo_scope.content.cloneNode(true));
assert_equals(getComputedStyle(div).zIndex, '2');
}, 'Nesting-selector within :scope rule');
</script>
<template id=test_parent_in_pseudo_scope_double>
<div>
<style>
@scope (#div) {
:scope {
z-index: 1;
& {
& {
z-index: 2;
}
}
}
}
</style>
<div id=div></div>
</div>
</template>
<script>
test((t) => {
t.add_cleanup(() => main.replaceChildren());
main.append(test_parent_in_pseudo_scope_double.content.cloneNode(true));
assert_equals(getComputedStyle(div).zIndex, '2');
}, 'Nesting-selector within :scope rule (double nested)');
</script>
<template id=test_scope_within_style_rule>
<div>
<style>
.a {
@scope (.b) {
.c { z-index: 1; }
}
}
</style>
<div class=a>
<div class=b>
<div class=c>
</div>
</div>
<div id=out_of_scope class=c>
</div>
</div>
</div>
</template>
<script>
test((t) => {
t.add_cleanup(() => main.replaceChildren());
main.append(test_scope_within_style_rule.content.cloneNode(true));
let c = document.querySelector('.c');
assert_equals(getComputedStyle(c).zIndex, '1');
assert_equals(getComputedStyle(out_of_scope).zIndex, 'auto');
}, '@scope nested within style rule');
</script>
<template id=test_parent_pseudo_in_nested_scope_start>
<div>
<style>
.a {
@scope (&.b) {
:scope { z-index: 1; }
}
}
</style>
<div class=a></div>
<div class=b></div>
<div class="a b"></div>
</div>
</template>
<script>
test((t) => {
t.add_cleanup(() => main.replaceChildren());
main.append(test_parent_pseudo_in_nested_scope_start.content.cloneNode(true));
let a = document.querySelector('.a:not(.b)');
let b = document.querySelector('.b:not(.a)');
let ab = document.querySelector('.a.b');
assert_equals(getComputedStyle(a).zIndex, 'auto');
assert_equals(getComputedStyle(b).zIndex, 'auto');
assert_equals(getComputedStyle(ab).zIndex, '1');
}, 'Parent pseudo class within scope-start');
</script>
<template id=test_parent_pseudo_in_nested_scope_end>
<div>
<style>
.a {
/* Note that & in <scope-end> refers to <scope-start>,
not the outer style rule. */
@scope (&.b) to (&.c) {
:scope, * { z-index: 1; }
}
}
</style>
<div class="a b">
<div class="a c">
<div class="a b c">
</div>
</div>
</div>
</div>
</template>
<script>
test((t) => {
t.add_cleanup(() => main.replaceChildren());
main.append(test_parent_pseudo_in_nested_scope_end.content.cloneNode(true));
let ab = document.querySelector('.a.b:not(.c)');
let ac = document.querySelector('.a.c:not(.b)');
let abc = document.querySelector('.a.b.c');
assert_equals(getComputedStyle(ab).zIndex, '1');
assert_equals(getComputedStyle(ac).zIndex, '1');
assert_equals(getComputedStyle(abc).zIndex, 'auto', 'limit element is not in scope');
}, 'Parent pseudo class within scope-end');
</script>
<template id=test_parent_pseudo_in_nested_scope_body>
<div>
<style>
.a {
@scope (.b) {
/* The & points to <scope-start>, which contains an implicit &
which points to .a. */
&.c { z-index: 1; }
}
}
</style>
<div class=a>
<div class=b>
<div class="c"></div>
<div class="a c"></div>
<div class="a b c" matching></div>
</div>
</div>
<div>
<div class=a></div>
<div class=b></div>
<div class=c></div>
<div class="a b"></div>
<div class="a c"></div>
<div class="b c"></div>
</div>
</div>
</template>
<script>
test((t) => {
t.add_cleanup(() => main.replaceChildren());
main.append(test_parent_pseudo_in_nested_scope_body.content.cloneNode(true));
let matching = main.querySelectorAll("div[matching]");
let non_matching = main.querySelectorAll("div:not([matching])");
for (let m of matching) {
assert_equals(getComputedStyle(m).zIndex, '1', `matching: ${m.nodeName}${m.className}`);
}
for (let m of non_matching) {
assert_equals(getComputedStyle(m).zIndex, 'auto', `non-matching: ${m.nodeName}${m.className}`);
}
}, 'Parent pseudo class within body of nested @scope');
</script>
<template id=test_direct_declarations_in_nested_scope>
<div>
<style>
.a {
@scope (.b) {
z-index: 1;
}
}
</style>
<div class=a>
<div class=b>
<div class="c"></div>
</div>
</div>
</div>
</template>
<script>
test((t) => {
t.add_cleanup(() => main.replaceChildren());
main.append(test_direct_declarations_in_nested_scope.content.cloneNode(true));
let a = document.querySelector('.a');
let b = document.querySelector('.b');
let c = document.querySelector('.c');
assert_equals(getComputedStyle(a).zIndex, 'auto');
assert_equals(getComputedStyle(b).zIndex, '1');
assert_equals(getComputedStyle(c).zIndex, 'auto');
}, 'Implicit rule within nested @scope ');
</script>
<template id=test_direct_declarations_in_nested_scope_proximity>
<div>
<style>
.a {
/* We're supposed to prepend :scope to this declaration. If we do that,
then :where() does not matter, since :scope does not gain any
specificity from the enclosing @scope rule. However, if an
implementation incorrectly prepends & instead, then :where() is
needed to avoid the test incorrectly passing due to specificity. */
@scope (:where(&) .b) {
z-index: 1; /* Should win due to proximity */
}
}
.b { z-index: 2; }
</style>
<div class=a>
<div class="b x">
<div class=c>
</div>
</div>
</div>
</div>
</template>
<script>
test((t) => {
t.add_cleanup(() => main.replaceChildren());
main.append(test_direct_declarations_in_nested_scope_proximity.content.cloneNode(true));
let a = document.querySelector('.a');
let b = document.querySelector('.b');
let c = document.querySelector('.c');
assert_equals(getComputedStyle(a).zIndex, 'auto');
assert_equals(getComputedStyle(b).zIndex, '1');
assert_equals(getComputedStyle(c).zIndex, 'auto');
}, 'Implicit rule within nested @scope (proximity)');
</script>
<template id=test_nested_scope_inside_an_is>
<div>
<style>
@scope (.a) {
.b {
/* When nesting, because were inside a defined scope,
the `:scope` should reference the scoping root node properly, and
check for the presence of an extra class on it, essentially
being equal to `:scope.x .b { z-index: 1 }`. */
&:is(:scope.x *) {
z-index: 1;
}
/* This should not match, as we have a defined scope, and should
not skip to the root. */
&:is(:root:scope *) {
z-index: 2;
}
}
/* The nested case can be though of the following when expanded: */
.c:is(:scope.x *) {
z-index: 3;
}
}
</style>
<div class="b">
</div>
<div class="a x">
<div class="b">
</div>
<div class="c">
</div>
</div>
</div>
</template>
<script>
test((t) => {
t.add_cleanup(() => main.replaceChildren());
main.append(test_nested_scope_inside_an_is.content.cloneNode(true));
let b_outside = document.querySelector('.b');
let b_inside = document.querySelector('.a .b');
let c = document.querySelector('.c');
assert_equals(getComputedStyle(b_outside).zIndex, 'auto');
assert_equals(getComputedStyle(b_inside).zIndex, '1');
assert_equals(getComputedStyle(c).zIndex, '3');
}, 'Nested :scope inside an :is');
</script>
<template id=test_nested_scope_pseudo>
<div>
<style>
@scope (.b) {
.a:not(:scope) {
& :scope {
z-index: 1;
}
}
}
</style>
<div class="b">
</div>
<div class="a">
<div class="b">
</div>
</div>
</div>
</template>
<script>
test((t) => {
t.add_cleanup(() => main.replaceChildren());
main.append(test_nested_scope_pseudo.content.cloneNode(true));
let b_outside = document.querySelector('.b');
let b_inside = document.querySelector('.a .b');
assert_equals(getComputedStyle(b_outside).zIndex, 'auto');
assert_equals(getComputedStyle(b_inside).zIndex, '1');
}, ':scope within nested and scoped rule');
</script>
<template id=test_nested_scope_pseudo_implied>
<div>
<style>
@scope (.b) {
.a:not(:scope) {
:scope { /* & implied */
z-index: 1;
}
}
}
</style>
<div class="b">
</div>
<div class="a">
<div class="b">
</div>
</div>
</div>
</template>
<script>
test((t) => {
t.add_cleanup(() => main.replaceChildren());
main.append(test_nested_scope_pseudo_implied.content.cloneNode(true));
let b_outside = document.querySelector('.b');
let b_inside = document.querySelector('.a .b');
assert_equals(getComputedStyle(b_outside).zIndex, 'auto');
assert_equals(getComputedStyle(b_inside).zIndex, '1');
}, ':scope within nested and scoped rule (implied &)');
</script>
<template id=test_nested_scope_pseudo_relative>
<div>
<style>
@scope (.b) {
.a:not(:scope) {
> :scope { /* & implied */
z-index: 1;
}
}
}
</style>
<div class="b">
</div>
<div class="a">
<div class="b">
</div>
</div>
</div>
</template>
<script>
test((t) => {
t.add_cleanup(() => main.replaceChildren());
main.append(test_nested_scope_pseudo_relative.content.cloneNode(true));
let b_outside = document.querySelector('.b');
let b_inside = document.querySelector('.a .b');
assert_equals(getComputedStyle(b_outside).zIndex, 'auto');
assert_equals(getComputedStyle(b_inside).zIndex, '1');
}, ':scope within nested and scoped rule (relative)');
</script>
<template id=test_scoped_nested_group_rule>
<div>
<style>
@scope (.a) {
.b:not(:scope) {
@media (width) {
z-index: 1;
}
}
}
</style>
<div class="b">
</div>
<div class="a">
<div class="b">
</div>
</div>
</div>
</template>
<script>
test((t) => {
t.add_cleanup(() => main.replaceChildren());
main.append(test_scoped_nested_group_rule.content.cloneNode(true));
let b_outside = document.querySelector('.b');
let b_inside = document.querySelector('.a .b');
assert_equals(getComputedStyle(b_outside).zIndex, 'auto');
assert_equals(getComputedStyle(b_inside).zIndex, '1');
}, 'Scoped nested group rule');
</script>