summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/css/css-animations/event-order.tentative.html
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /testing/web-platform/tests/css/css-animations/event-order.tentative.html
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/css/css-animations/event-order.tentative.html')
-rw-r--r--testing/web-platform/tests/css/css-animations/event-order.tentative.html259
1 files changed, 259 insertions, 0 deletions
diff --git a/testing/web-platform/tests/css/css-animations/event-order.tentative.html b/testing/web-platform/tests/css/css-animations/event-order.tentative.html
new file mode 100644
index 0000000000..58f0bb67ca
--- /dev/null
+++ b/testing/web-platform/tests/css/css-animations/event-order.tentative.html
@@ -0,0 +1,259 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Tests for CSS animation event order</title>
+<link rel="help" href="https://drafts.csswg.org/css-animations-2/#event-dispatch"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/testcommon.js"></script>
+<style>
+@keyframes anim {
+ from { margin-left: 0px; }
+ to { margin-left: 100px; }
+}
+@keyframes color-anim {
+ from { color: red; }
+ to { color: green; }
+}
+</style>
+<div id="log"></div>
+<script type='text/javascript'>
+'use strict';
+
+/**
+ * Asserts that the set of actual and received events match.
+ * @param actualEvents An array of the received AnimationEvent objects.
+ * @param expectedEvents A series of array objects representing the expected
+ * events, each having the form:
+ * [ event type, target element, [pseudo type], elapsed time ]
+ */
+const checkEvents = (actualEvents, ...expectedEvents) => {
+ const actualTypeSummary = actualEvents.map(event => event.type).join(', ');
+ const expectedTypeSummary = expectedEvents.map(event => event[0]).join(', ');
+
+ assert_equals(
+ actualEvents.length,
+ expectedEvents.length,
+ `Number of events received (${actualEvents.length}) \
+should match expected number (${expectedEvents.length}) \
+(expected: ${expectedTypeSummary}, actual: ${actualTypeSummary})`
+ );
+
+ for (const [index, actualEvent] of actualEvents.entries()) {
+ const expectedEvent = expectedEvents[index];
+ const [type, target] = expectedEvent;
+ const pseudoElement = expectedEvent.length === 4 ? expectedEvent[2] : '';
+ const elapsedTime = expectedEvent[expectedEvent.length - 1];
+
+ assert_equals(
+ actualEvent.type,
+ type,
+ `Event #${index + 1} types should match \
+(expected: ${expectedTypeSummary}, actual: ${actualTypeSummary})`
+ );
+ assert_equals(
+ actualEvent.target,
+ target,
+ `Event #${index + 1} targets should match`
+ );
+ assert_equals(
+ actualEvent.pseudoElement,
+ pseudoElement,
+ `Event #${index + 1} pseudoElements should match`
+ );
+ assert_equals(
+ actualEvent.elapsedTime,
+ elapsedTime,
+ `Event #${index + 1} elapsedTimes should match`
+ );
+ }
+};
+
+const setupAnimation = (t, animationStyle, receiveEvents) => {
+ const div = addDiv(t, { style: 'animation: ' + animationStyle });
+
+ for (const name of ['start', 'iteration', 'end']) {
+ div['onanimation' + name] = evt => {
+ receiveEvents.push({
+ type: evt.type,
+ target: evt.target,
+ pseudoElement: evt.pseudoElement,
+ elapsedTime: evt.elapsedTime,
+ });
+ };
+ }
+
+ const watcher = new EventWatcher(t, div, [
+ 'animationstart',
+ 'animationiteration',
+ 'animationend',
+ ]);
+
+ const animation = div.getAnimations()[0];
+
+ return [animation, watcher, div];
+};
+
+promise_test(async t => {
+ let events = [];
+ const [animation1, watcher1, div1] =
+ setupAnimation(t, 'anim 100s 2 paused', events);
+ const [animation2, watcher2, div2] =
+ setupAnimation(t, 'anim 100s 2 paused', events);
+
+ await Promise.all([ watcher1.wait_for('animationstart'),
+ watcher2.wait_for('animationstart') ]);
+
+ checkEvents(events, ['animationstart', div1, 0],
+ ['animationstart', div2, 0]);
+
+ events.length = 0; // Clear received event array
+
+ animation1.currentTime = 100 * MS_PER_SEC;
+ animation2.currentTime = 100 * MS_PER_SEC;
+
+ await Promise.all([ watcher1.wait_for('animationiteration'),
+ watcher2.wait_for('animationiteration') ]);
+
+ checkEvents(events, ['animationiteration', div1, 100],
+ ['animationiteration', div2, 100]);
+
+ events.length = 0; // Clear received event array
+
+ animation1.finish();
+ animation2.finish();
+
+ await Promise.all([ watcher1.wait_for('animationend'),
+ watcher2.wait_for('animationend') ]);
+
+ checkEvents(events, ['animationend', div1, 200],
+ ['animationend', div2, 200]);
+}, 'Same events are ordered by elements');
+
+function pseudoTest(description, testMarkerPseudos) {
+ promise_test(async t => {
+ // Setup a hierarchy as follows:
+ //
+ // parent
+ // |
+ // (::marker, ::before, ::after) // ::marker optional
+ // |
+ // child
+ const parentDiv = addDiv(t, { style: 'animation: anim 100s' });
+
+ parentDiv.id = 'parent-div';
+ addStyle(t, {
+ '#parent-div::after': "content: ''; animation: anim 100s",
+ '#parent-div::before': "content: ''; animation: anim 100s",
+ });
+
+ if (testMarkerPseudos) {
+ parentDiv.style.display = 'list-item';
+ addStyle(t, {
+ '#parent-div::marker': "content: ''; animation: color-anim 100s",
+ });
+ }
+
+ const childDiv = addDiv(t, { style: 'animation: anim 100s' });
+ parentDiv.append(childDiv);
+
+ // Setup event handlers
+ let events = [];
+ for (const name of ['start', 'iteration', 'end', 'cancel']) {
+ parentDiv['onanimation' + name] = evt => {
+ events.push({
+ type: evt.type,
+ target: evt.target,
+ pseudoElement: evt.pseudoElement,
+ elapsedTime: evt.elapsedTime,
+ });
+ };
+ }
+
+ // Wait a couple of frames for the events to be dispatched
+ await waitForFrame();
+ await waitForFrame();
+
+ const expectedEvents = [
+ ['animationstart', parentDiv, 0],
+ ['animationstart', parentDiv, '::marker', 0],
+ ['animationstart', parentDiv, '::before', 0],
+ ['animationstart', parentDiv, '::after', 0],
+ ['animationstart', childDiv, 0],
+ ];
+ if (!testMarkerPseudos) {
+ expectedEvents.splice(1, 1);
+ }
+
+ checkEvents(events, ...expectedEvents);
+ }, description);
+}
+
+pseudoTest('Same events on pseudo-elements follow the prescribed order', false);
+pseudoTest('Same events on pseudo-elements follow the prescribed order ' +
+ '(::marker)', true);
+
+promise_test(async t => {
+ let events = [];
+ const [animation1, watcher1, div1] =
+ setupAnimation(t, 'anim 200s 400s', events);
+ const [animation2, watcher2, div2] =
+ setupAnimation(t, 'anim 300s 2', events);
+
+ await watcher2.wait_for('animationstart');
+
+ animation1.currentTime = 400 * MS_PER_SEC;
+ animation2.currentTime = 400 * MS_PER_SEC;
+
+ events.length = 0; // Clear received event array
+
+ await Promise.all([ watcher1.wait_for('animationstart'),
+ watcher2.wait_for('animationiteration') ]);
+
+ checkEvents(events, ['animationiteration', div2, 300],
+ ['animationstart', div1, 0]);
+}, 'Start and iteration events are ordered by time');
+
+promise_test(async t => {
+ let events = [];
+ const [animation1, watcher1, div1] =
+ setupAnimation(t, 'anim 150s', events);
+ const [animation2, watcher2, div2] =
+ setupAnimation(t, 'anim 100s 2', events);
+
+ await Promise.all([ watcher1.wait_for('animationstart'),
+ watcher2.wait_for('animationstart') ]);
+
+ animation1.currentTime = 150 * MS_PER_SEC;
+ animation2.currentTime = 150 * MS_PER_SEC;
+
+ events.length = 0; // Clear received event array
+
+ await Promise.all([ watcher1.wait_for('animationend'),
+ watcher2.wait_for('animationiteration') ]);
+
+ checkEvents(events, ['animationiteration', div2, 100],
+ ['animationend', div1, 150]);
+}, 'Iteration and end events are ordered by time');
+
+promise_test(async t => {
+ let events = [];
+ const [animation1, watcher1, div1] =
+ setupAnimation(t, 'anim 100s 100s', events);
+ const [animation2, watcher2, div2] =
+ setupAnimation(t, 'anim 100s 2', events);
+
+ animation1.finish();
+ animation2.finish();
+
+ await Promise.all([ watcher1.wait_for([ 'animationstart',
+ 'animationend' ]),
+ watcher2.wait_for([ 'animationstart',
+ 'animationend' ]) ]);
+
+ checkEvents(events, ['animationstart', div2, 0],
+ ['animationstart', div1, 0],
+ ['animationend', div1, 100],
+ ['animationend', div2, 200]);
+}, 'Start and end events are sorted correctly when fired simultaneously');
+
+</script>