Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!DOCTYPE html>
<meta charset="utf-8">
<title>:host:has(...) to check whether a shadow host has a shadow tree element (nonsubject position)</title>
<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div class="ancestor host_context">
<div id="host" class="ancestor">
<template shadowrootmode="open">
<style>
div { color: red; }
:host:has(.descendant) .subject { color: green; }
:host:has(> .child) .subject { color: blue; }
:host:has(~ .sibling) .subject { color: yellow; }
:host:has(:is(.ancestor .descendant)) .subject { color: purple; }
:host:has(.descendant):has(> .child) .subject { color: pink; }
:host-context(.host_context):has(> .child > .grand_child) .subject { color: ivory; }
:host(.host_context):has(> .child > .grand_child) .subject { color: skyblue; }
:host:has(> .child > .grand_child):host(.host_context):has(> .child > .descendant) .subject { color: lightgreen; }
</style>
<div id="subject" class="subject"></div>
<div id="shadow_child">
<div id="shadow_descendant"></div>
</div>
</template>
<div class="child">
<div class="descendant"></div>
</div>
</div>
<div class="sibling"></div>
</div>
<script>
const red = 'rgb(255, 0, 0)';
const green = 'rgb(0, 128, 0)';
const blue = 'rgb(0, 0, 255)';
const yellow = 'rgb(255, 255, 0)';
const purple = 'rgb(128, 0, 128)';
const pink = 'rgb(255, 192, 203)';
const ivory = 'rgb(255, 255, 240)';
const skyblue = 'rgb(135, 206, 235)';
const lightgreen = 'rgb(144, 238, 144)';
var shadow_root = host.shadowRoot;
function element(id) {
return document.getElementById(id);
}
function shadow_element(id) {
return shadow_root.getElementById(id);
}
var subject = shadow_element('subject');
function test_color(test_name, color) {
test(function() {
assert_equals(getComputedStyle(subject).color, color);
}, test_name);
}
function create_div(id, class_name) {
let div = document.createElement('div');
div.id = id;
div.classList.add(class_name);
return div
}
test_color('Initial color', red);
shadow_element('shadow_child').classList.add('descendant');
test_color(`Add .descendant to #shadow_child`, green);
shadow_element('shadow_child').classList.remove('descendant');
test_color(`Remove .descendant from #shadow_child`, red);
shadow_element('shadow_descendant').classList.add('descendant');
test_color(`Add .descendant to #shadow_descendant`, green);
shadow_element('shadow_child').classList.add('ancestor');
test_color(`Add .ancestor to #shadow_child:has(.descendant)`, purple);
shadow_element('shadow_child').classList.remove('ancestor');
test_color(`Remove .ancestor from #shadow_child:has(.descendant)`, green);
shadow_element('shadow_child').classList.add('child');
test_color(`Add .child to #shadow_child:has(.descendant)`, pink);
shadow_element('shadow_child').classList.remove('child');
test_color(`Remove .child from #shadow_child:has(.descendant)`, green);
shadow_element('shadow_descendant').classList.remove('descendant');
test_color(`Remove .descendant from #shadow_descendant`, red);
shadow_element('shadow_child').classList.add('child');
test_color(`Add .child to #shadow_child`, blue);
shadow_element('shadow_descendant').classList.add('grand_child');
test_color(`Add .grand_child to #shadow_descendant`, ivory);
element('host').classList.add('host_context');
test_color(`Add .host_context to #host`, skyblue);
shadow_element('shadow_descendant').classList.add('descendant');
test_color(`Add .descendant to #shadow_descendant.grand_child`, lightgreen);
shadow_element('shadow_descendant').classList.remove('descendant');
test_color(`Remove .descendant from #shadow_descendant.grand_child`, skyblue);
shadow_element('shadow_descendant').classList.remove('grand_child');
test_color(`Remove .grand_child from #shadow_descendant`, blue);
shadow_element('shadow_child').classList.remove('child');
test_color(`Remove .child from #shadow_child`, red);
shadow_element('shadow_descendant').classList.add('child');
test_color(`Add .child to #shadow_descendant`, red);
shadow_element('shadow_descendant').classList.remove('child');
test_color(`Remove .child from #shadow_descendant`, red);
div = shadow_root.insertBefore(create_div('first_child', 'descendant'),
shadow_root.firstChild);
test_color(`Insert #first_child.descendant to shadow root`, green);
div.remove();
test_color(`Remove #first_child.descendant from shadow root`, red);
div = shadow_root.insertBefore(create_div('last_child', 'descendant'), null);
test_color(`Insert #last_child.descendant to shadow root`, green);
div.remove();
test_color(`Remove #last_child.descendant from shadow root`, red);
div = shadow_root.insertBefore(create_div('child_in_middle','descendant'),
shadow_element('shadow_child'));
test_color(`Insert #child_in_middle.descendant before #shadow_child`, green);
div.remove();
test_color(`Remove #child_in_middle.descendant from shadow root`, red);
div = shadow_element('shadow_child')
.insertBefore(create_div('grand_child','descendant'),
shadow_element('shadow_descendant'));
test_color(`Insert #grand_child.descendant before #shadow_descendant`, green);
div.remove();
test_color(`Remove #grand_child.descendant from shadow tree`, red);
</script>