has-relative-argument.html (5516B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <title>:has pseudo class behavior with various relative arguments</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 9 <main id=main> 10 <div id=d01> 11 <div id=d02 class="x"> 12 <div id=d03 class="a"></div> 13 <div id=d04></div> 14 <div id=d05 class="b"></div> 15 </div> 16 <div id=d06 class="x"> 17 <div id=d07 class="x"> 18 <div id=d08 class="a"></div> 19 </div> 20 </div> 21 <div id=d09 class="x"> 22 <div id=d10 class="a"> 23 <div id=d11 class="b"></div> 24 </div> 25 </div> 26 <div id=d12 class="x"> 27 <div id=d13 class="a"> 28 <div id=d14> 29 <div id=d15 class="b"></div> 30 </div> 31 </div> 32 <div id=d16 class="b"></div> 33 </div> 34 </div> 35 <div id=d17> 36 <div id=d18 class="x"></div> 37 <div id=d19 class="x"></div> 38 <div id=d20 class="a"></div> 39 <div id=d21 class="x"></div> 40 <div id=d22 class="a"> 41 <div id=d23 class="b"></div> 42 </div> 43 <div id=d24 class="x"></div> 44 <div id=d25 class="a"> 45 <div id=d26> 46 <div id=d27 class="b"></div> 47 </div> 48 </div> 49 <div id=d28 class="x"></div> 50 <div id=d29 class="a"></div> 51 <div id=d30 class="b"> 52 <div id=d31 class="c"></div> 53 </div> 54 <div id=d32 class="x"></div> 55 <div id=d33 class="a"></div> 56 <div id=d34 class="b"> 57 <div id=d35> 58 <div id=d36 class="c"></div> 59 </div> 60 </div> 61 <div id=d37 class="x"></div> 62 <div id=d38 class="a"></div> 63 <div id=d39 class="b"></div> 64 <div id=d40 class="x"></div> 65 <div id=d41 class="a"></div> 66 <div id=d42></div> 67 <div id=d43 class="b"> 68 <div id=d44 class="x"> 69 <div id=d45 class="c"></div> 70 </div> 71 </div> 72 <div id=d46 class="x"></div> 73 <div id=d47 class="a"> 74 </div> 75 </div> 76 <div> 77 <div id=d48 class="x"> 78 <div id=d49 class="x"> 79 <div id=d50 class="x d"> 80 <div id=d51 class="x d"> 81 <div id=d52 class="x"> 82 <div id=d53 class="x e"> 83 <div id=d54 class="f"></div> 84 </div> 85 </div> 86 </div> 87 </div> 88 </div> 89 </div> 90 <div id=d55 class="x"></div> 91 <div id=d56 class="x d"></div> 92 <div id=d57 class="x d"></div> 93 <div id=d58 class="x"></div> 94 <div id=d59 class="x e"></div> 95 <div id=d60 class="f"></div> 96 </div> 97 <div> 98 <div id=d61 class="x"></div> 99 <div id=d62 class="x y"></div> 100 <div id=d63 class="x y"> 101 <div id=d64 class="y g"> 102 <div id=d65 class="y"> 103 <div id=d66 class="y h"> 104 <div id=d67 class="i"></div> 105 </div> 106 </div> 107 </div> 108 </div> 109 <div id=d68 class="x y"> 110 <div id=d69 class="x"></div> 111 <div id=d70 class="x"></div> 112 <div id=d71 class="x y"> 113 <div id=d72 class="y g"> 114 <div id=d73 class="y"> 115 <div id=d74 class="y h"> 116 <div id=d75 class="i"></div> 117 </div> 118 </div> 119 </div> 120 </div> 121 <div id=d76 class="x"></div> 122 <div id=d77 class="j"><div id=d78><div id=d79></div></div></div> 123 </div> 124 <div id=d80 class="j"></div> 125 </div> 126 </main> 127 128 <script> 129 function formatElements(elements) { 130 return elements.map(e => e.id).sort().join(); 131 } 132 133 // Test that |selector| returns the given elements in #main. 134 function test_selector_all(selector, expected) { 135 test(function() { 136 let actual = Array.from(main.querySelectorAll(selector)); 137 assert_equals(formatElements(actual), formatElements(expected)); 138 }, `${selector} matches expected elements`); 139 } 140 141 test_selector_all('.x:has(.a)', [d02, d06, d07, d09, d12]); 142 test_selector_all('.x:has(.a > .b)', [d09]); 143 test_selector_all('.x:has(.a .b)', [d09, d12]); 144 test_selector_all('.x:has(.a + .b)', [d12]); 145 test_selector_all('.x:has(.a ~ .b)', [d02, d12]); 146 147 test_selector_all('.x:has(> .a)', [d02, d07, d09, d12]); 148 test_selector_all('.x:has(> .a > .b)', [d09]); 149 test_selector_all('.x:has(> .a .b)', [d09, d12]); 150 test_selector_all('.x:has(> .a + .b)', [d12]); 151 test_selector_all('.x:has(> .a ~ .b)', [d02, d12]); 152 153 test_selector_all('.x:has(+ .a)', [d19, d21, d24, d28, d32, d37, d40, d46]); 154 test_selector_all('.x:has(+ .a > .b)', [d21]); 155 test_selector_all('.x:has(+ .a .b)', [d21, d24]); 156 test_selector_all('.x:has(+ .a + .b)', [d28, d32, d37]); 157 test_selector_all('.x:has(+ .a ~ .b)', [d19, d21, d24, d28, d32, d37, d40]); 158 159 test_selector_all('.x:has(~ .a)', [d18, d19, d21, d24, d28, d32, d37, d40, d46]); 160 test_selector_all('.x:has(~ .a > .b)', [d18, d19, d21]); 161 test_selector_all('.x:has(~ .a .b)', [d18, d19, d21, d24]); 162 test_selector_all('.x:has(~ .a + .b)', [d18, d19, d21, d24, d28, d32, d37]); 163 test_selector_all('.x:has(~ .a + .b > .c)', [d18, d19, d21, d24, d28]); 164 test_selector_all('.x:has(~ .a + .b .c)', [d18, d19, d21, d24, d28, d32]); 165 166 test_selector_all('.x:has(.d .e)', [d48, d49, d50]); 167 test_selector_all('.x:has(.d .e) .f', [d54]); 168 test_selector_all('.x:has(> .d)', [d49, d50]); 169 test_selector_all('.x:has(> .d) .f', [d54]); 170 test_selector_all('.x:has(~ .d ~ .e)', [d48, d55, d56]); 171 test_selector_all('.x:has(~ .d ~ .e) ~ .f', [d60]); 172 test_selector_all('.x:has(+ .d ~ .e)', [d55, d56]); 173 test_selector_all('.x:has(+ .d ~ .e) ~ .f', [d60]); 174 175 test_selector_all('.y:has(> .g .h)', [d63, d71]) 176 test_selector_all('.y:has(.g .h)', [d63, d68, d71]) 177 test_selector_all('.y:has(> .g .h) .i', [d67, d75]) 178 test_selector_all('.y:has(.g .h) .i', [d67, d75]) 179 180 test_selector_all('.d .x:has(.e)', [d51, d52]) 181 182 test_selector_all('.d ~ .x:has(~ .e)', [d57, d58]) 183 184 </script>