Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

<!doctype html>
<title>Pointer Events boundary events in capturing tests</title>
<meta name="viewport" content="width=device-width">
<meta name="variant" content="?mouse">
<meta name="variant" content="?touch">
<meta name="variant" content="?pen">
<link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
<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 src="pointerevent_support.js"></script>
<h1>Pointer Events boundary events in capturing</h1>
<h2 id="pointerTypeDescription"></h2>
<h4 id="desc">
This automated test checks the boundary events of pointer events while the capturing
changes. This test cannot be run manually.
<div id="target0" class="touchActionNone"></div>
<div id="capturer">Do not hover over or touch this element.</div>
<div id="log"></div>
let input_source =;
let events_received = [];
let log_events = false;
// The events are handled as follows:
// - When "target0" receives a "pointerdown", the pointer is captured to "capturer" and event
// logging starts.
// - During event logging, all boundary events and "got/lostpointercapture" events to both
// "target0" and "capturer" are logged.
// - The first "pointermove" at "capturer" releases the pointer capture, so that subsequent
// "pointermove"/"pointerup" events go to "target0".
// - Event logging ends when "target0" receives a "pointerup".
function logEvent(event, element) {
if (log_events)
events_received.push(event.type + "@" +;
let target0 = document.getElementById("target0");
let capturer = document.getElementById("capturer");
target0.addEventListener("pointerdown", event => {
capturer.addEventListener("pointermove", event => {
if (capturer.hasPointerCapture(event.pointerId))
let other_event_types = [ "pointercancel",
"pointerover", "pointerout", "pointerenter", "pointerleave",
"gotpointercapture", "lostpointercapture" ];
other_event_types.forEach(event_name => {
[target0, capturer].forEach(target => {
target.addEventListener(event_name, event => logEvent(event, target));
promise_test(async () => {
// Start logging events after the pointerdown in the drag.
getEvent("pointerdown", target0).then(() => {
log_events = true;
let pointerup_promise = getEvent("pointerup", target0);
pointerup_promise.then(() => {
log_events = false;
await pointerDragInTarget(input_source, target0, "right");
// Wait for all events in the drag to have been dispatched.
await pointerup_promise;
const expected_events = [
"pointerout@target0", "pointerleave@target0",
"pointerover@capturer", "pointerenter@capturer",
"pointerout@capturer", "pointerleave@capturer",
"pointerover@target0", "pointerenter@target0"
assert_array_equals(events_received, expected_events);
}, "Boundary events around pointer capture and release");