| <!doctype html> | |
| <meta charset=utf-8> | |
| <title>Pausing a CSSAnimation</title> | |
| <link rel="help" | |
| href="https://drafts.csswg.org/css-animations-2/#animation-play-state"> | |
| <script src="/resources/testharness.js"></script> | |
| <script src="/resources/testharnessreport.js"></script> | |
| <script src="support/testcommon.js"></script> | |
| <style> | |
| @keyframes anim { | |
| 0% { margin-left: 0px } | |
| 100% { margin-left: 10000px } | |
| } | |
| </style> | |
| <div id="log"></div> | |
| <script> | |
| 'use strict'; | |
| promise_test(async t => { | |
| const div = addDiv(t); | |
| div.style.animation = 'anim 1000s paused'; | |
| const animation = div.getAnimations()[0]; | |
| animation.play(); | |
| await animation.ready; | |
| await waitForNextFrame(); | |
| assert_equals( | |
| animation.playState, | |
| 'running', | |
| 'Play state is running after calling play()' | |
| ); | |
| // Flip the animation-play-state back and forth to check it has no effect | |
| div.style.animationPlayState = 'running'; | |
| getComputedStyle(div).animationPlayState; | |
| div.style.animationPlayState = 'paused'; | |
| getComputedStyle(div).animationPlayState; | |
| assert_equals( | |
| animation.playState, | |
| 'running', | |
| 'Should still be running even after flipping the animation-play-state' | |
| ); | |
| }, 'play() overrides animation-play-state'); | |
| promise_test(async t => { | |
| const div = addDiv(t); | |
| div.style.animation = 'anim 100s infinite paused'; | |
| const animation = div.getAnimations()[0]; | |
| animation.playbackRate = -1; | |
| animation.currentTime = -1; | |
| assert_throws_dom('InvalidStateError', () => { | |
| animation.play(); | |
| }, 'Trying to play a reversed infinite animation should throw'); | |
| assert_equals( | |
| animation.playState, | |
| 'paused', | |
| 'Animation should still be paused' | |
| ); | |
| animation.playbackRate = 1; | |
| div.style.animationPlayState = 'running'; | |
| assert_equals( | |
| animation.playState, | |
| 'running', | |
| 'Changing the animation-play-state should play the animation' | |
| ); | |
| }, 'play() does NOT override the animation-play-state if there was an error'); | |
| promise_test(async t => { | |
| const div = addDiv(t); | |
| div.style.animation = 'anim 1000s paused'; | |
| const animation = div.getAnimations()[0]; | |
| animation.pause(); | |
| div.style.animationPlayState = 'running'; | |
| getComputedStyle(div).animationPlayState; | |
| await animation.ready; | |
| await waitForNextFrame(); | |
| assert_equals(animation.playState, 'paused', 'playState is paused '); | |
| // Flip the animation-play-state back and forth to check it has no effect | |
| div.style.animationPlayState = 'paused'; | |
| getComputedStyle(div).animationPlayState; | |
| div.style.animationPlayState = 'running'; | |
| getComputedStyle(div).animationPlayState; | |
| assert_equals( | |
| animation.playState, | |
| 'paused', | |
| 'Should still be paused even after flipping the animation-play-state' | |
| ); | |
| }, 'pause() overrides animation-play-state'); | |
| promise_test(async t => { | |
| const div = addDiv(t); | |
| div.style.animation = 'anim 100s paused'; | |
| const animation = div.getAnimations()[0]; | |
| animation.reverse(); | |
| assert_equals( | |
| animation.playState, | |
| 'running', | |
| 'Play state is running after calling reverse()' | |
| ); | |
| // Flip the animation-play-state back and forth to check it has no effect | |
| div.style.animationPlayState = 'running'; | |
| getComputedStyle(div).animationPlayState; | |
| div.style.animationPlayState = 'paused'; | |
| getComputedStyle(div).animationPlayState; | |
| assert_equals( | |
| animation.playState, | |
| 'running', | |
| 'Should still be running even after flipping the animation-play-state' | |
| ); | |
| }, 'reverse() overrides animation-play-state when it starts playing the' | |
| + ' animation'); | |
| promise_test(async t => { | |
| const div = addDiv(t); | |
| div.style.animation = 'anim 100s'; | |
| const animation = div.getAnimations()[0]; | |
| animation.reverse(); | |
| assert_equals( | |
| animation.playState, | |
| 'running', | |
| 'Play state is running after calling reverse()' | |
| ); | |
| div.style.animationPlayState = 'paused'; | |
| getComputedStyle(div).animationPlayState; | |
| assert_equals( | |
| animation.playState, | |
| 'paused', | |
| 'Should be paused after changing the animation-play-state' | |
| ); | |
| }, 'reverse() does NOT override animation-play-state if the animation is' | |
| + ' already running'); | |
| promise_test(async t => { | |
| const div = addDiv(t); | |
| div.style.animation = 'anim 100s'; | |
| const animation = div.getAnimations()[0]; | |
| animation.startTime = null; | |
| assert_equals( | |
| animation.playState, | |
| 'paused', | |
| 'Play state is paused after setting the start time to null' | |
| ); | |
| // Flip the animation-play-state back and forth to check it has no effect | |
| div.style.animationPlayState = 'paused'; | |
| getComputedStyle(div).animationPlayState; | |
| div.style.animationPlayState = 'running'; | |
| getComputedStyle(div).animationPlayState; | |
| assert_equals( | |
| animation.playState, | |
| 'paused', | |
| 'Should still be paused even after flipping the animation-play-state' | |
| ); | |
| }, 'Setting the startTime to null overrides animation-play-state if the' | |
| + ' animation is already running'); | |
| promise_test(async t => { | |
| const div = addDiv(t); | |
| div.style.animation = 'anim 100s paused'; | |
| const animation = div.getAnimations()[0]; | |
| animation.startTime = document.timeline.currentTime; | |
| assert_equals( | |
| animation.playState, | |
| 'running', | |
| 'Play state is running after setting the start time to non-null' | |
| ); | |
| // Flip the animation-play-state back and forth to check it has no effect | |
| div.style.animationPlayState = 'running'; | |
| getComputedStyle(div).animationPlayState; | |
| div.style.animationPlayState = 'paused'; | |
| getComputedStyle(div).animationPlayState; | |
| assert_equals( | |
| animation.playState, | |
| 'running', | |
| 'Should still be running even after flipping the animation-play-state' | |
| ); | |
| }, 'Setting the startTime to non-null overrides animation-play-state if the' | |
| + ' animation is paused'); | |
| promise_test(async t => { | |
| const div = addDiv(t); | |
| div.style.animation = 'anim 100s'; | |
| const animation = div.getAnimations()[0]; | |
| animation.startTime = document.timeline.currentTime; | |
| div.style.animationPlayState = 'paused'; | |
| getComputedStyle(div).animationPlayState; | |
| assert_equals( | |
| animation.playState, | |
| 'paused', | |
| 'Should be paused after changing the animation-play-state' | |
| ); | |
| }, 'Setting the startTime to non-null does NOT override the' | |
| + ' animation-play-state if the animation is already running'); | |
| promise_test(async t => { | |
| const div = addDiv(t, { style: 'animation: anim 1000s' }); | |
| const animation = div.getAnimations()[0]; | |
| let readyPromiseRun = false; | |
| await animation.ready; | |
| div.style.animationPlayState = 'paused'; | |
| assert_true(animation.pending && animation.playState === 'paused', | |
| 'Animation is pause-pending'); | |
| // Set current time | |
| animation.currentTime = 5 * MS_PER_SEC; | |
| assert_equals(animation.playState, 'paused', | |
| 'Animation is paused immediately after setting currentTime'); | |
| assert_equals(animation.startTime, null, | |
| 'Animation startTime is unresolved immediately after ' + | |
| 'setting currentTime'); | |
| assert_equals(animation.currentTime, 5 * MS_PER_SEC, | |
| 'Animation currentTime does not change when forcing a ' + | |
| 'pause operation to complete'); | |
| // The ready promise should now be resolved. If it's not then test will | |
| // probably time out before anything else happens that causes it to resolve. | |
| await animation.ready; | |
| }, 'Setting the current time completes a pending pause'); | |
| </script> |