Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

<!DOCTYPE html>
<meta charset="utf-8">
<title>:has pseudo class behavior with various relative arguments</title>
<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<main id=main>
<div id=d01>
<div id=d02 class="x">
<div id=d03 class="a"></div>
<div id=d04></div>
<div id=d05 class="b"></div>
</div>
<div id=d06 class="x">
<div id=d07 class="x">
<div id=d08 class="a"></div>
</div>
</div>
<div id=d09 class="x">
<div id=d10 class="a">
<div id=d11 class="b"></div>
</div>
</div>
<div id=d12 class="x">
<div id=d13 class="a">
<div id=d14>
<div id=d15 class="b"></div>
</div>
</div>
<div id=d16 class="b"></div>
</div>
</div>
<div id=d17>
<div id=d18 class="x"></div>
<div id=d19 class="x"></div>
<div id=d20 class="a"></div>
<div id=d21 class="x"></div>
<div id=d22 class="a">
<div id=d23 class="b"></div>
</div>
<div id=d24 class="x"></div>
<div id=d25 class="a">
<div id=d26>
<div id=d27 class="b"></div>
</div>
</div>
<div id=d28 class="x"></div>
<div id=d29 class="a"></div>
<div id=d30 class="b">
<div id=d31 class="c"></div>
</div>
<div id=d32 class="x"></div>
<div id=d33 class="a"></div>
<div id=d34 class="b">
<div id=d35>
<div id=d36 class="c"></div>
</div>
</div>
<div id=d37 class="x"></div>
<div id=d38 class="a"></div>
<div id=d39 class="b"></div>
<div id=d40 class="x"></div>
<div id=d41 class="a"></div>
<div id=d42></div>
<div id=d43 class="b">
<div id=d44 class="x">
<div id=d45 class="c"></div>
</div>
</div>
<div id=d46 class="x"></div>
<div id=d47 class="a">
</div>
</div>
<div>
<div id=d48 class="x">
<div id=d49 class="x">
<div id=d50 class="x d">
<div id=d51 class="x d">
<div id=d52 class="x">
<div id=d53 class="x e">
<div id=d54 class="f"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id=d55 class="x"></div>
<div id=d56 class="x d"></div>
<div id=d57 class="x d"></div>
<div id=d58 class="x"></div>
<div id=d59 class="x e"></div>
<div id=d60 class="f"></div>
</div>
<div>
<div id=d61 class="x"></div>
<div id=d62 class="x y"></div>
<div id=d63 class="x y">
<div id=d64 class="y g">
<div id=d65 class="y">
<div id=d66 class="y h">
<div id=d67 class="i"></div>
</div>
</div>
</div>
</div>
<div id=d68 class="x y">
<div id=d69 class="x"></div>
<div id=d70 class="x"></div>
<div id=d71 class="x y">
<div id=d72 class="y g">
<div id=d73 class="y">
<div id=d74 class="y h">
<div id=d75 class="i"></div>
</div>
</div>
</div>
</div>
<div id=d76 class="x"></div>
<div id=d77 class="j"><div id=d78><div id=d79></div></div></div>
</div>
<div id=d80 class="j"></div>
</div>
</main>
<script>
function formatElements(elements) {
return elements.map(e => e.id).sort().join();
}
// Test that |selector| returns the given elements in #main.
function test_selector_all(selector, expected) {
test(function() {
let actual = Array.from(main.querySelectorAll(selector));
assert_equals(formatElements(actual), formatElements(expected));
}, `${selector} matches expected elements`);
}
test_selector_all('.x:has(.a)', [d02, d06, d07, d09, d12]);
test_selector_all('.x:has(.a > .b)', [d09]);
test_selector_all('.x:has(.a .b)', [d09, d12]);
test_selector_all('.x:has(.a + .b)', [d12]);
test_selector_all('.x:has(.a ~ .b)', [d02, d12]);
test_selector_all('.x:has(> .a)', [d02, d07, d09, d12]);
test_selector_all('.x:has(> .a > .b)', [d09]);
test_selector_all('.x:has(> .a .b)', [d09, d12]);
test_selector_all('.x:has(> .a + .b)', [d12]);
test_selector_all('.x:has(> .a ~ .b)', [d02, d12]);
test_selector_all('.x:has(+ .a)', [d19, d21, d24, d28, d32, d37, d40, d46]);
test_selector_all('.x:has(+ .a > .b)', [d21]);
test_selector_all('.x:has(+ .a .b)', [d21, d24]);
test_selector_all('.x:has(+ .a + .b)', [d28, d32, d37]);
test_selector_all('.x:has(+ .a ~ .b)', [d19, d21, d24, d28, d32, d37, d40]);
test_selector_all('.x:has(~ .a)', [d18, d19, d21, d24, d28, d32, d37, d40, d46]);
test_selector_all('.x:has(~ .a > .b)', [d18, d19, d21]);
test_selector_all('.x:has(~ .a .b)', [d18, d19, d21, d24]);
test_selector_all('.x:has(~ .a + .b)', [d18, d19, d21, d24, d28, d32, d37]);
test_selector_all('.x:has(~ .a + .b > .c)', [d18, d19, d21, d24, d28]);
test_selector_all('.x:has(~ .a + .b .c)', [d18, d19, d21, d24, d28, d32]);
test_selector_all('.x:has(.d .e)', [d48, d49, d50]);
test_selector_all('.x:has(.d .e) .f', [d54]);
test_selector_all('.x:has(> .d)', [d49, d50]);
test_selector_all('.x:has(> .d) .f', [d54]);
test_selector_all('.x:has(~ .d ~ .e)', [d48, d55, d56]);
test_selector_all('.x:has(~ .d ~ .e) ~ .f', [d60]);
test_selector_all('.x:has(+ .d ~ .e)', [d55, d56]);
test_selector_all('.x:has(+ .d ~ .e) ~ .f', [d60]);
test_selector_all('.y:has(> .g .h)', [d63, d71])
test_selector_all('.y:has(.g .h)', [d63, d68, d71])
test_selector_all('.y:has(> .g .h) .i', [d67, d75])
test_selector_all('.y:has(.g .h) .i', [d67, d75])
test_selector_all('.d .x:has(.e)', [d51, d52])
test_selector_all('.d ~ .x:has(~ .e)', [d57, d58])
</script>