diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /testing/web-platform/tests/css/css-animations/event-order.tentative.html | |
parent | Initial commit. (diff) | |
download | firefox-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.html | 259 |
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> |