fire-focusin-focusout.html (4447B)
1 <!DOCTYPE html> 2 <title>moveBefore should not fire focus events</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 collect_focusinout_events(t) { 24 const collected = []; 25 const listener = event => { collected.push(event); }; 26 document.addEventListener("focusin", listener); 27 document.addEventListener("focusout", listener); 28 t.add_cleanup(() => document.removeEventListener("focusin", listener)); 29 t.add_cleanup(() => document.removeEventListener("focusout", listener)); 30 return collected; 31 } 32 33 function assert_collected_events_equals(a, b) { 34 const eventToString = event => `${event.target.id || event.target.nodeName}.on${event.type}`; 35 return assert_array_equals(a.map(eventToString), b.map(eventToString)); 36 } 37 38 test(t => { 39 const collected_events = collect_focusinout_events(t); 40 const old_parent = document.querySelector("#old_parent"); 41 const button = document.querySelector("#button"); 42 t.add_cleanup(() => old_parent.append(button)); 43 button.focus(); 44 assert_collected_events_equals(collected_events, [ 45 {type: "focusin", target: button}, 46 ]); 47 assert_equals(document.activeElement, button); 48 new_parent.moveBefore(button, null); 49 assert_collected_events_equals(collected_events, [ 50 {type: "focusin", target: button}, 51 ]); 52 }, "Don't fire focusin/out when reparenting focused element directly"); 53 54 test(t => { 55 const collected_events = collect_focusinout_events(t); 56 const old_parent = document.querySelector("#old_parent"); 57 const button = document.querySelector("#button"); 58 t.add_cleanup(() => document.body.append(old_parent)); 59 button.focus(); 60 new_parent.moveBefore(old_parent, null); 61 assert_collected_events_equals(collected_events, [ 62 {type: "focusin", target: button}, 63 ]); 64 }, "Don't fire focusin/out when reparenting an element that has focus within"); 65 66 test(t => { 67 const collected_events = collect_focusinout_events(t); 68 const old_parent = document.querySelector("#old_parent"); 69 const button = document.querySelector("#button"); 70 t.add_cleanup(() => old_parent.append(button)); 71 button.focus(); 72 old_parent.moveBefore(button, null); 73 assert_collected_events_equals(collected_events, [ 74 {type: "focusin", target: button}, 75 ]); 76 }, "Don't fire focusin/out when moving to the same parent"); 77 78 promise_test(async t => { 79 const collected_events = collect_focusinout_events(t); 80 const old_parent = document.querySelector("#old_parent"); 81 const inert_parent= document.querySelector("#inert_parent"); 82 const button = document.querySelector("#button"); 83 t.add_cleanup(() => old_parent.append(button)); 84 button.focus(); 85 inert_parent.moveBefore(button, null); 86 assert_collected_events_equals(collected_events, [ 87 {type: "focusin", target: button}]); 88 await new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(() => resolve()))); 89 assert_collected_events_equals(collected_events, [ 90 {type: "focusin", target: button}, 91 {type: "focusout", target: button}, 92 ]); 93 }, "Don't fire focusin and then correct when moving to an inert subtree"); 94 95 promise_test(async t => { 96 const collected_events = collect_focusinout_events(t); 97 const old_parent = document.querySelector("#old_parent"); 98 const inert_when_not_empty_parent = document.querySelector("#inert_when_not_empty_parent"); 99 const button = document.querySelector("#button"); 100 t.add_cleanup(() => old_parent.append(button)); 101 button.focus(); 102 inert_when_not_empty_parent.moveBefore(button, null); 103 assert_collected_events_equals(collected_events, [ 104 {type: "focusin", target: button}, 105 ]); 106 await new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(() => resolve()))); 107 assert_collected_events_equals(collected_events, [ 108 {type: "focusin", target: button}, 109 {type: "focusout", target: button}, 110 ]); 111 }, "Don't fire focusin and then correct when moving to a tree that is made inert using style"); 112 113 </script>