focus-within.html (3469B)
1 <!DOCTYPE html> 2 <title>moveBefore should handle focus bubbling correctly</title> 3 <script src="/resources/testharness.js"></script> 4 <script src="/resources/testharnessreport.js"></script> 5 <body> 6 <section id="old_parent"> 7 <button id="button" tabindex="1">Button</button> 8 </section> 9 <section id="new_parent"> 10 </section> 11 <section id="inert_parent" inert> 12 </section> 13 <section id="inert_when_not_empty_parent"> 14 </section> 15 16 <style> 17 #inert_when_not_empty_parent:has(button) { 18 display: none; 19 } 20 </style> 21 22 <script> 23 function assert_focus_within(expected) { 24 const element_to_string = e => e.id || e.nodeName; 25 assert_array_equals( 26 Array.from(document.querySelectorAll(":focus-within"), element_to_string), 27 expected.map(element_to_string)); 28 } 29 30 test(t => { 31 const old_parent = document.querySelector("#old_parent"); 32 const button = document.querySelector("#button"); 33 t.add_cleanup(() => old_parent.append(button)); 34 button.focus(); 35 assert_focus_within([document.documentElement, document.body, old_parent, button]); 36 new_parent.moveBefore(button, null); 37 assert_focus_within([document.documentElement, document.body, new_parent, button]); 38 }, "focus-within should be updated when reparenting focused element directly"); 39 40 test(t => { 41 const old_parent = document.querySelector("#old_parent"); 42 const button = document.querySelector("#button"); 43 t.add_cleanup(() => document.body.append(old_parent)); 44 button.focus(); 45 new_parent.moveBefore(old_parent, null); 46 assert_focus_within([document.documentElement, document.body, new_parent, old_parent, button]); 47 }, "focus-within should be updated when reparenting an element that has focus within"); 48 49 test(t => { 50 const old_parent = document.querySelector("#old_parent"); 51 const button = document.querySelector("#button"); 52 t.add_cleanup(() => old_parent.append(button)); 53 button.focus(); 54 old_parent.moveBefore(button, null); 55 assert_focus_within([document.documentElement, document.body, old_parent, button]); 56 }, "focus-within should remain the same when moving to the same parent"); 57 58 promise_test(async t => { 59 const old_parent = document.querySelector("#old_parent"); 60 const inert_parent= document.querySelector("#inert_parent"); 61 const button = document.querySelector("#button"); 62 t.add_cleanup(() => old_parent.append(button)); 63 button.focus(); 64 inert_parent.moveBefore(button, null); 65 assert_focus_within([document.documentElement, document.body, inert_parent, button]); 66 await new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(() => resolve()))); 67 assert_focus_within([]); 68 }, ":focus-within should be eventually up to date when moving to an inert subtree"); 69 70 promise_test(async t => { 71 const old_parent = document.querySelector("#old_parent"); 72 const inert_when_not_empty_parent = document.querySelector("#inert_when_not_empty_parent"); 73 const button = document.querySelector("#button"); 74 t.add_cleanup(() => old_parent.append(button)); 75 button.focus(); 76 inert_when_not_empty_parent.moveBefore(button, null); 77 assert_focus_within([document.documentElement, document.body, inert_when_not_empty_parent, button]); 78 await new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(() => resolve()))); 79 assert_focus_within([]); 80 }, ":focus-within should be eventually up to date when moving to a subtree that would become inert via style"); 81 </script>