-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
DOM: Test 'slotchange' event firing during move
See whatwg/dom#1307 (comment). [email protected] Bug: 40150299 Change-Id: I9529941e05591620da5b3c11635693a15f0ce866 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6111212 Reviewed-by: Noam Rosenthal <[email protected]> Commit-Queue: Dominic Farolino <[email protected]> Cr-Commit-Position: refs/heads/main@{#1399350}
- Loading branch information
1 parent
2331838
commit 45901e8
Showing
1 changed file
with
106 additions
and
0 deletions.
There are no files selected for viewing
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,106 @@ | ||
<!DOCTYPE html> | ||
<title>slotchanged event</title> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<body> | ||
|
||
<script> | ||
customElements.define( | ||
"custom-element", | ||
class extends HTMLElement { | ||
constructor() { | ||
super(); | ||
const shadowRoot = this.attachShadow({mode: "open"}); | ||
const slot = document.createElement('slot'); | ||
slot.name = 'content'; | ||
shadowRoot.append(slot); | ||
} | ||
}, | ||
); | ||
|
||
promise_test(async t => { | ||
const customElement = document.body.appendChild(document.createElement('custom-element')); | ||
t.add_cleanup(() => customElement.remove()); | ||
|
||
const slot = customElement.shadowRoot.children[0]; | ||
const slotChangePromise = new Promise((resolve, reject) => { | ||
slot.addEventListener('slotchange', e => resolve(), {once: true}); | ||
t.step_timeout(() => reject('Timeout; slotchange was not fired'), 1500); | ||
}); | ||
|
||
const defaultContentP = customElement.shadowRoot.appendChild(document.createElement('p')); | ||
slot.moveBefore(defaultContentP, null); | ||
await slotChangePromise; | ||
}, "Moving default content into a slot fires 'slotchange' event"); | ||
|
||
promise_test(async t => { | ||
const customElement = document.body.appendChild(document.createElement('custom-element')); | ||
t.add_cleanup(() => customElement.remove()); | ||
|
||
const slot = customElement.shadowRoot.children[0]; | ||
const defaultContentP = slot.appendChild(document.createElement('p')); | ||
|
||
// Wait for "signal a slot change" to asynchronously settle. This should fire | ||
// the 'slotchange' event for the insertion above, but we will not assert that, | ||
// since this test is only testing that 'slotchange' is fired on removal. We | ||
// separate this out in case an implementation fires one but not the other | ||
// (i.e., Chromium, at the time of writing this). | ||
await new Promise(resolve => t.step_timeout(() => resolve())); | ||
|
||
const slotChangePromise = new Promise((resolve, reject) => { | ||
slot.addEventListener('slotchange', e => resolve(), {once: true}); | ||
t.step_timeout(() => reject('Timeout; slotchange was not fired'), 1500); | ||
}); | ||
|
||
// Move `defaultContentP` OUT of the slot, and into the ShadowRoot. This | ||
// triggers "signal a slot change" on `defaultContentP`'s old parent, which is | ||
// the slot. | ||
customElement.shadowRoot.moveBefore(defaultContentP, null); | ||
await slotChangePromise; | ||
}, "Moving default content out of a slot fires 'slotchange' event"); | ||
|
||
promise_test(async t => { | ||
const customElement = document.body.appendChild(document.createElement('custom-element')); | ||
t.add_cleanup(() => customElement.remove()); | ||
|
||
const slot = customElement.shadowRoot.children[0]; | ||
const slottable = document.body.appendChild(document.createElement('p')); | ||
slottable.slot = 'content'; | ||
|
||
{ | ||
const slotChangePromise = new Promise((resolve, reject) => { | ||
slot.addEventListener('slotchange', e => { | ||
if (slot.assignedNodes().includes(slottable)) { | ||
resolve(); | ||
} else { | ||
reject('slot.assignedNodes() did not include the slottable after move'); | ||
} | ||
}, {once: true}); | ||
|
||
t.step_timeout(() => reject('Timeout; slotchange (whiling moving an element in) was not fired'), 1500); | ||
}); | ||
|
||
// Move the slottable INTO the custom element, thus slotting it. | ||
customElement.moveBefore(slottable, null); | ||
await slotChangePromise; | ||
} | ||
|
||
{ | ||
const slotChangePromise = new Promise((resolve, reject) => { | ||
slot.addEventListener('slotchange', e => { | ||
if (slot.assignedNodes().length === 0) { | ||
resolve(); | ||
} else { | ||
reject('slot.assignedNodes() not empty after the slottable moved out'); | ||
} | ||
}, {once: true}); | ||
|
||
t.step_timeout(() => reject('Timeout; slotchange (whiling moving an element out) was not fired'), 1500); | ||
}); | ||
|
||
// Move the slottable OUT of the custom element, thus unslotting it. | ||
document.body.moveBefore(slottable, null); | ||
await slotChangePromise; | ||
} | ||
}, "Moving a slottable into and out out of a custom element fires 'slotchange' event"); | ||
</script> |