host-has-shadow-tree-element-at-nonsubject-position.html (5580B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <title>:host:has(...) to check whether a shadow host has a shadow tree element (nonsubject position)</title> 4 <link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com"> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 <link rel="help" href="https://drafts.csswg.org/selectors/#relational"> 8 <div class="ancestor host_context"> 9 <div id="host" class="ancestor"> 10 <template shadowrootmode="open"> 11 <style> 12 div { color: red; } 13 :host:has(.descendant) .subject { color: green; } 14 :host:has(> .child) .subject { color: blue; } 15 :host:has(~ .sibling) .subject { color: yellow; } 16 :host:has(:is(.ancestor .descendant)) .subject { color: purple; } 17 :host:has(.descendant):has(> .child) .subject { color: pink; } 18 :host-context(.host_context):has(> .child > .grand_child) .subject { color: ivory; } 19 :host(.host_context):has(> .child > .grand_child) .subject { color: skyblue; } 20 :host:has(> .child > .grand_child):host(.host_context):has(> .child > .descendant) .subject { color: lightgreen; } 21 </style> 22 <div id="subject" class="subject"></div> 23 <div id="shadow_child"> 24 <div id="shadow_descendant"></div> 25 </div> 26 </template> 27 <div class="child"> 28 <div class="descendant"></div> 29 </div> 30 </div> 31 <div class="sibling"></div> 32 </div> 33 34 <script> 35 const red = 'rgb(255, 0, 0)'; 36 const green = 'rgb(0, 128, 0)'; 37 const blue = 'rgb(0, 0, 255)'; 38 const yellow = 'rgb(255, 255, 0)'; 39 const purple = 'rgb(128, 0, 128)'; 40 const pink = 'rgb(255, 192, 203)'; 41 const ivory = 'rgb(255, 255, 240)'; 42 const skyblue = 'rgb(135, 206, 235)'; 43 const lightgreen = 'rgb(144, 238, 144)'; 44 45 var shadow_root = host.shadowRoot; 46 47 function element(id) { 48 return document.getElementById(id); 49 } 50 51 function shadow_element(id) { 52 return shadow_root.getElementById(id); 53 } 54 55 var subject = shadow_element('subject'); 56 57 function test_color(test_name, color) { 58 test(function() { 59 assert_equals(getComputedStyle(subject).color, color); 60 }, test_name); 61 } 62 63 function create_div(id, class_name) { 64 let div = document.createElement('div'); 65 div.id = id; 66 div.classList.add(class_name); 67 return div 68 } 69 70 test_color('Initial color', red); 71 72 shadow_element('shadow_child').classList.add('descendant'); 73 test_color(`Add .descendant to #shadow_child`, green); 74 75 shadow_element('shadow_child').classList.remove('descendant'); 76 test_color(`Remove .descendant from #shadow_child`, red); 77 78 shadow_element('shadow_descendant').classList.add('descendant'); 79 test_color(`Add .descendant to #shadow_descendant`, green); 80 81 shadow_element('shadow_child').classList.add('ancestor'); 82 test_color(`Add .ancestor to #shadow_child:has(.descendant)`, purple); 83 84 shadow_element('shadow_child').classList.remove('ancestor'); 85 test_color(`Remove .ancestor from #shadow_child:has(.descendant)`, green); 86 87 shadow_element('shadow_child').classList.add('child'); 88 test_color(`Add .child to #shadow_child:has(.descendant)`, pink); 89 90 shadow_element('shadow_child').classList.remove('child'); 91 test_color(`Remove .child from #shadow_child:has(.descendant)`, green); 92 93 shadow_element('shadow_descendant').classList.remove('descendant'); 94 test_color(`Remove .descendant from #shadow_descendant`, red); 95 96 shadow_element('shadow_child').classList.add('child'); 97 test_color(`Add .child to #shadow_child`, blue); 98 99 shadow_element('shadow_descendant').classList.add('grand_child'); 100 test_color(`Add .grand_child to #shadow_descendant`, ivory); 101 102 element('host').classList.add('host_context'); 103 test_color(`Add .host_context to #host`, skyblue); 104 105 shadow_element('shadow_descendant').classList.add('descendant'); 106 test_color(`Add .descendant to #shadow_descendant.grand_child`, lightgreen); 107 108 shadow_element('shadow_descendant').classList.remove('descendant'); 109 test_color(`Remove .descendant from #shadow_descendant.grand_child`, skyblue); 110 111 shadow_element('shadow_descendant').classList.remove('grand_child'); 112 test_color(`Remove .grand_child from #shadow_descendant`, blue); 113 114 shadow_element('shadow_child').classList.remove('child'); 115 test_color(`Remove .child from #shadow_child`, red); 116 117 shadow_element('shadow_descendant').classList.add('child'); 118 test_color(`Add .child to #shadow_descendant`, red); 119 120 shadow_element('shadow_descendant').classList.remove('child'); 121 test_color(`Remove .child from #shadow_descendant`, red); 122 123 div = shadow_root.insertBefore(create_div('first_child', 'descendant'), 124 shadow_root.firstChild); 125 test_color(`Insert #first_child.descendant to shadow root`, green); 126 div.remove(); 127 test_color(`Remove #first_child.descendant from shadow root`, red); 128 129 div = shadow_root.insertBefore(create_div('last_child', 'descendant'), null); 130 test_color(`Insert #last_child.descendant to shadow root`, green); 131 div.remove(); 132 test_color(`Remove #last_child.descendant from shadow root`, red); 133 134 div = shadow_root.insertBefore(create_div('child_in_middle','descendant'), 135 shadow_element('shadow_child')); 136 test_color(`Insert #child_in_middle.descendant before #shadow_child`, green); 137 div.remove(); 138 test_color(`Remove #child_in_middle.descendant from shadow root`, red); 139 140 div = shadow_element('shadow_child') 141 .insertBefore(create_div('grand_child','descendant'), 142 shadow_element('shadow_descendant')); 143 test_color(`Insert #grand_child.descendant before #shadow_descendant`, green); 144 div.remove(); 145 test_color(`Remove #grand_child.descendant from shadow tree`, red); 146 147 </script>