Skip to content

Commit

Permalink
Rewrite to re-enable pointerevent_attributes_nohover_pointers WPT
Browse files Browse the repository at this point in the history
The test was written using complicated event-driven logic, and had two
tests hooked up together.  This CL switches it to a simpler
Promise-based approach like newer tests in the same folder, expecting
to address the leak issue.

The CL also corrects an error message in testdriver-vendor.js that
misled our initial investigation.

Fixed: 1446799
Change-Id: If5cf1e9c0856a6beea4441a505fb320bf30344ca
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4794391
Commit-Queue: Kevin Ellis <[email protected]>
Reviewed-by: Kevin Ellis <[email protected]>
Auto-Submit: Mustaq Ahmed <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1186659}
  • Loading branch information
mustaqahmed authored and pull[bot] committed Aug 30, 2023
1 parent e2c77ae commit f52d1cd
Showing 1 changed file with 123 additions and 133 deletions.
256 changes: 123 additions & 133 deletions pointerevents/pointerevent_attributes_nohover_pointers.html
Original file line number Diff line number Diff line change
@@ -1,134 +1,124 @@
<!doctype html>
<html>
<head>
<title>Pointer Events properties 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>
var detected_pointertypes = {};
var detected_eventTypes = {};
var eventList = ['pointerover', 'pointerenter', 'pointerdown', 'pointerup', 'pointerout', 'pointerleave'];
// TODO([email protected]): missing touch pointermove coverage!
var expectedPointerId = NaN;

function resetTestState() {
detected_eventTypes = {};
document.getElementById("square1").style.visibility = 'visible';
document.getElementById('innerFrame').contentDocument.getElementById("square2").style.visibility = 'hidden';
}
function checkPointerEventAttributes(event, targetBoundingClientRect, testNamePrefix) {
if (detected_eventTypes[event.type])
return;
var expectedEventType = eventList[Object.keys(detected_eventTypes).length];
detected_eventTypes[event.type] = true;
var pointerTestName = (testNamePrefix ? testNamePrefix + ' ' : '')
+ expectedPointerType + ' ' + expectedEventType;

detected_pointertypes[event.pointerType] = true;

test(function() {
assert_equals(event.type, expectedEventType);
}, pointerTestName + ".type should be " + expectedEventType);

// Test button and buttons
test(function() {
assert_equals(event.button, 0);
}, pointerTestName + ".button attribute is 0 on touch-down.");

if (event.type == 'pointerdown' || event.type == 'pointerover' || event.type == 'pointerenter') {
test(function() {
assert_equals(event.buttons, 1);
}, pointerTestName + ".buttons attribute is 1 on touch-down.");
} else {
test(function() {
assert_equals(event.buttons, 0);
}, pointerTestName + ".buttons is 0 on touch-release.");
}

// Test clientX and clientY
test(function () {
assert_true(event.clientX >= targetBoundingClientRect.left && event.clientX < targetBoundingClientRect.right && event.clientY >= targetBoundingClientRect.top && event.clientY < targetBoundingClientRect.bottom);
}, pointerTestName + ".clientX and .clientY attributes are correct.");

check_PointerEvent(event, testNamePrefix);

// Test isPrimary
test(function () {
assert_equals(event.isPrimary, true);
}, pointerTestName + ".isPrimary attribute is true.");

// Test pointerId value
if (isNaN(expectedPointerId)) {
expectedPointerId = event.pointerId;
} else {
test(function () {
assert_equals(event.pointerId, expectedPointerId);
}, pointerTestName + ".pointerId should be the same as previous pointer events for this active pointer.");
}
}

async function run() {
var test_pointerEvent = setup_pointerevent_test("pointerevent attributes", ['touch']);
var square1 = document.getElementById("square1");
var rectSquare1 = square1.getBoundingClientRect();
var innerFrame = document.getElementById('innerFrame');
var square2 = innerFrame.contentDocument.getElementById('square2');
var rectSquare2 = square2.getBoundingClientRect();

eventList.forEach(function(eventName) {
on_event(square1, eventName, function (event) {
if (square1.style.visibility == 'hidden')
return;
checkPointerEventAttributes(event, rectSquare1, "");
if (Object.keys(detected_eventTypes).length == eventList.length) {
square1.style.visibility = 'hidden';
detected_eventTypes = {};
square2.style.visibility = 'visible';
expectedPointerId = NaN;
}
});
on_event(square2, eventName, function (event) {
checkPointerEventAttributes(event, rectSquare2, "Inner frame ");
if (Object.keys(detected_eventTypes).length == eventList.length) {
square2.style.visibility = 'hidden';
test_pointerEvent.done();
}
});
});

// Inject touch inputs.
await clickInTarget("touch", square1);
await clickInTarget("touch", square2);
}
</script>
</head>
<body onload="run()">
<h1>Pointer Events no-hover pointer attributes test</h1>
<h2 id="pointerTypeDescription"></h2>
<h4>
Test Description: This test checks the properties of pointer events that do not support hover.
<ol>
<li>Tap the black square.</li>
<li>Then move it off the black square so that it disappears.</li>
<li>When the red square appears tap on that as well.</li>
</ol>

Test passes if the proper behavior of the events is observed.
</h4>
<div id="square1" class="square"></div>
<iframe id="innerFrame" src="resources/pointerevent_attributes_hoverable_pointers-iframe.html"></iframe>
<div class="spacer"></div>
<div id="complete-notice">
<p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
<p>Refresh the page to run the tests again with a different pointer type.</p>
</div>
<div id="log"></div>
</body>
</html>
<title>Pointer Events no-hover pointer attributes test</title>
<meta name="variant" content="?touch">
<meta name="viewport" content="width=device-width">
<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 type="text/javascript" src="pointerevent_support.js"></script>
<style>
div {
height: 80px;
width: 80px;
}
</style>
<body onload="run()">
<div id="square1"></div>
<iframe id="innerFrame"
src="resources/pointerevent_attributes_hoverable_pointers-iframe.html">
</iframe>
<div id="done"></div>
</body>
<script>
'use strict';
const pointer_type = location.search.substring(1);
const test_pointer = pointer_type + "TestPointer";

const logged_events = [
"pointerover", "pointerenter", "pointerdown",
"pointerup", "pointerout", "pointerleave"
];

// TODO([email protected]): add pointermove coverage with touch-action:none.

function checkPointerEventAttributes(event,
expected_pointer_id, expected_event_type,
expected_bounding_rect) {
assert_equals(event.pointerType, pointer_type,
expected_event_type + ".pointerType should match test input");

assert_equals(event.pointerId, expected_pointer_id,
expected_event_type + ".pointerId should match all other events");
assert_equals(event.type, expected_event_type,
expected_event_type + ".type should be " + expected_event_type);

assert_equals(event.button, 0,
expected_event_type + ".button should be 0");

if (['pointerover', 'pointerenter', 'pointerdown'].includes(event.type)) {
assert_equals(event.buttons, 1,
expected_event_type + ".buttons should be 1");
} else {
assert_equals(event.buttons, 0,
expected_event_type + ".buttons should be 0");
}

assert_true(event.clientX >= expected_bounding_rect.left &&
event.clientX < expected_bounding_rect.right,
expected_event_type + ".clientX should be within bounding client rect.");

assert_true(event.clientY >= expected_bounding_rect.top &&
event.clientY < expected_bounding_rect.bottom,
expected_event_type + ".clientY should be within bounding client rect.");

check_PointerEvent(event, expected_event_type);

assert_equals(event.isPrimary, true,
expected_event_type + ".isPrimary is true.");
}

async function checkEventsOnTarget(test, elem) {
const done = document.getElementById("done");

let logged_event_promises = [];
for (let i = 0; i < logged_events.length; i++) {
logged_event_promises.push(getEvent(logged_events[i], elem, test));
}
let done_promise = getEvent("pointerup", done, test);

let actions = new test_driver.Actions();
actions = actions
.addPointer(test_pointer, pointer_type)
.pointerMove(0, 0, {origin:elem, sourceName:test_pointer})
.pointerDown({sourceName:test_pointer})
.pointerUp({sourceName:test_pointer})
.pointerMove(0, 0, {origin:done, sourceName:test_pointer})
.pointerDown({sourceName:test_pointer})
.pointerUp({sourceName:test_pointer});
await actions.send();

let done_event = await done_promise;

let expected_pointer_id;

// All Promises in logged_event_promises are already resolved bynow.
for (let i = 0; i < logged_event_promises.length; i++) {
let event = await logged_event_promises[i];
if (expected_pointer_id === undefined) {
expected_pointer_id = event.pointerId;
}
checkPointerEventAttributes(event, expected_pointer_id,
logged_events[i], elem.getBoundingClientRect());
}
}

function run() {
promise_test(async test => {
const target = document.getElementById("square1");
checkEventsOnTarget(test, target);
}, "PointerEvent attributes");

promise_test(async test => {
const target = frames[0].document.getElementById("square2");

// In Chromium, `test_driver.Actions()` sent to a subframe does not work
// even though the `onload` event here fires after a sqame-origin
// subframe is loaded. Waiting for 2 animation frames resolves this.
await waitForAnimationFrames(2);

checkEventsOnTarget(test, target);
}, "PointerEvent attributes in a subframe");
}
</script>

0 comments on commit f52d1cd

Please sign in to comment.