-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bug 1901815 [wpt PR 46694] - WPT coverage for Pointer Events for slot…
…ted elements., a=testonly Automatic update from web-platform-tests WPT coverage for Pointer Events for slotted elements. This CL adds tests for two untested aspects of PointerEvents in slots: - PE event sequence around slots when the shadow DOM remains unchanged. - Boundary events after modifications to slotted elements. This covers the last remaining WPT for: w3c/pointerevents#477 Bug: 40156858 Change-Id: I9823595a0b15672d0395d4e117ccc6462c3e42f2 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5598510 Commit-Queue: Mustaq Ahmed <mustaq@chromium.org> Reviewed-by: Robert Flack <flackr@chromium.org> Cr-Commit-Position: refs/heads/main@{#1313570} -- wpt-commits: b8aab6837b61aacee4cbad1fbb6aeb3952af7b60 wpt-pr: 46694
- Loading branch information
1 parent
7bee123
commit 56ef0ea
Showing
2 changed files
with
282 additions
and
0 deletions.
There are no files selected for viewing
174 changes: 174 additions & 0 deletions
174
testing/web-platform/tests/pointerevents/pointerevent_after_target_removed_from_slot.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
<!DOCTYPE HTML> | ||
<link rel="help" href="https://w3c.github.io/pointerevents/#firing-events-using-the-pointerevent-interface"> | ||
<title>Enter/leave events fired to parent after child is removed from slot</title> | ||
<meta name="variant" content="?mouse"> | ||
<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> | ||
|
||
<template id="template"> | ||
<style> | ||
div { | ||
width: 100px; | ||
height: 100px; | ||
} | ||
</style> | ||
<div id="parent"> | ||
<slot>slot</slot> | ||
</div> | ||
</template> | ||
|
||
<style> | ||
div, my-elem { | ||
width: 100px; | ||
height: 100px; | ||
display: block; | ||
} | ||
</style> | ||
|
||
<my-elem id="host"> | ||
<div id="child">child</div> | ||
</my-elem> | ||
<div id="done">done</div> | ||
|
||
<script> | ||
"use strict"; | ||
|
||
customElements.define( | ||
"my-elem", | ||
class extends HTMLElement { | ||
constructor() { | ||
super(); | ||
let content = document.getElementById("template").content; | ||
const shadowRoot = this.attachShadow({ mode: "open" }); | ||
shadowRoot.appendChild(content.cloneNode(true)); | ||
} | ||
}, | ||
); | ||
|
||
const pointer_type = location.search.substring(1); | ||
|
||
const shadow_host = document.getElementById("host"); | ||
const parent = shadow_host.shadowRoot.getElementById("parent"); | ||
const slot = parent.firstElementChild; | ||
const slotted_child = document.getElementById("child"); | ||
const done = document.getElementById("done"); | ||
|
||
let event_log = []; | ||
let elem_to_remove; | ||
|
||
function logEvent(e) { | ||
if (e.eventPhase == e.AT_TARGET) { | ||
event_log.push(e.type + "@" + e.target.id); | ||
} | ||
} | ||
|
||
function removeChildFromSlot() { | ||
elem_to_remove.remove(); | ||
event_log.push("(child-removed)"); | ||
} | ||
|
||
function restoreChildInSlot() { | ||
if (!slotted_child.parentElement) { | ||
shadow_host.appendChild(slotted_child); | ||
} | ||
if (!slot.parentElement) { | ||
parent.appendChild(slot); | ||
} | ||
} | ||
|
||
function setup() { | ||
const events = ["pointerover", "pointerout", | ||
"pointerenter", "pointerleave", "pointerdown", "pointerup"]; | ||
let targets = [parent, slotted_child]; | ||
for (let i = 0; i < targets.length; i++) { | ||
events.forEach(event => targets[i].addEventListener(event, logEvent)); | ||
} | ||
} | ||
|
||
function addPromiseTest(remover_event, tested_elem_to_remove, | ||
expected_events) { | ||
assert_true(["slot", "slotted-child"].includes(tested_elem_to_remove), | ||
"Unexpcted tested_elem_to_remove param"); | ||
|
||
const test_name = `Pointer events from ${pointer_type} `+ | ||
`received before/after ${tested_elem_to_remove} removal `+ | ||
`at ${remover_event}`; | ||
|
||
promise_test(async test => { | ||
event_log = []; | ||
elem_to_remove = (tested_elem_to_remove == "slot" ? slot : slotted_child); | ||
|
||
restoreChildInSlot(); | ||
child.addEventListener(remover_event, removeChildFromSlot, | ||
{ once: true }); | ||
// TODO(mustaq@chromium.org): It would be more robust if we could remove | ||
// the event listener above through `test.add_cleanup()` but strangely the | ||
// cleanup call fails after the test that removes the slotted-child! This | ||
// happens even if we make the shadow DOM construction dynamic inside this | ||
// `promise_test`!!! | ||
|
||
let done_click_promise = getEvent("click", done); | ||
|
||
let actions = new test_driver.Actions() | ||
.addPointer("TestPointer", pointer_type) | ||
.pointerMove(-30, -30, {origin: shadow_host}) | ||
.pointerDown() | ||
.pointerUp() | ||
.pointerMove(30, 30, {origin: shadow_host}) | ||
.pointerDown() | ||
.pointerUp() | ||
.pointerMove(0, 0, {origin: done}) | ||
.pointerDown() | ||
.pointerUp(); | ||
|
||
await actions.send(); | ||
await done_click_promise; | ||
|
||
assert_equals(event_log.toString(), expected_events.toString(), | ||
"events received"); | ||
}, test_name); | ||
} | ||
|
||
setup(); | ||
|
||
addPromiseTest( | ||
"pointerdown", | ||
"slot", | ||
["pointerover@child", "pointerenter@parent", "pointerenter@child", | ||
"pointerdown@child", "(child-removed)", | ||
"pointerout@child", "pointerleave@child", | ||
"pointerover@parent", "pointerup@parent", | ||
"pointerdown@parent", "pointerup@parent", | ||
"pointerout@parent", "pointerleave@parent"] | ||
); | ||
addPromiseTest( | ||
"pointerdown", | ||
"slotted-child", | ||
["pointerover@child", "pointerenter@parent", "pointerenter@child", | ||
"pointerdown@child", "(child-removed)", | ||
"pointerover@parent", "pointerup@parent", | ||
"pointerdown@parent", "pointerup@parent", | ||
"pointerout@parent", "pointerleave@parent"] | ||
); | ||
addPromiseTest( | ||
"pointerup", | ||
"slot", | ||
["pointerover@child", "pointerenter@parent", "pointerenter@child", | ||
"pointerdown@child", "pointerup@child", "(child-removed)", | ||
"pointerout@child", "pointerleave@child", | ||
"pointerover@parent", "pointerdown@parent", "pointerup@parent", | ||
"pointerout@parent", "pointerleave@parent"] | ||
); | ||
addPromiseTest( | ||
"pointerup", | ||
"slotted-child", | ||
["pointerover@child", "pointerenter@parent", "pointerenter@child", | ||
"pointerdown@child", "pointerup@child", "(child-removed)", | ||
"pointerover@parent", "pointerdown@parent", "pointerup@parent", | ||
"pointerout@parent", "pointerleave@parent"] | ||
); | ||
</script> |
108 changes: 108 additions & 0 deletions
108
testing/web-platform/tests/pointerevents/pointerevent_to_slotted_target.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
<!DOCTYPE HTML> | ||
<link rel="help" href="https://w3c.github.io/pointerevents/#firing-events-using-the-pointerevent-interface"> | ||
<title>Enter/leave events fired to parent after child is removed from slot</title> | ||
<meta name="variant" content="?mouse"> | ||
<meta name="variant" content="?touch"> | ||
<meta name="variant" content="?pen"> | ||
<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> | ||
|
||
<template id="template"> | ||
<style> | ||
div { | ||
width: 100px; | ||
height: 100px; | ||
} | ||
</style> | ||
<div id="parent"> | ||
<slot id="slot">slot</slot> | ||
</div> | ||
</template> | ||
|
||
<style> | ||
div, my-elem { | ||
width: 100px; | ||
height: 100px; | ||
display: block; | ||
} | ||
</style> | ||
|
||
<my-elem id="host"> | ||
<div id="child">child</div> | ||
</my-elem> | ||
<div id="done">done</div> | ||
|
||
<script> | ||
"use strict"; | ||
|
||
customElements.define( | ||
"my-elem", | ||
class extends HTMLElement { | ||
constructor() { | ||
super(); | ||
let content = document.getElementById("template").content; | ||
const shadowRoot = this.attachShadow({ mode: "open" }); | ||
shadowRoot.appendChild(content.cloneNode(true)); | ||
} | ||
}, | ||
); | ||
|
||
const pointer_type = location.search.substring(1); | ||
|
||
const shadow_host = document.getElementById("host"); | ||
const parent = shadow_host.shadowRoot.getElementById("parent"); | ||
const slot = parent.firstElementChild; | ||
const slotted_child = document.getElementById("child"); | ||
const done = document.getElementById("done"); | ||
|
||
let event_log = []; | ||
|
||
function logEvent(e) { | ||
if (e.eventPhase == e.AT_TARGET) { | ||
event_log.push(e.type + "@" + e.target.id); | ||
} | ||
} | ||
|
||
function setup() { | ||
const events = ["pointerover", "pointerout", | ||
"pointerenter", "pointerleave", "pointerdown", "pointerup"]; | ||
let targets = [shadow_host, parent, slot, slotted_child]; | ||
for (let i = 0; i < targets.length; i++) { | ||
events.forEach(event => targets[i].addEventListener(event, logEvent)); | ||
} | ||
} | ||
|
||
setup(); | ||
|
||
promise_test(async test => { | ||
event_log = []; | ||
|
||
let done_click_promise = getEvent("click", done); | ||
|
||
let actions = new test_driver.Actions() | ||
.addPointer("TestPointer", pointer_type) | ||
.pointerMove(0, 0, {origin: shadow_host}) | ||
.pointerDown() | ||
.pointerUp() | ||
.pointerMove(0, 0, {origin: done}) | ||
.pointerDown() | ||
.pointerUp(); | ||
|
||
await actions.send(); | ||
await done_click_promise; | ||
|
||
const expected_events = [ | ||
"pointerover@child", | ||
"pointerenter@host", "pointerenter@parent", "pointerenter@slot", "pointerenter@child", | ||
"pointerdown@child", "pointerup@child", | ||
"pointerout@child", | ||
"pointerleave@child", "pointerleave@slot", "pointerleave@parent", "pointerleave@host" | ||
]; | ||
assert_equals(event_log.toString(), expected_events.toString(), | ||
"events received"); | ||
}, `Pointer events from ${pointer_type} to slotted element and shadow-host`); | ||
</script> |