Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!DOCTYPE html>
<title>moveBefore should handle focus bubbling correctly</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<section id="old_parent">
<button id="button" tabindex="1">Button</button>
</section>
<section id="new_parent">
</section>
<section id="inert_parent" inert>
</section>
<section id="inert_when_not_empty_parent">
</section>
<style>
#inert_when_not_empty_parent:has(button) {
display: none;
}
</style>
<script>
function assert_focus_within(expected) {
const element_to_string = e => e.id || e.nodeName;
assert_array_equals(
Array.from(document.querySelectorAll(":focus-within"), element_to_string),
expected.map(element_to_string));
}
test(t => {
const old_parent = document.querySelector("#old_parent");
const button = document.querySelector("#button");
t.add_cleanup(() => old_parent.append(button));
button.focus();
assert_focus_within([document.documentElement, document.body, old_parent, button]);
new_parent.moveBefore(button, null);
assert_focus_within([document.documentElement, document.body, new_parent, button]);
}, "focus-within should be updated when reparenting focused element directly");
test(t => {
const old_parent = document.querySelector("#old_parent");
const button = document.querySelector("#button");
t.add_cleanup(() => document.body.append(old_parent));
button.focus();
new_parent.moveBefore(old_parent, null);
assert_focus_within([document.documentElement, document.body, new_parent, old_parent, button]);
}, "focus-within should be updated when reparenting an element that has focus within");
test(t => {
const old_parent = document.querySelector("#old_parent");
const button = document.querySelector("#button");
t.add_cleanup(() => old_parent.append(button));
button.focus();
old_parent.moveBefore(button, null);
assert_focus_within([document.documentElement, document.body, old_parent, button]);
}, "focus-within should remain the same when moving to the same parent");
promise_test(async t => {
const old_parent = document.querySelector("#old_parent");
const inert_parent= document.querySelector("#inert_parent");
const button = document.querySelector("#button");
t.add_cleanup(() => old_parent.append(button));
button.focus();
inert_parent.moveBefore(button, null);
assert_focus_within([document.documentElement, document.body, inert_parent, button]);
await new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(() => resolve())));
assert_focus_within([]);
}, ":focus-within should be eventually up to date when moving to an inert subtree");
promise_test(async t => {
const old_parent = document.querySelector("#old_parent");
const inert_when_not_empty_parent = document.querySelector("#inert_when_not_empty_parent");
const button = document.querySelector("#button");
t.add_cleanup(() => old_parent.append(button));
button.focus();
inert_when_not_empty_parent.moveBefore(button, null);
assert_focus_within([document.documentElement, document.body, inert_when_not_empty_parent, button]);
await new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(() => resolve())));
assert_focus_within([]);
}, ":focus-within should be eventually up to date when moving to a subtree that would become inert via style");
</script>