| <!doctype html> | |
| <meta charset=utf-8> | |
| <title> | |
| Element.getAnimations() - Dynamic changes to the list of CSS animations | |
| </title> | |
| <!-- TODO: Add a more specific link for this once it is specified. --> | |
| <link rel="help" href="https://drafts.csswg.org/css-animations-2/"> | |
| <script src="/resources/testharness.js"></script> | |
| <script src="/resources/testharnessreport.js"></script> | |
| <script src="support/testcommon.js"></script> | |
| <style> | |
| @keyframes anim1 { | |
| to { left: 100px } | |
| } | |
| @keyframes anim2 { } | |
| </style> | |
| <div id="log"></div> | |
| <script> | |
| 'use strict'; | |
| promise_test(async t => { | |
| const div = addDiv(t); | |
| div.style.animation = 'anim1 100s'; | |
| const originalAnimation = div.getAnimations()[0]; | |
| // Wait a moment so we can confirm the startTime doesn't change (and doesn't | |
| // simply reflect the current time). | |
| await originalAnimation.ready; | |
| const originalStartTime = originalAnimation.startTime; | |
| const originalCurrentTime = originalAnimation.currentTime; | |
| // Wait a moment so we can confirm the startTime doesn't change (and | |
| // doesn't simply reflect the current time). | |
| await waitForNextFrame(); | |
| div.style.animationDuration = '200s'; | |
| const animation = div.getAnimations()[0]; | |
| assert_equals(animation, originalAnimation, | |
| 'The same Animation is returned after updating' | |
| + ' animation duration'); | |
| assert_equals(animation.startTime, originalStartTime, | |
| 'Animations returned by getAnimations preserve' | |
| + ' their startTime even when they are updated'); | |
| // Sanity check | |
| assert_not_equals(animation.currentTime, originalCurrentTime, | |
| 'Animation.currentTime has updated in next' | |
| + ' requestAnimationFrame callback'); | |
| }, 'Animations preserve their startTime when changed'); | |
| test(t => { | |
| const div = addDiv(t); | |
| div.style.animation = 'anim1 100s, anim1 100s'; | |
| // Store original state | |
| let animations = div.getAnimations(); | |
| const animation1 = animations[0]; | |
| const animation2 = animations[1]; | |
| // Update first in list | |
| div.style.animationDuration = '200s, 100s'; | |
| animations = div.getAnimations(); | |
| assert_equals(animations[0], animation1, | |
| 'First Animation is in same position after update'); | |
| assert_equals(animations[1], animation2, | |
| 'Second Animation is in same position after update'); | |
| }, 'Updated Animations maintain their order in the list'); | |
| promise_test(async t => { | |
| const div = addDiv(t); | |
| div.style.animation = 'anim1 200s, anim1 100s'; | |
| // Store original state | |
| let animations = div.getAnimations(); | |
| const animation1 = animations[0]; | |
| const animation2 = animations[1]; | |
| // Wait before continuing so we can compare start times (otherwise the | |
| // new Animation objects and existing Animation objects will all have the same | |
| // start time). | |
| await waitForAllAnimations(animations); | |
| await waitForFrame(); | |
| // Swap duration of first and second in list and prepend animation at the | |
| // same time | |
| div.style.animation = 'anim1 100s, anim1 100s, anim1 200s'; | |
| animations = div.getAnimations(); | |
| assert_true(animations[0] !== animation1 && animations[0] !== animation2, | |
| 'New Animation is prepended to start of list'); | |
| assert_equals(animations[1], animation1, | |
| 'First animation is in second position after update'); | |
| assert_equals(animations[2], animation2, | |
| 'Second animation is in third position after update'); | |
| assert_equals(animations[1].startTime, animations[2].startTime, | |
| 'Old animations have the same start time'); | |
| assert_equals(animations[0].startTime, null, | |
| 'New animation has a null start time'); | |
| await animations[0].ready; | |
| assert_greater_than(animations[0].startTime, animations[1].startTime, | |
| 'New animation has later start time'); | |
| }, 'Only the startTimes of existing animations are preserved'); | |
| promise_test(async t => { | |
| const div = addDiv(t); | |
| div.style.animation = 'anim1 100s, anim1 100s'; | |
| const secondAnimation = div.getAnimations()[1]; | |
| // Wait before continuing so we can compare start times | |
| await secondAnimation.ready; | |
| await waitForNextFrame(); | |
| // Trim list of animations | |
| div.style.animationName = 'anim1'; | |
| const animations = div.getAnimations(); | |
| assert_equals(animations.length, 1, 'List of Animations was trimmed'); | |
| assert_equals(animations[0], secondAnimation, | |
| 'Remaining Animation is the second one in the list'); | |
| assert_equals(typeof(animations[0].startTime), 'number', | |
| 'Remaining Animation has resolved startTime'); | |
| assert_less_than(animations[0].startTime, | |
| animations[0].timeline.currentTime, | |
| 'Remaining Animation preserves startTime'); | |
| }, 'Animations are removed from the start of the list while preserving' | |
| + ' the state of existing Animations'); | |
| promise_test(async t => { | |
| const div = addDiv(t); | |
| div.style.animation = 'anim1 100s'; | |
| const firstAddedAnimation = div.getAnimations()[0]; | |
| // Wait and add second Animation | |
| await firstAddedAnimation.ready; | |
| await waitForFrame(); | |
| div.style.animation = 'anim1 100s, anim1 100s'; | |
| const secondAddedAnimation = div.getAnimations()[0]; | |
| // Wait again and add another Animation | |
| await secondAddedAnimation.ready; | |
| await waitForFrame(); | |
| div.style.animation = 'anim1 100s, anim2 100s, anim1 100s'; | |
| const animations = div.getAnimations(); | |
| assert_not_equals(firstAddedAnimation, secondAddedAnimation, | |
| 'New Animations are added to start of the list'); | |
| assert_equals(animations[0], secondAddedAnimation, | |
| 'Second Animation remains in same position after' | |
| + ' interleaving'); | |
| assert_equals(animations[2], firstAddedAnimation, | |
| 'First Animation remains in same position after' | |
| + ' interleaving'); | |
| await animations[1].ready; | |
| assert_greater_than(animations[1].startTime, animations[0].startTime, | |
| 'Interleaved animation starts later than existing ' + | |
| 'animations'); | |
| assert_greater_than(animations[0].startTime, animations[2].startTime, | |
| 'Original animations retain their start time'); | |
| }, 'Animation state is preserved when interleaving animations in list'); | |
| </script> |