Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test has a WPT meta file that expects 3 subtest issues.
- This WPT test may be referenced by the following Test IDs:
- /pointerevents/pointerevent_pointerrawupdate_remove_target.https.html - WPT Dashboard Interop Dashboard
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale:1">
<title>If a `pointerrawupdate` listener removes the target, `pointermove` should be fired its connected ancestor</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script>
"use strict";
/**
* `pointerrawupdate` is defined as:
* > The target of pointerrawupdate events might be different from the
* > pointermove events due to the fact that pointermove events might get
* > delayed or coalesced, and the final position of the event which is used
* > for finding the target could be different from its coalesced events.
*
* This checks whether `pointermove` is fired on the latest element underneath
* the pointer when the `pointerrawupdate` event listener removes its target.
*/
addEventListener("DOMContentLoaded", () => {
const testContainer = document.getElementById("testContainer");
let events = [];
function logEvent(event) {
if (event.eventPhase != Event.AT_TARGET) {
return;
}
events.push(`${event.type}@${event.target.id ? event.target.id : `<${event.target.nodeName}>`}`);
}
promise_test(async () => {
testContainer.innerHTML = "<div id=container><div id=init></div><div id=target></div></div>";
const initialDiv = document.getElementById("init");
await new test_driver.Actions()
.pointerMove(0, 0, {origin: initialDiv})
.send();
const target = document.getElementById("target");
for (const type of ["pointerrawupdate", "pointermove", "pointerover"]) {
target.addEventListener(type, logEvent);
}
const container = document.getElementById("container");
for (const type of ["pointerrawupdate", "pointermove", "pointerover"]) {
container.addEventListener(type, logEvent);
}
target.addEventListener("pointerrawupdate", () => {
target.remove();
}, {once: true});
events = [];
await new test_driver.Actions()
.pointerMove(0, 0, {origin: target})
.send();
assert_equals(
events.join(","),
[
"pointerover@target",
"pointerrawupdate@target",
"pointerover@container",
"pointermove@container",
].join(",")
);
}, `"pointermove" and its preceding boundary events should be fired on parent if "pointerrawupdate" event listener removes its target`);
promise_test(async () => {
testContainer.innerHTML =
"<div id=container><div id=container2><div id=init></div><div id=target></div></div></div>";
const initialDiv = document.getElementById("init");
await new test_driver.Actions()
.pointerMove(0, 0, {origin: initialDiv})
.send();
const target = document.getElementById("target");
for (const type of ["pointerrawupdate", "pointermove", "pointerover"]) {
target.addEventListener(type, logEvent);
}
const container = document.getElementById("container");
for (const type of ["pointerrawupdate", "pointermove", "pointerover"]) {
container.addEventListener(type, logEvent);
}
target.addEventListener("pointerrawupdate", () => {
target.parentNode.remove();
}, {once: true});
events = [];
await new test_driver.Actions()
.pointerMove(0, 0, {origin: target})
.send();
assert_equals(
events.join(","),
[
"pointerover@target",
"pointerrawupdate@target",
"pointerover@container",
"pointermove@container",
].join(",")
);
}, `"pointermove" and its preceding boundary events should be fired on ancestor if "pointerrawupdate" event listener removes its target parent`);
promise_test(async () => {
testContainer.innerHTML =
"<div id=container><div id=init></div><iframe srcdoc='<div id=target style=height:64px></div>'></iframe></div>";
const iframe = document.querySelector("iframe");
if (iframe.contentDocument.readyState != "complete") {
await new Promise(resolve => iframe.addEventListener("load", resolve, {once: true}));
}
const initialDiv = document.getElementById("init");
await new test_driver.Actions()
.pointerMove(0, 0, {origin: initialDiv})
.send();
const target = iframe.contentDocument.getElementById("target");
for (const type of ["pointerrawupdate", "pointermove", "pointerover"]) {
target.addEventListener(type, logEvent);
}
const container = document.getElementById("container");
for (const type of ["pointerrawupdate", "pointermove", "pointerover"]) {
container.addEventListener(type, logEvent);
}
target.addEventListener("pointerrawupdate", () => {
iframe.remove();
}, {once: true});
events = [];
await new test_driver.Actions()
.pointerMove(0, 0, {origin: target})
.send();
assert_equals(
events.join(", "),
[
"pointerover@target",
"pointerrawupdate@target",
"pointerover@container",
"pointermove@container",
].join(", ")
);
}, `"pointermove" and its preceding boundary events should be fired on parent if "pointerrawupdate" event listener removes its document`);
}, {once: true});
</script>
<style>
#container, #container2 {
min-height: 200px;
}
#target, #init {
width: 64px;
height: 64px;
}
</style>
<body><div id="testContainer"></div></body>
</html>