diff options
Diffstat (limited to 'testing/web-platform/tests/scroll-animations/scroll-timelines/cancel-animation.html')
-rw-r--r-- | testing/web-platform/tests/scroll-animations/scroll-timelines/cancel-animation.html | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/testing/web-platform/tests/scroll-animations/scroll-timelines/cancel-animation.html b/testing/web-platform/tests/scroll-animations/scroll-timelines/cancel-animation.html new file mode 100644 index 0000000000..7daf76a7a5 --- /dev/null +++ b/testing/web-platform/tests/scroll-animations/scroll-timelines/cancel-animation.html @@ -0,0 +1,214 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Canceling an animation</title> +<link rel="help" + href="https://drafts.csswg.org/web-animations/#canceling-an-animation-section"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/web-animations/testcommon.js"></script> +<script src="testcommon.js"></script> +<style> +.scroller { + overflow: auto; + height: 100px; + width: 100px; + will-change: transform; +} + +.contents { + height: 1000px; + width: 100%; +} +</style> +<body> +<script> +'use strict'; + +promise_test(async t => { + const animation = createScrollLinkedAnimation(t); + // Wait for new animation frame which allows the timeline to compute new + // current time. + await waitForNextFrame(); + animation.play(); + animation.cancel(); + + assert_equals(animation.startTime, null, + 'The start time of a canceled animation should be unresolved'); + assert_equals(animation.currentTime, null, + 'The hold time of a canceled animation should be unresolved'); +}, 'Canceling an animation should cause its start time and hold time to be' + + ' unresolved'); + +promise_test(async t => { + const animation = createScrollLinkedAnimation(t); + // Wait for new animation frame which allows the timeline to compute new + // current time. + await waitForNextFrame(); + animation.play(); + const retPromise = animation.ready.then(() => { + assert_unreached('ready promise was fulfilled'); + }).catch(err => { + assert_equals(err.name, 'AbortError', + 'ready promise is rejected with AbortError'); + }); + + animation.cancel(); + + return retPromise; +}, 'A play-pending ready promise should be rejected when the animation is' + + ' canceled'); + +promise_test(async t => { + const animation = createScrollLinkedAnimation(t); + // Wait for new animation frame which allows the timeline to compute new + // current time. + await waitForNextFrame(); + animation.play(); + await animation.ready; + + // Make it pause-pending + animation.pause(); + + // We need to store the original ready promise since cancel() will + // replace it + const originalPromise = animation.ready; + animation.cancel(); + + await promise_rejects_dom(t, 'AbortError', originalPromise, + 'Cancel should abort ready promise'); +}, 'A pause-pending ready promise should be rejected when the animation is' + + ' canceled'); + +promise_test(async t => { + const animation = createScrollLinkedAnimation(t); + // Wait for new animation frame which allows the timeline to compute new + // current time. + await waitForNextFrame(); + animation.play(); + animation.cancel(); + const promiseResult = await animation.ready; + assert_equals(promiseResult, animation); +}, 'When an animation is canceled, it should create a resolved Promise'); + +promise_test(async t => { + const animation = createScrollLinkedAnimation(t); + // Wait for new animation frame which allows the timeline to compute new + // current time. + await waitForNextFrame(); + animation.play(); + const promise = animation.ready; + animation.cancel(); + assert_not_equals(animation.ready, promise); + promise_rejects_dom(t, 'AbortError', promise, + 'Cancel should abort ready promise'); +}, 'The ready promise should be replaced when the animation is canceled'); + +promise_test(async t => { + const animation = createScrollLinkedAnimation(t); + // Wait for new animation frame which allows the timeline to compute new + // current time. + await waitForNextFrame(); + assert_equals(animation.playState, 'idle', + 'The animation should be initially idle'); + + animation.finished.then(t.step_func(() => { + assert_unreached('Finished promise should not resolve'); + }), t.step_func(() => { + assert_unreached('Finished promise should not reject'); + })); + + animation.cancel(); + + return waitForAnimationFrames(3); +}, 'The finished promise should NOT be rejected if the animation is already' + + ' idle'); + +promise_test(async t => { + const animation = createScrollLinkedAnimation(t); + // Wait for new animation frame which allows the timeline to compute new + // current time. + await waitForNextFrame(); + assert_equals(animation.playState, 'idle', + 'The animation should be initially idle'); + + animation.oncancel = t.step_func(() => { + assert_unreached('Cancel event should not be fired'); + }); + + animation.cancel(); + + return waitForAnimationFrames(3); +}, 'The cancel event should NOT be fired if the animation is already idle'); + +promise_test(async t => { + const animation = createScrollLinkedAnimation(t); + // Wait for new animation frame which allows the timeline to compute new + // current time. + await waitForNextFrame(); + animation.play(); + animation.effect.target.remove(); + + const eventWatcher = new EventWatcher(t, animation, 'cancel'); + + await animation.ready; + animation.cancel(); + + await eventWatcher.wait_for('cancel'); + + assert_equals(animation.effect.target.parentNode, null, + 'cancel event should be fired for the animation on an orphaned element'); +}, 'Canceling an animation should fire cancel event on orphaned element'); + +promise_test(async t => { + const animation = createScrollLinkedAnimation(t); + const scroller = animation.timeline.source; + + // Wait for new animation frame which allows the timeline to compute new + // current time. + await waitForNextFrame(); + animation.play(); + await animation.ready; + + // Make the scroll timeline inactive. + scroller.style.overflow = 'visible'; + scroller.scrollTop; + await waitForNextFrame(); + assert_equals(animation.timeline.currentTime, null, + 'Sanity check the timeline is inactive.'); + animation.cancel(); + assert_equals(animation.startTime, null, + 'The start time of a canceled animation should be unresolved'); + assert_equals(animation.currentTime, null, + 'The current time of a canceled animation should be unresolved'); +}, 'Canceling an animation with inactive timeline should cause its start time' + + ' and hold time to be unresolved'); + +promise_test(async t => { + const animation = createScrollLinkedAnimation(t); + const scroller = animation.timeline.source; + + // Wait for new animation frame which allows the timeline to compute new + // current time. + await waitForNextFrame(); + animation.play(); + await animation.ready; + + // Make the scroll timeline inactive. + scroller.style.overflow = 'visible'; + scroller.scrollTop; + await waitForNextFrame(); + assert_equals(animation.timeline.currentTime, null, + 'Sanity check the timeline is inactive.'); + + const eventWatcher = new EventWatcher(t, animation, 'cancel'); + animation.cancel(); + const cancelEvent = await eventWatcher.wait_for('cancel'); + + assert_equals(cancelEvent.currentTime, null, + 'event.currentTime should be unresolved when the timeline is inactive.'); + assert_equals(cancelEvent.timelineTime, null, + 'event.timelineTime should be unresolved when the timeline is inactive'); +}, 'oncancel event is fired when the timeline is inactive.'); + +</script> +</body> |