blob: a395e22e5c0ef701b7ce401397500a267e55f282 [file] [log] [blame]
<!doctype html>
<meta charset=utf-8>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="../resources/testcommon.js"></script>
<style>
@keyframes animLeft {
to { left: 100px }
}
@keyframes animTop {
to { top: 100px }
}
@keyframes animBottom {
to { bottom: 100px }
}
@keyframes animRight {
to { right: 100px }
}
::before {
content: ''
}
::after {
content: ''
}
</style>
<body>
<div id="log"></div>
<script>
'use strict';
test(function(t) {
assert_equals(document.getAnimations().length, 0,
'getAnimations returns an empty sequence for a document'
+ ' with no animations');
}, 'getAnimations for non-animated content');
test(function(t) {
var div = addDiv(t);
// Add an animation
div.style.animation = 'animLeft 100s';
assert_equals(document.getAnimations().length, 1,
'getAnimations returns a running CSS Animation');
// Add another animation
div.style.animation = 'animLeft 100s, animTop 100s';
assert_equals(document.getAnimations().length, 2,
'getAnimations returns two running CSS Animations');
// Remove both
div.style.animation = '';
assert_equals(document.getAnimations().length, 0,
'getAnimations returns no running CSS Animations');
}, 'getAnimations for CSS Animations');
test(function(t) {
var div = addDiv(t);
div.style.animation = 'animLeft 100s, animTop 100s, animRight 100s, ' +
'animBottom 100s';
var animations = document.getAnimations();
assert_equals(animations.length, 4,
'getAnimations returns all running CSS Animations');
assert_equals(animations[0].animationName, 'animLeft',
'Order of first animation returned');
assert_equals(animations[1].animationName, 'animTop',
'Order of second animation returned');
assert_equals(animations[2].animationName, 'animRight',
'Order of third animation returned');
assert_equals(animations[3].animationName, 'animBottom',
'Order of fourth animation returned');
}, 'Order of CSS Animations - within an element');
test(function(t) {
var div1 = addDiv(t, { style: 'animation: animLeft 100s' });
var div2 = addDiv(t, { style: 'animation: animLeft 100s' });
var div3 = addDiv(t, { style: 'animation: animLeft 100s' });
var div4 = addDiv(t, { style: 'animation: animLeft 100s' });
var animations = document.getAnimations();
assert_equals(animations.length, 4,
'getAnimations returns all running CSS Animations');
assert_equals(animations[0].effect.target, div1,
'Order of first animation returned');
assert_equals(animations[1].effect.target, div2,
'Order of second animation returned');
assert_equals(animations[2].effect.target, div3,
'Order of third animation returned');
assert_equals(animations[3].effect.target, div4,
'Order of fourth animation returned');
// Order should be depth-first pre-order so add some depth as follows:
//
// <parent>
// / |
// 2 3
// / \
// 1 4
//
// Which should give: 2, 1, 4, 3
div2.appendChild(div1);
div2.appendChild(div4);
animations = document.getAnimations();
assert_equals(animations[0].effect.target, div2,
'Order of first animation returned after tree surgery');
assert_equals(animations[1].effect.target, div1,
'Order of second animation returned after tree surgery');
assert_equals(animations[2].effect.target, div4,
'Order of third animation returned after tree surgery');
assert_equals(animations[3].effect.target, div3,
'Order of fourth animation returned after tree surgery');
}, 'Order of CSS Animations - across elements');
test(function(t) {
var div1 = addDiv(t, { style: 'animation: animLeft 100s, animTop 100s' });
var div2 = addDiv(t, { style: 'animation: animBottom 100s' });
var expectedResults = [ [ div1, 'animLeft' ],
[ div1, 'animTop' ],
[ div2, 'animBottom' ] ];
var animations = document.getAnimations();
assert_equals(animations.length, expectedResults.length,
'getAnimations returns all running CSS Animations');
animations.forEach(function(anim, i) {
assert_equals(anim.effect.target, expectedResults[i][0],
'Target of animation in position ' + i);
assert_equals(anim.animationName, expectedResults[i][1],
'Name of animation in position ' + i);
});
// Modify tree structure and animation list
div2.appendChild(div1);
div1.style.animation = 'animLeft 100s, animRight 100s, animTop 100s';
expectedResults = [ [ div2, 'animBottom' ],
[ div1, 'animLeft' ],
[ div1, 'animRight' ],
[ div1, 'animTop' ] ];
animations = document.getAnimations();
assert_equals(animations.length, expectedResults.length,
'getAnimations returns all running CSS Animations after ' +
'making changes');
animations.forEach(function(anim, i) {
assert_equals(anim.effect.target, expectedResults[i][0],
'Target of animation in position ' + i + ' after changes');
assert_equals(anim.animationName, expectedResults[i][1],
'Name of animation in position ' + i + ' after changes');
});
}, 'Order of CSS Animations - across and within elements');
test(function(t) {
var div = addDiv(t, { style: 'animation: animLeft 100s, animTop 100s' });
var animLeft = document.getAnimations()[0];
assert_equals(animLeft.animationName, 'animLeft',
'Originally, animLeft animation comes first');
// Disassociate animLeft from markup and restart
div.style.animation = 'animTop 100s';
animLeft.play();
var animations = document.getAnimations();
assert_equals(animations.length, 2,
'getAnimations returns markup-bound and free animations');
assert_equals(animations[0].animationName, 'animTop',
'Markup-bound animations come first');
assert_equals(animations[1], animLeft, 'Free animations come last');
}, 'Order of CSS Animations - markup-bound vs free animations');
test(function(t) {
var div = addDiv(t, { style: 'animation: animLeft 100s, animTop 100s' });
var animLeft = document.getAnimations()[0];
var animTop = document.getAnimations()[1];
// Disassociate both animations from markup and restart in opposite order
div.style.animation = '';
animTop.play();
animLeft.play();
var animations = document.getAnimations();
assert_equals(animations.length, 2,
'getAnimations returns free animations');
assert_equals(animations[0], animTop,
'Free animations are returned in the order they are started');
assert_equals(animations[1], animLeft,
'Animations started later are returned later');
// Restarting an animation should have no effect
animTop.cancel();
animTop.play();
assert_equals(document.getAnimations()[0], animTop,
'After restarting, the ordering of free animations' +
' does not change');
}, 'Order of CSS Animations - free animations');
test(function(t) {
// Add an animation first
var div = addDiv(t, { style: 'animation: animLeft 100s' });
div.style.top = '0px';
div.style.transition = 'all 100s';
flushComputedStyle(div);
// *Then* add a transition
div.style.top = '100px';
flushComputedStyle(div);
// Although the transition was added later, it should come first in the list
var animations = document.getAnimations();
assert_equals(animations.length, 2,
'Both CSS animations and transitions are returned');
assert_class_string(animations[0], 'CSSTransition', 'Transition comes first');
assert_class_string(animations[1], 'CSSAnimation', 'Animation comes second');
}, 'Order of CSS Animations and CSS Transitions');
test(function(t) {
var div = addDiv(t, { style: 'animation: animLeft 100s forwards' });
div.getAnimations()[0].finish();
assert_equals(document.getAnimations().length, 1,
'Forwards-filling CSS animations are returned');
}, 'Finished but filling CSS Animations are returned');
test(function(t) {
var div = addDiv(t, { style: 'animation: animLeft 100s' });
div.getAnimations()[0].finish();
assert_equals(document.getAnimations().length, 0,
'Non-filling finished CSS animations are not returned');
}, 'Finished but not filling CSS Animations are not returned');
test(function(t) {
var div = addDiv(t, { style: 'animation: animLeft 100s 100s' });
assert_equals(document.getAnimations().length, 1,
'Yet-to-start CSS animations are returned');
}, 'Yet-to-start CSS Animations are returned');
test(function(t) {
var div = addDiv(t, { style: 'animation: animLeft 100s' });
div.getAnimations()[0].cancel();
assert_equals(document.getAnimations().length, 0,
'CSS animations cancelled by the API are not returned');
}, 'CSS Animations cancelled via the API are not returned');
test(function(t) {
var div = addDiv(t, { style: 'animation: animLeft 100s' });
var anim = div.getAnimations()[0];
anim.cancel();
anim.play();
assert_equals(document.getAnimations().length, 1,
'CSS animations cancelled and restarted by the API are ' +
'returned');
}, 'CSS Animations cancelled and restarted via the API are returned');
test(function(t) {
addStyle(t, { '#parent::after': 'animation: animLeft 10s;',
'#parent::before': 'animation: animRight 10s;' });
// create two divs with these arrangement:
// parent
// ::before,
// ::after
// |
// child
var parent = addDiv(t, { 'id': 'parent' });
var child = addDiv(t, { 'id': 'child' });
parent.appendChild(child);
[parent, child].forEach((div) => {
div.setAttribute('style', 'animation: animBottom 10s');
});
var anims = document.getAnimations();
assert_equals(anims.length, 4,
'CSS animations on both pseudo-elements and elements ' +
'are returned');
assert_equals(anims[0].effect.target, parent,
'The animation targeting the parent element comes first');
assert_equals(anims[1].animationName, 'animRight',
'The animation targeting the ::before element comes second');
assert_equals(anims[2].animationName, 'animLeft',
'The animation targeting the ::after element comes third');
assert_equals(anims[3].effect.target, child,
'The animation targeting the child element comes last');
}, 'CSS Animations targetting (pseudo-)elements should have correct order ' +
'after sorting');
</script>
</body>