<!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>