pointerevent_pointerrawupdate_remove_target.https.html (5546B)
1 <!doctype html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <meta name="viewport" content="width=device-width, initial-scale:1"> 6 <title>If a `pointerrawupdate` listener removes the target, `pointermove` should be fired its connected ancestor</title> 7 <script src="/resources/testharness.js"></script> 8 <script src="/resources/testharnessreport.js"></script> 9 <script src="/resources/testdriver.js"></script> 10 <script src="/resources/testdriver-actions.js"></script> 11 <script src="/resources/testdriver-vendor.js"></script> 12 <script> 13 "use strict"; 14 15 /** 16 * `pointerrawupdate` is defined as: 17 * > The target of pointerrawupdate events might be different from the 18 * > pointermove events due to the fact that pointermove events might get 19 * > delayed or coalesced, and the final position of the event which is used 20 * > for finding the target could be different from its coalesced events. 21 * 22 * This checks whether `pointermove` is fired on the latest element underneath 23 * the pointer when the `pointerrawupdate` event listener removes its target. 24 */ 25 26 addEventListener("DOMContentLoaded", () => { 27 const testContainer = document.getElementById("testContainer"); 28 let events = []; 29 function logEvent(event) { 30 if (event.eventPhase != Event.AT_TARGET) { 31 return; 32 } 33 events.push(`${event.type}@${event.target.id ? event.target.id : `<${event.target.nodeName}>`}`); 34 } 35 promise_test(async () => { 36 testContainer.innerHTML = "<div id=container><div id=init></div><div id=target></div></div>"; 37 const initialDiv = document.getElementById("init"); 38 await new test_driver.Actions() 39 .pointerMove(0, 0, {origin: initialDiv}) 40 .send(); 41 const target = document.getElementById("target"); 42 for (const type of ["pointerrawupdate", "pointermove", "pointerover"]) { 43 target.addEventListener(type, logEvent); 44 } 45 const container = document.getElementById("container"); 46 for (const type of ["pointerrawupdate", "pointermove", "pointerover"]) { 47 container.addEventListener(type, logEvent); 48 } 49 target.addEventListener("pointerrawupdate", () => { 50 target.remove(); 51 }, {once: true}); 52 events = []; 53 await new test_driver.Actions() 54 .pointerMove(0, 0, {origin: target}) 55 .send(); 56 assert_equals( 57 events.join(","), 58 [ 59 "pointerover@target", 60 "pointerrawupdate@target", 61 "pointerover@container", 62 "pointermove@container", 63 ].join(",") 64 ); 65 }, `"pointermove" and its preceding boundary events should be fired on parent if "pointerrawupdate" event listener removes its target`); 66 67 promise_test(async () => { 68 testContainer.innerHTML = 69 "<div id=container><div id=container2><div id=init></div><div id=target></div></div></div>"; 70 const initialDiv = document.getElementById("init"); 71 await new test_driver.Actions() 72 .pointerMove(0, 0, {origin: initialDiv}) 73 .send(); 74 const target = document.getElementById("target"); 75 for (const type of ["pointerrawupdate", "pointermove", "pointerover"]) { 76 target.addEventListener(type, logEvent); 77 } 78 const container = document.getElementById("container"); 79 for (const type of ["pointerrawupdate", "pointermove", "pointerover"]) { 80 container.addEventListener(type, logEvent); 81 } 82 target.addEventListener("pointerrawupdate", () => { 83 target.parentNode.remove(); 84 }, {once: true}); 85 events = []; 86 await new test_driver.Actions() 87 .pointerMove(0, 0, {origin: target}) 88 .send(); 89 assert_equals( 90 events.join(","), 91 [ 92 "pointerover@target", 93 "pointerrawupdate@target", 94 "pointerover@container", 95 "pointermove@container", 96 ].join(",") 97 ); 98 }, `"pointermove" and its preceding boundary events should be fired on ancestor if "pointerrawupdate" event listener removes its target parent`); 99 100 promise_test(async () => { 101 testContainer.innerHTML = 102 "<div id=container><div id=init></div><iframe srcdoc='<div id=target style=height:64px></div>'></iframe></div>"; 103 const iframe = document.querySelector("iframe"); 104 if (iframe.contentDocument.readyState != "complete") { 105 await new Promise(resolve => iframe.addEventListener("load", resolve, {once: true})); 106 } 107 const initialDiv = document.getElementById("init"); 108 await new test_driver.Actions() 109 .pointerMove(0, 0, {origin: initialDiv}) 110 .send(); 111 const target = iframe.contentDocument.getElementById("target"); 112 for (const type of ["pointerrawupdate", "pointermove", "pointerover"]) { 113 target.addEventListener(type, logEvent); 114 } 115 const container = document.getElementById("container"); 116 for (const type of ["pointerrawupdate", "pointermove", "pointerover"]) { 117 container.addEventListener(type, logEvent); 118 } 119 target.addEventListener("pointerrawupdate", () => { 120 iframe.remove(); 121 }, {once: true}); 122 events = []; 123 await new test_driver.Actions() 124 .pointerMove(0, 0, {origin: target}) 125 .send(); 126 assert_equals( 127 events.join(", "), 128 [ 129 "pointerover@target", 130 "pointerrawupdate@target", 131 "pointerover@container", 132 "pointermove@container", 133 ].join(", ") 134 ); 135 }, `"pointermove" and its preceding boundary events should be fired on parent if "pointerrawupdate" event listener removes its document`); 136 }, {once: true}); 137 </script> 138 <style> 139 #container, #container2 { 140 min-height: 200px; 141 } 142 #target, #init { 143 width: 64px; 144 height: 64px; 145 } 146 147 </style> 148 <body><div id="testContainer"></div></body> 149 </html>