Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
- This WPT test may be referenced by the following Test IDs:
- /pointerevents/pointerevent_pointerId_scope.html - WPT Dashboard Interop Dashboard
<!doctype html>
<html>
<head>
<title>Pointer Events pointerdown tests</title>
<meta name="viewport" content="width=device-width">
<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>
<!-- Additional helper script for common checks across event types -->
<script type="text/javascript" src="pointerevent_support.js"></script>
<script>
"use strict"
function loadFrame() {
return new Promise(resolve => {
const innerframe = document.getElementById("innerframe");
innerframe.onload = resolve;
innerframe.src =
"resources/pointerevent_pointerId_scope-iframe.html";
});
}
const eventList = [
'pointerenter',
'pointerover',
'pointermove',
'pointerout',
'pointerleave'
];
function recordEvents(test) {
const target0 = document.getElementById("target0");
const innerframe = document.getElementById("innerframe");
let activePointerId = undefined;
let activePointerType = undefined;
const eventsReceived = {
'inner': {},
'outer': {},
};
// Records the last event of a given type in the case of multiple
// events.
const recordEvent = (event, context) => {
if (activePointerId === undefined) {
activePointerId = event.pointerId;
}
if (activePointerType == undefined) {
activePointerType= event.pointerType;
}
eventsReceived[context][event.type] = {
pointerId: event.pointerId,
pointerType: event.pointerType
};
}
const listener = (event) => {
recordEvent(event, 'outer');
};
eventList.forEach(eventType => {
target0.addEventListener(eventType, listener);
});
const messageListener = (event) => {
if (event.source != innerframe.contentWindow) {
return;
}
recordEvent(event.data, 'inner');
};
window.addEventListener('message', messageListener);
test.add_cleanup(() => {
eventList.forEach(eventType => {
target0.removeEventListener(eventType, listener);
});
window.removeEventListener('message', messageListener);
});
return new Promise(resolve => {
document.addEventListener('pointerup', () => {
// As pointer events for the inner frame are routed via a post
// message, the outer frame won't see the event until the following
// event processing loop. Allow 2 additional animation frames to
// ensure adequate time to receive the events.
waitForAnimationFrames(2).then(() => {
eventsReceived.activePointerId = activePointerId;
eventsReceived.activePointerType = activePointerType;
resolve(eventsReceived);
});
}, { once: true });
});
};
async function run() {
await loadFrame();
const target0 = document.getElementById("target0");
const innerframe = document.getElementById("innerframe");
const target1 =
innerframe.contentWindow.document.getElementsByTagName("div")[0];
promise_test(async t => {
const results = recordEvents(t);
// Move from the target in the outer-frame to a target in the inner-
// frame, click on second target, move back to the first and click.
// The inner target is not centered in the iframe, thus its position
// needs to be calculated.
const iframeRect = innerframe.getClientRects()[0];
const rect = target1.getClientRects()[0];
const center_x =
Math.round(iframeRect.left + (rect.left + rect.right) / 2);
const center_y =
Math.round(iframeRect.top + (rect.top + rect.bottom) / 2);
await new test_driver.Actions()
.pointerMove(0, 0, { origin: target0 })
.pointerMove(center_x, center_y)
.pointerDown()
.pointerUp()
.pointerMove(0, 0, { origin: target0 })
.pointerDown()
.pointerUp()
.send();
const events = await results;
assert_equals(
Object.keys(events.outer).length, eventList.length,
"Missing events for outer target");
assert_equals(
Object.keys(events.inner).length, eventList.length,
"Missing events for inner target");
const activePointerId = events.activePointerId;
const activePointerType = events.activePointerType;
eventList.forEach(eventName => {
assert_equals(
events.inner[eventName].pointerId, activePointerId,
`PointerId of ${eventName} in the inner frame is not correct`);
assert_equals(
events.outer[eventName].pointerId, activePointerId,
`PointerId of ${eventName} in the outer frame is not correct`);
assert_equals(
events.inner[eventName].pointerType, activePointerType,
`PointerType of ${eventName} in the inner frame is not correct`);
assert_equals(
events.outer[eventName].pointerType, activePointerType,
`PointerType of ${eventName} in the outer frame is not correct`);
});
}, 'pointerId of an active pointer is the same across same origin ' +
'frames');
}
</script>
</head>
<body onload="run()">
<h1>Pointer Events pointer ID tests</h1>
<div id="target0" class="touchActionNone"></div>
<!-- Document onload does not guarantee that child iframes have loaded.
Force synchronization by deferring setting the iframe's source
until a promise is set up to capture its load event. The root
document will load first, then the iframe. This ordering ensures
deterministic behavior.
-->
<iframe id="innerframe"></iframe>
</body>
</html>