pointerevent_after_target_removed_interleaved.tentative.html (4061B)
1 <!DOCTYPE HTML> 2 <!-- 3 Tentative due to: 4 https://github.com/w3c/pointerevents/issues/492 5 --> 6 <title> 7 Enter/leave events fired to parent after child is removed 8 right before compat mouse-event 9 </title> 10 <meta name="variant" content="?mouse"> 11 <meta name="variant" content="?touch"> 12 <meta name="variant" content="?pen"> 13 <script src="/resources/testharness.js"></script> 14 <script src="/resources/testharnessreport.js"></script> 15 <script src="/resources/testdriver.js"></script> 16 <script src="/resources/testdriver-actions.js"></script> 17 <script src="/resources/testdriver-vendor.js"></script> 18 <script src="pointerevent_support.js"></script> 19 20 <style> 21 div.target { 22 width: 100px; 23 height: 100px; 24 } 25 </style> 26 <div class="target" id="parent"> 27 <div class="target" id="child">child</div> 28 </div> 29 <div id="done">done</div> 30 31 <script> 32 'use strict'; 33 const pointer_type = location.search.substring(1); 34 35 const parent = document.getElementById("parent"); 36 const child = document.getElementById("child"); 37 const done = document.getElementById("done"); 38 39 let event_log = []; 40 let logged_event_prefix = ""; 41 let received_compat_mouse_events = false; 42 43 function logEvent(e) { 44 if (e.type.startsWith(logged_event_prefix) && e.eventPhase == e.AT_TARGET) { 45 event_log.push(e.type + "@" + e.target.id); 46 } 47 if (e.type.startsWith("mouse")) { 48 received_compat_mouse_events = true; 49 } 50 } 51 52 function removeChild() { 53 parent.removeChild(child); 54 event_log.push("(child-removed)"); 55 } 56 57 function setup() { 58 const logged_event_suffixes = 59 ["over", "out", "enter", "leave", "down", "up"]; 60 let targets = document.getElementsByClassName("target"); 61 for (let i = 0; i < targets.length; i++) { 62 logged_event_suffixes.forEach(suffix => { 63 targets[i].addEventListener("pointer" + suffix, logEvent); 64 targets[i].addEventListener("mouse" + suffix, logEvent); 65 }); 66 targets[i].addEventListener("click", logEvent); 67 } 68 } 69 70 function addPromiseTest(remover_event, tested_event_prefix, expected_events) { 71 const test_name = `${tested_event_prefix} events from ${pointer_type} `+ 72 `received before/after child removal at ${remover_event}`; 73 74 promise_test(async test => { 75 event_log = []; 76 logged_event_prefix = tested_event_prefix; 77 78 child.addEventListener(remover_event, removeChild); 79 test.add_cleanup(() => { 80 child.removeEventListener(remover_event, removeChild); 81 if (!child.parentElement) { 82 parent.appendChild(child); 83 } 84 }); 85 86 let done_click_promise = getEvent("click", done); 87 88 let actions = new test_driver.Actions() 89 .addPointer("TestPointer", pointer_type) 90 .pointerMove(-30, -30, {origin: parent}) 91 .pointerDown() 92 .pointerUp() 93 .pointerMove(30, 30, {origin: parent}) 94 .pointerDown() 95 .pointerUp() 96 .pointerMove(0, 0, {origin: done}) 97 .pointerDown() 98 .pointerUp(); 99 100 await actions.send(); 101 await done_click_promise; 102 103 if (tested_event_prefix == "mouse" && !received_compat_mouse_events) { 104 expected_events = []; 105 } 106 107 assert_equals(event_log.toString(), expected_events.toString(), 108 "events received"); 109 }, test_name); 110 } 111 112 setup(); 113 114 // Tests for dispatched compatibility mouse events 115 // after DOM modification through pointer events. 116 addPromiseTest("pointerdown", "mouse", [ 117 "mouseover@child", "mouseenter@parent", "mouseenter@child", 118 "(child-removed)", "mouseover@parent", "mousedown@parent", "mouseup@parent", "click@parent", 119 "mousedown@parent", "mouseup@parent", "click@parent", 120 "mouseout@parent", "mouseleave@parent" 121 ]); 122 addPromiseTest("pointerup", "mouse", [ 123 "mouseover@child", "mouseenter@parent", "mouseenter@child", 124 "mousedown@child", "(child-removed)", "mouseover@parent", "mouseup@parent", "click@parent", 125 "mousedown@parent", "mouseup@parent", "click@parent", 126 "mouseout@parent", "mouseleave@parent" 127 ]); 128 </script>