| <!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'; | |
| const getMarginLeft = cs => parseFloat(cs.marginLeft); | |
| promise_test(async t => { | |
| const div = addDiv(t); | |
| const cs = getComputedStyle(div); | |
| div.style.animation = 'anim 1000s paused'; | |
| const animation = div.getAnimations()[0]; | |
| assert_equals(getMarginLeft(cs), 0, | |
| 'Initial value of margin-left is zero'); | |
| animation.play(); | |
| await animation.ready; | |
| await waitForNextFrame(); | |
| assert_greater_than(getMarginLeft(cs), 0, | |
| 'Playing value of margin-left is greater than zero'); | |
| }, 'play() overrides animation-play-state'); | |
| promise_test(async t => { | |
| const div = addDiv(t); | |
| const cs = getComputedStyle(div); | |
| div.style.animation = 'anim 1000s paused'; | |
| const animation = div.getAnimations()[0]; | |
| assert_equals(getMarginLeft(cs), 0, | |
| 'Initial value of margin-left is zero'); | |
| animation.pause(); | |
| div.style.animationPlayState = 'running'; | |
| await animation.ready; | |
| await waitForNextFrame(); | |
| assert_equals(cs.animationPlayState, 'running', | |
| 'animation-play-state is running'); | |
| assert_equals(getMarginLeft(cs), 0, | |
| 'Paused value of margin-left is zero'); | |
| }, 'pause() overrides animation-play-state'); | |
| promise_test(async t => { | |
| const div = addDiv(t); | |
| const cs = getComputedStyle(div); | |
| div.style.animation = 'anim 1000s paused'; | |
| const animation = div.getAnimations()[0]; | |
| assert_equals(getMarginLeft(cs), 0, | |
| 'Initial value of margin-left is zero'); | |
| animation.play(); | |
| await animation.ready; | |
| div.style.animationPlayState = 'running'; | |
| cs.animationPlayState; // Trigger style resolution | |
| await waitForNextFrame(); | |
| assert_equals(cs.animationPlayState, 'running', | |
| 'animation-play-state is running'); | |
| div.style.animationPlayState = 'paused'; | |
| await animation.ready; | |
| assert_equals(cs.animationPlayState, 'paused', | |
| 'animation-play-state is paused'); | |
| const previousAnimVal = getMarginLeft(cs); | |
| await waitForNextFrame(); | |
| assert_equals(getMarginLeft(cs), previousAnimVal, | |
| 'Animated value of margin-left does not change when' | |
| + ' paused by style'); | |
| }, 'play() is overridden by later setting "animation-play-state: paused"'); | |
| promise_test(async t => { | |
| const div = addDiv(t); | |
| const cs = getComputedStyle(div); | |
| div.style.animation = 'anim 1000s'; | |
| const animation = div.getAnimations()[0]; | |
| assert_equals(getMarginLeft(cs), 0, | |
| 'Initial value of margin-left is zero'); | |
| // Set the specified style first. If implementations fail to | |
| // apply the style changes first, they will ignore the redundant | |
| // call to play() and fail to correctly override the pause style. | |
| div.style.animationPlayState = 'paused'; | |
| animation.play(); | |
| const previousAnimVal = getMarginLeft(cs); | |
| await animation.ready; | |
| await waitForNextFrame(); | |
| assert_equals(cs.animationPlayState, 'paused', | |
| 'animation-play-state is paused'); | |
| assert_greater_than(getMarginLeft(cs), previousAnimVal, | |
| 'Playing value of margin-left is increasing'); | |
| }, 'play() flushes pending changes to animation-play-state first'); | |
| promise_test(async t => { | |
| const div = addDiv(t); | |
| const cs = getComputedStyle(div); | |
| div.style.animation = 'anim 1000s paused'; | |
| const animation = div.getAnimations()[0]; | |
| assert_equals(getMarginLeft(cs), 0, | |
| 'Initial value of margin-left is zero'); | |
| // Unlike the previous test for play(), since calling pause() is sticky, | |
| // we'll apply it even if the underlying style also says we're paused. | |
| // | |
| // We would like to test that implementations flush styles before running | |
| // pause() but actually there's no style we can currently set that will | |
| // change the behavior of pause(). That may change in the future | |
| // (e.g. if we introduce animation-timeline or animation-playback-rate etc.). | |
| // | |
| // For now this just serves as a sanity check that we do the same thing | |
| // even if we set style before calling the API. | |
| div.style.animationPlayState = 'running'; | |
| animation.pause(); | |
| const previousAnimVal = getMarginLeft(cs); | |
| await animation.ready; | |
| await waitForNextFrame(); | |
| assert_equals(cs.animationPlayState, 'running', | |
| 'animation-play-state is running'); | |
| assert_equals(getMarginLeft(cs), previousAnimVal, | |
| 'Paused value of margin-left does not change'); | |
| }, 'pause() applies pending changes to animation-play-state first'); | |
| // (Note that we can't actually test for this; see comment above, in test-body.) | |
| 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> |