Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Selector Invalidation: :has() with nesting parent containing complex selector</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<style>
.anchor { background-color: white; }
.ancestor .descendant {
.anchor:has(&) { background-color: blue; }
}
.ancestor .child {
.anchor:has(> &) { background-color: lightblue; }
}
.ancestor_prev ~ div .descendant {
.anchor:has(&) { background-color: yellow; }
}
.ancestor_prev ~ div.ancestor .descendant {
.anchor:has(&) { background-color: yellowgreen; }
}
.prev ~ .indirect_next {
.anchor:has(~ &) { background-color: green; }
}
.prev ~ .direct_next {
.anchor:has(+ &) { background-color: lightgreen; }
}
</style>
<div><div id="grand_parent1">
<div id="parent1">
<div id="anchor1" class="anchor">
<div><div class="descendant"></div></div>
</div>
</div>
</div></div>
<div><div id="grand_parent2">
<div id="parent2">
<div id="anchor2" class="anchor">
<div class="child"></div>
</div>
</div>
</div></div>
<div><div id="grand_parent_indirect_prev3"></div>
<div id="grand_parent_direct_prev3"></div>
<div id="grand_parent3">
<div id="parent_indirect_prev3"></div>
<div id="parent_direct_prev3"></div>
<div id="parent3">
<div id="anchor_indirect_prev3"></div>
<div id="anchor_direct_prev3"></div>
<div id="anchor3" class="anchor">
<div><div class="descendant"></div></div>
</div>
</div>
</div></div>
<div><div id="indirect_prev4"></div>
<div id="direct_prev4"></div>
<div id="anchor4" class="anchor"></div>
<div></div><div class="indirect_next">
</div></div>
<div><div id="indirect_prev5"></div>
<div id="direct_prev5"></div>
<div id="anchor5" class="anchor"></div>
<div class="direct_next">
</div></div>
<script>
const white = "rgb(255, 255, 255)";
const blue = "rgb(0, 0, 255)";
const lightblue = "rgb(173, 216, 230)";
const yellow = "rgb(255, 255, 0)";
const yellowgreen = "rgb(154, 205, 50)";
const green = "rgb(0, 128, 0)";
const lightgreen = "rgb(144, 238, 144)";
function bg_color(element, color, message) {
promise_test(async () => {
assert_equals(getComputedStyle(element)['background-color'], color);
}, message);
}
function add_class_and_check_bg_color(
element_to_add, class_name, has_anchor, color) {
promise_test(async () => {
element_to_add.classList.add(class_name);
assert_equals(getComputedStyle(has_anchor)['background-color'], color);
}, `#${has_anchor.id} becomes ${color} after adding .${class_name} to #${element_to_add.id}`);
}
function remove_class_and_check_bg_color(
element_to_remove, class_name, has_anchor, color) {
promise_test(async () => {
element_to_remove.classList.remove(class_name);
assert_equals(getComputedStyle(has_anchor)['background-color'], color);
}, `#${has_anchor.id} becomes ${color} after removing .${class_name} from #${element_to_remove.id}`);
}
bg_color(anchor1, white, "#anchor1 initially white");
add_class_and_check_bg_color(grand_parent1, "ancestor", anchor1, blue);
remove_class_and_check_bg_color(grand_parent1, "ancestor", anchor1, white);
add_class_and_check_bg_color(parent1, "ancestor", anchor1, blue);
remove_class_and_check_bg_color(parent1, "ancestor", anchor1, white);
bg_color(anchor2, white, "#anchor2 initially white");
add_class_and_check_bg_color(grand_parent2, "ancestor", anchor2, lightblue);
remove_class_and_check_bg_color(grand_parent2, "ancestor", anchor2, white);
add_class_and_check_bg_color(parent2, "ancestor", anchor2, lightblue);
remove_class_and_check_bg_color(parent2, "ancestor", anchor2, white);
bg_color(anchor3, white, "#anchor3 initially white");
add_class_and_check_bg_color(grand_parent_indirect_prev3, "ancestor_prev",
anchor3, yellow);
add_class_and_check_bg_color(grand_parent3, "ancestor", anchor3, yellowgreen);
remove_class_and_check_bg_color(grand_parent3, "ancestor", anchor3, yellow);
remove_class_and_check_bg_color(grand_parent_indirect_prev3, "ancestor_prev",
anchor3, white);
add_class_and_check_bg_color(grand_parent_direct_prev3, "ancestor_prev",
anchor3, yellow);
remove_class_and_check_bg_color(grand_parent_direct_prev3, "ancestor_prev",
anchor3, white);
add_class_and_check_bg_color(parent_indirect_prev3, "ancestor_prev",
anchor3, yellow);
add_class_and_check_bg_color(parent3, "ancestor", anchor3, yellowgreen);
remove_class_and_check_bg_color(parent3, "ancestor", anchor3, yellow);
remove_class_and_check_bg_color(parent_indirect_prev3, "ancestor_prev",
anchor3, white);
add_class_and_check_bg_color(parent_direct_prev3, "ancestor_prev",
anchor3, yellow);
remove_class_and_check_bg_color(parent_direct_prev3, "ancestor_prev",
anchor3, white);
add_class_and_check_bg_color(anchor_indirect_prev3, "ancestor_prev",
anchor3, yellow);
remove_class_and_check_bg_color(anchor_indirect_prev3, "ancestor_prev",
anchor3, white);
add_class_and_check_bg_color(anchor_direct_prev3, "ancestor_prev",
anchor3, yellow);
remove_class_and_check_bg_color(anchor_direct_prev3, "ancestor_prev",
anchor3, white);
bg_color(anchor4, white, "#anchor4 initially white");
add_class_and_check_bg_color(indirect_prev4, "prev", anchor4, green);
remove_class_and_check_bg_color(indirect_prev4, "prev", anchor4, white);
add_class_and_check_bg_color(direct_prev4, "prev", anchor4, green);
remove_class_and_check_bg_color(direct_prev4, "prev", anchor4, white);
bg_color(anchor5, white, "#anchor5 initially white");
add_class_and_check_bg_color(indirect_prev5, "prev", anchor5, lightgreen);
remove_class_and_check_bg_color(indirect_prev5, "prev", anchor5, white);
add_class_and_check_bg_color(direct_prev5, "prev", anchor5, lightgreen);
remove_class_and_check_bg_color(direct_prev5, "prev", anchor5, white);
</script>