Bug 1145246, part 2 - Update Web Animations code and tests for the rename of Animatable.getAnimationPlayers() to Animatable.getAnimations(). r=birtles

This commit is contained in:
Jonathan Watt 2015-03-20 18:20:37 +00:00
parent 49b12af674
commit 598dd090ea
21 changed files with 800 additions and 792 deletions

View File

@ -321,8 +321,8 @@ protected:
// Indicates whether we were in the finished state during our
// most recent unthrottled sample (our last ComposeStyle call).
bool mIsPreviousStateFinished; // Spec calls this "previous finished state"
// Indicates that the player should be exposed in an element's
// getAnimationPlayers() list.
// Indicates that the animation should be exposed in an element's
// getAnimations() list.
bool mIsRelevant;
};

View File

@ -141,7 +141,7 @@ function assert_record_list(actual, expected, desc, index, listName) {
}
for (var i = 0; i < actual.length; i++) {
ok(actual.indexOf(expected[i]) != -1,
`${desc} - record[${index}].${listName} contains expected AnimationPlayer`);
`${desc} - record[${index}].${listName} contains expected Animation`);
}
}
@ -181,27 +181,27 @@ function assert_records(expected, desc) {
// Register for the end of the transition.
var transitionEnd = await_event(e, "transitionend");
// The transition should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after transition start");
// The transition should cause the creation of a single Animation.
var animations = e.getAnimations();
is(animations.length, 1, "getAnimations().length after transition start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// Wait for the single MutationRecord for the Animation addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
assert_records([{ added: animations, changed: [], removed: [] }],
"records after transition start");
// Advance until near the end of the transition, then wait for it to finish.
players[0].currentTime = 99900;
animations[0].currentTime = 99900;
yield transitionEnd;
// After the transition has finished, the AnimationPlayer should disappear.
is(e.getAnimationPlayers().length, 0, "getAnimationPlayers().length after transition end");
// After the transition has finished, the Animation should disappear.
is(e.getAnimations().length, 0, "getAnimations().length after transition end");
// Wait for the single MutationRecord for the AnimationPlayer removal to
// Wait for the single MutationRecord for the Animation removal to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
assert_records([{ added: [], changed: [], removed: animations }],
"records after transition end");
e.style = "";
@ -214,23 +214,23 @@ function assert_records(expected, desc) {
// Start a long transition.
e.style = "transition: background-color 100s; background-color: lime;";
// The transition should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after transition start");
// The transition should cause the creation of a single Animation.
var animations = e.getAnimations();
is(animations.length, 1, "getAnimations().length after transition start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// Wait for the single MutationRecord for the Animation addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
assert_records([{ added: animations, changed: [], removed: [] }],
"records after transition start");
// Cancel the transition by setting transition-property.
e.style.transitionProperty = "none";
// Wait for the single MutationRecord for the AnimationPlayer removal to
// Wait for the single MutationRecord for the Animation removal to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
assert_records([{ added: [], changed: [], removed: animations }],
"records after transition end");
e.style = "";
@ -243,14 +243,14 @@ function assert_records(expected, desc) {
// Start a long transition with a predictable value.
e.style = "transition: background-color 100s steps(2, end) -51s; background-color: lime;";
// The transition should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after transition start");
// The transition should cause the creation of a single Animation.
var animations = e.getAnimations();
is(animations.length, 1, "getAnimations().length after transition start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// Wait for the single MutationRecord for the Animation addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
assert_records([{ added: animations, changed: [], removed: [] }],
"records after transition start");
// Cancel the transition by setting the current animation value.
@ -258,10 +258,10 @@ function assert_records(expected, desc) {
is(getComputedStyle(e).backgroundColor, value, "half-way transition value");
e.style.backgroundColor = value;
// Wait for the single MutationRecord for the AnimationPlayer removal to
// Wait for the single MutationRecord for the Animation removal to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
assert_records([{ added: [], changed: [], removed: animations }],
"records after transition end");
e.style = "";
@ -274,23 +274,23 @@ function assert_records(expected, desc) {
// Start a long transition.
e.style = "transition: line-height 100s; line-height: 100px;";
// The transition should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after transition start");
// The transition should cause the creation of a single Animation.
var animations = e.getAnimations();
is(animations.length, 1, "getAnimations().length after transition start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// Wait for the single MutationRecord for the Animation addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
assert_records([{ added: animations, changed: [], removed: [] }],
"records after transition start");
// Cancel the transition by setting line-height to a non-interpolable value.
e.style.lineHeight = "normal";
// Wait for the single MutationRecord for the AnimationPlayer removal to
// Wait for the single MutationRecord for the Animation removal to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
assert_records([{ added: [], changed: [], removed: animations }],
"records after transition end");
e.style = "";
@ -303,50 +303,50 @@ function assert_records(expected, desc) {
// Start a long transition.
e.style = "transition: background-color 100s step-start; background-color: lime;";
// The transition should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after transition start");
// The transition should cause the creation of a single Animation.
var animations = e.getAnimations();
is(animations.length, 1, "getAnimations().length after transition start");
var firstPlayer = players[0];
var firstAnimation = animations[0];
// Wait for the single MutationRecord for the AnimationPlayer addition to
// Wait for the single MutationRecord for the Animation addition to
// be delivered.
yield await_frame();
assert_records([{ added: [firstPlayer], changed: [], removed: [] }],
assert_records([{ added: [firstAnimation], changed: [], removed: [] }],
"records after transition start");
// Wait for the AnimationPlayer to get going, then seek well into
// Wait for the Animation to get going, then seek well into
// the transition.
yield await_frame();
firstPlayer.currentTime = 50000;
firstAnimation.currentTime = 50000;
// Reverse the transition by setting the background-color back to its
// original value.
e.style.backgroundColor = "yellow";
// The reversal should cause the creation of a new AnimationPlayer.
players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after transition reversal");
// The reversal should cause the creation of a new Animation.
animations = e.getAnimations();
is(animations.length, 1, "getAnimations().length after transition reversal");
var secondPlayer = players[0];
var secondAnimation = animations[0];
ok(firstPlayer != secondPlayer,
"second AnimationPlayer should be different from the first");
ok(firstAnimation != secondAnimation,
"second Animation should be different from the first");
// Wait for the single MutationRecord for the removal of the original
// AnimationPlayer and the addition of the new AnimationPlayer to
// be delivered.
// Animation and the addition of the new Animation to be delivered.
yield await_frame();
assert_records([{ added: [secondPlayer], changed: [], removed: [firstPlayer] }],
assert_records([{ added: [secondAnimation], changed: [],
removed: [firstAnimation] }],
"records after transition reversal");
// Cancel the transition.
e.style.transitionProperty = "none";
// Wait for the single MutationRecord for the AnimationPlayer removal to
// Wait for the single MutationRecord for the Animation removal to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: [secondPlayer] }],
assert_records([{ added: [], changed: [], removed: [secondAnimation] }],
"records after transition end");
e.style = "";
@ -360,45 +360,45 @@ function assert_records(expected, desc) {
"transition-property: color, background-color, line-height; " +
"color: blue; background-color: lime; line-height: 24px;";
// The transitions should cause the creation of three AnimationPlayers.
var players = e.getAnimationPlayers();
is(players.length, 3, "getAnimationPlayers().length after transition starts");
// The transitions should cause the creation of three Animations.
var animations = e.getAnimations();
is(animations.length, 3, "getAnimations().length after transition starts");
// Wait for the single MutationRecord for the AnimationPlayer additions to
// Wait for the single MutationRecord for the Animation additions to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
assert_records([{ added: animations, changed: [], removed: [] }],
"records after transition starts");
// Wait for the AnimationPlayers to get going, then seek well into
// Wait for the Animations to get going, then seek well into
// the transitions.
yield await_frame();
players.forEach(p => p.currentTime = 50000);
animations.forEach(p => p.currentTime = 50000);
is(players.filter(p => p.playState == "running").length, 3, "number of running AnimationPlayers");
is(animations.filter(p => p.playState == "running").length, 3, "number of running Animations");
// Cancel one of the transitions by setting transition-property.
e.style.transitionProperty = "background-color, line-height";
var colorPlayer = players.filter(p => p.playState != "running");
var otherPlayers = players.filter(p => p.playState == "running");
var colorAnimation = animations.filter(p => p.playState != "running");
var otherAnimations = animations.filter(p => p.playState == "running");
is(colorPlayer.length, 1, "number of non-running AnimationPlayers after cancelling one");
is(otherPlayers.length, 2, "number of running AnimationPlayers after cancelling one");
is(colorAnimation.length, 1, "number of non-running Animations after cancelling one");
is(otherAnimations.length, 2, "number of running Animations after cancelling one");
// Wait for a MutationRecord for one of the AnimationPlayer
// Wait for a MutationRecord for one of the Animation
// removals to be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: colorPlayer }],
assert_records([{ added: [], changed: [], removed: colorAnimation }],
"records after color transition end");
// Cancel the remaining transitions.
e.style.transitionProperty = "none";
// Wait for the MutationRecord for the other two AnimationPlayer
// Wait for the MutationRecord for the other two Animation
// removals to be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: otherPlayers }],
assert_records([{ added: [], changed: [], removed: otherAnimations }],
"records after other transition ends");
e.style = "";
@ -413,27 +413,27 @@ function assert_records(expected, desc) {
// Register for the end of the animation.
var animationEnd = await_event(e, "animationend");
// The animation should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after animation start");
// The animation should cause the creation of a single Animation.
var animations = e.getAnimations();
is(animations.length, 1, "getAnimations().length after animation start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// Wait for the single MutationRecord for the Animation addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
assert_records([{ added: animations, changed: [], removed: [] }],
"records after animation start");
// Advance until near the end of the animation, then wait for it to finish.
players[0].currentTime = 99900;
animations[0].currentTime = 99900;
yield animationEnd;
// After the animation has finished, the AnimationPlayer should disappear.
is(e.getAnimationPlayers().length, 0, "getAnimationPlayers().length after animation end");
// After the animation has finished, the Animation should disappear.
is(e.getAnimations().length, 0, "getAnimations().length after animation end");
// Wait for the single MutationRecord for the AnimationPlayer removal to
// Wait for the single MutationRecord for the Animation removal to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
assert_records([{ added: [], changed: [], removed: animations }],
"records after animation end");
e.style = "";
@ -446,23 +446,23 @@ function assert_records(expected, desc) {
// Start a long animation.
e.style = "animation: anim 100s;";
// The animation should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after animation start");
// The animation should cause the creation of a single Animation.
var animations = e.getAnimations();
is(animations.length, 1, "getAnimations().length after animation start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// Wait for the single MutationRecord for the Animation addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
assert_records([{ added: animations, changed: [], removed: [] }],
"records after animation start");
// Cancel the animation by setting animation-name.
e.style.animationName = "none";
// Wait for the single MutationRecord for the AnimationPlayer removal to
// Wait for the single MutationRecord for the Animation removal to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
assert_records([{ added: [], changed: [], removed: animations }],
"records after animation end");
e.style = "";
@ -475,27 +475,27 @@ function assert_records(expected, desc) {
// Start a long animation.
e.style = "animation: anim 100s;";
// The animation should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after animation start");
// The animation should cause the creation of a single Animation.
var animations = e.getAnimations();
is(animations.length, 1, "getAnimations().length after animation start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// Wait for the single MutationRecord for the Animation addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
assert_records([{ added: animations, changed: [], removed: [] }],
"records after animation start");
// Advance the animation by a second.
players[0].currentTime += 1000;
animations[0].currentTime += 1000;
// Cancel the animation by setting animation-duration to a value less
// than a second.
e.style.animationDuration = "0.1s";
// Wait for the single MutationRecord for the AnimationPlayer removal to
// Wait for the single MutationRecord for the Animation removal to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
assert_records([{ added: [], changed: [], removed: animations }],
"records after animation end");
e.style = "";
@ -508,23 +508,23 @@ function assert_records(expected, desc) {
// Start a long animation.
e.style = "animation: anim 100s;";
// The animation should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after animation start");
// The animation should cause the creation of a single Animation.
var animations = e.getAnimations();
is(animations.length, 1, "getAnimations().length after animation start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// Wait for the single MutationRecord for the Animation addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
assert_records([{ added: animations, changed: [], removed: [] }],
"records after animation start");
// Cancel the animation by setting animation-delay.
e.style.animationDelay = "-200s";
// Wait for the single MutationRecord for the AnimationPlayer removal to
// Wait for the single MutationRecord for the Animation removal to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
assert_records([{ added: [], changed: [], removed: animations }],
"records after animation end");
e.style = "";
@ -540,18 +540,18 @@ function assert_records(expected, desc) {
// Register for the end of the animation.
var animationEnd = await_event(e, "animationend");
// The animation should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after animation start");
// The animation should cause the creation of a single Animation.
var animations = e.getAnimations();
is(animations.length, 1, "getAnimations().length after animation start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// Wait for the single MutationRecord for the Animation addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
assert_records([{ added: animations, changed: [], removed: [] }],
"records after animation start");
// Advance until near the end of the animation, then wait for it to finish.
players[0].currentTime = 99900;
animations[0].currentTime = 99900;
yield animationEnd;
// No changes to the list of animations at this point.
@ -560,10 +560,10 @@ function assert_records(expected, desc) {
// Cancel the animation by setting animation-fill-mode.
e.style.animationFillMode = "none";
// Wait for the single MutationRecord for the AnimationPlayer removal to
// Wait for the single MutationRecord for the Animation removal to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
assert_records([{ added: [], changed: [], removed: animations }],
"records after animation end");
e.style = "";
@ -576,18 +576,18 @@ function assert_records(expected, desc) {
// Start a short, repeated animation.
e.style = "animation: anim 0.5s infinite;";
// The animation should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after animation start");
// The animation should cause the creation of a single Animation.
var animations = e.getAnimations();
is(animations.length, 1, "getAnimations().length after animation start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// Wait for the single MutationRecord for the Animation addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
assert_records([{ added: animations, changed: [], removed: [] }],
"records after animation start");
// Advance the animation until we are past the first iteration.
players[0].currentTime += 1000;
animations[0].currentTime += 1000;
// No changes to the list of animations at this point.
assert_records([], "records after animation starts repeating");
@ -595,10 +595,10 @@ function assert_records(expected, desc) {
// Cancel the animation by setting animation-iteration-count.
e.style.animationIterationCount = "1";
// Wait for the single MutationRecord for the AnimationPlayer removal to
// Wait for the single MutationRecord for the Animation removal to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
assert_records([{ added: [], changed: [], removed: animations }],
"records after animation end");
e.style = "";
@ -618,23 +618,23 @@ function assert_records(expected, desc) {
// Start a long animation.
e.style = "animation: anim 100s;";
// The animation should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after animation start");
// The animation should cause the creation of a single Animation.
var animations = e.getAnimations();
is(animations.length, 1, "getAnimations().length after animation start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// Wait for the single MutationRecord for the Animation addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
assert_records([{ added: animations, changed: [], removed: [] }],
"records after animation start");
// Change a property of the animation such that it keeps running.
e.style[aChangeTest.prop] = aChangeTest.val;
// Wait for the single MutationRecord for the AnimationPlayer change to
// Wait for the single MutationRecord for the Animation change to
// be delivered.
yield await_frame();
assert_records([{ added: [], changed: players, removed: [] }],
assert_records([{ added: [], changed: animations, removed: [] }],
"records after animation change");
// Cancel the animation.
@ -642,7 +642,7 @@ function assert_records(expected, desc) {
// Wait for the addition, change and removal MutationRecords to be delivered.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
assert_records([{ added: [], changed: [], removed: animations }],
"records after animation end");
e.style = "";
@ -655,14 +655,14 @@ function assert_records(expected, desc) {
// Start a long animation.
e.style = "animation: anim 100s;";
// The animation should cause the creation of a single AnimationPlayer.
var players = e.getAnimationPlayers();
is(players.length, 1, "getAnimationPlayers().length after animation start");
// The animation should cause the creation of a single Animation.
var animations = e.getAnimations();
is(animations.length, 1, "getAnimations().length after animation start");
// Wait for the single MutationRecord for the AnimationPlayer addition to
// Wait for the single MutationRecord for the Animation addition to
// be delivered.
yield await_frame();
assert_records([{ added: players, changed: [], removed: [] }],
assert_records([{ added: animations, changed: [], removed: [] }],
"records after animation start");
// Update the animation's delay such that it is still running.
@ -673,7 +673,7 @@ function assert_records(expected, desc) {
// We should get a single removal notification.
yield await_frame();
assert_records([{ added: [], changed: [], removed: players }],
assert_records([{ added: [], changed: [], removed: animations }],
"records after animation end");
e.style = "";
@ -685,9 +685,9 @@ function assert_records(expected, desc) {
// Start an animation that should already be finished.
e.style = "animation: anim 1s -2s;";
// The animation should cause no AnimationPlayers to be created.
var players = e.getAnimationPlayers();
is(players.length, 0, "getAnimationPlayers().length after animation start");
// The animation should cause no Animations to be created.
var animations = e.getAnimations();
is(animations.length, 0, "getAnimations().length after animation start");
// And we should get no notifications.
yield await_frame();

View File

@ -42,21 +42,21 @@ var omtaEnabled = SpecialPowers.DOMWindowUtils.layerManagerRemote &&
// FIXME: When we implement Element.animate, use that here instead of CSS
// so that we remove any dependency on the CSS mapping.
div.style.animation = 'anim 100s';
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
player.ready.then(function() {
is(player.isRunningOnCompositor, omtaEnabled,
'AnimationPlayer reports that it is running on the compositor'
animation.ready.then(function() {
is(animation.isRunningOnCompositor, omtaEnabled,
'Animation reports that it is running on the compositor'
+ ' during playback');
div.style.animationPlayState = 'paused';
window.getComputedStyle(div).animationPlayState;
// FIXME: When we implement deferred pausing (bug 1109390), we should wait
// on player.ready here.
// on animation.ready here.
window.requestAnimationFrame(function() {
is(player.isRunningOnCompositor, false,
'AnimationPlayer reports that it is NOT running on the compositor'
is(animation.isRunningOnCompositor, false,
'Animation reports that it is NOT running on the compositor'
+ ' when paused');
SimpleTest.finish();
});

View File

@ -15,21 +15,21 @@
test(function(t) {
var div = addDiv(t);
div.style.animation = 'xyz 100s';
assert_equals(div.getAnimationPlayers()[0].source.effect.name, 'xyz',
assert_equals(div.getAnimations()[0].source.effect.name, 'xyz',
'Animation effect name matches keyframes rule name');
}, 'Effect name makes keyframe rule');
test(function(t) {
var div = addDiv(t);
div.style.animation = 'x\\yz 100s';
assert_equals(div.getAnimationPlayers()[0].source.effect.name, 'xyz',
assert_equals(div.getAnimations()[0].source.effect.name, 'xyz',
'Escaped animation effect name matches keyframes rule name');
}, 'Escaped animation name');
test(function(t) {
var div = addDiv(t);
div.style.animation = 'x\\79 z 100s';
assert_equals(div.getAnimationPlayers()[0].source.effect.name, 'xyz',
assert_equals(div.getAnimations()[0].source.effect.name, 'xyz',
'Hex-escaped animation effect name matches keyframes rule'
+ ' name');
}, 'Animation name with hex-escape');

View File

@ -22,17 +22,17 @@ async_test(function(t) {
var cs = window.getComputedStyle(div);
div.style.animation = 'anim 1000s';
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
assert_equals(getMarginLeft(cs), 0,
'Initial value of margin-left is zero');
var previousAnimVal = getMarginLeft(cs);
player.ready.then(waitForFrame).then(t.step_func(function() {
animation.ready.then(waitForFrame).then(t.step_func(function() {
assert_true(getMarginLeft(cs) > previousAnimVal,
'margin-left is initially increasing');
player.pause();
return player.ready;
animation.pause();
return animation.ready;
})).then(t.step_func(function() {
previousAnimVal = getMarginLeft(cs);
return waitForFrame();
@ -48,14 +48,14 @@ async_test(function(t) {
var cs = window.getComputedStyle(div);
div.style.animation = 'anim 1000s paused';
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
assert_equals(getMarginLeft(cs), 0,
'Initial value of margin-left is zero');
player.pause();
animation.pause();
div.style.animationPlayState = 'running';
player.ready.then(waitForFrame).then(t.step_func(function() {
animation.ready.then(waitForFrame).then(t.step_func(function() {
assert_equals(cs.animationPlayState, 'running',
'animation-play-state is running');
assert_equals(getMarginLeft(cs), 0,
@ -69,14 +69,14 @@ async_test(function(t) {
var cs = window.getComputedStyle(div);
div.style.animation = 'anim 1000s paused';
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
assert_equals(getMarginLeft(cs), 0,
'Initial value of margin-left is zero');
player.play();
animation.play();
player.ready.then(waitForFrame).then(t.step_func(function() {
animation.ready.then(waitForFrame).then(t.step_func(function() {
assert_true(getMarginLeft(cs) > 0,
'Playing value of margin-left is greater than zero');
t.done();
@ -88,15 +88,15 @@ async_test(function(t) {
var cs = window.getComputedStyle(div);
div.style.animation = 'anim 1000s paused';
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
assert_equals(getMarginLeft(cs), 0,
'Initial value of margin-left is zero');
player.play();
animation.play();
var previousAnimVal;
player.ready.then(function() {
animation.ready.then(function() {
div.style.animationPlayState = 'running';
cs.animationPlayState; // Trigger style resolution
return waitForFrame();
@ -104,7 +104,7 @@ async_test(function(t) {
assert_equals(cs.animationPlayState, 'running',
'animation-play-state is running');
div.style.animationPlayState = 'paused';
return player.ready;
return animation.ready;
})).then(t.step_func(function() {
assert_equals(cs.animationPlayState, 'paused',
'animation-play-state is paused');
@ -123,7 +123,7 @@ async_test(function(t) {
var cs = window.getComputedStyle(div);
div.style.animation = 'anim 1000s';
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
assert_equals(getMarginLeft(cs), 0,
'Initial value of margin-left is zero');
@ -131,10 +131,10 @@ async_test(function(t) {
// 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';
player.play();
animation.play();
var previousAnimVal = getMarginLeft(cs);
player.ready.then(waitForFrame).then(t.step_func(function() {
animation.ready.then(waitForFrame).then(t.step_func(function() {
assert_equals(cs.animationPlayState, 'paused',
'animation-play-state is paused');
assert_true(getMarginLeft(cs) > previousAnimVal,
@ -148,7 +148,7 @@ async_test(function(t) {
var cs = window.getComputedStyle(div);
div.style.animation = 'anim 1000s paused';
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
assert_equals(getMarginLeft(cs), 0,
'Initial value of margin-left is zero');
@ -163,10 +163,10 @@ async_test(function(t) {
// 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';
player.pause();
animation.pause();
var previousAnimVal = getMarginLeft(cs);
player.ready.then(waitForFrame).then(t.step_func(function() {
animation.ready.then(waitForFrame).then(t.step_func(function() {
assert_equals(cs.animationPlayState, 'running',
'animation-play-state is running');
assert_equals(getMarginLeft(cs), previousAnimVal,

View File

@ -3,7 +3,7 @@
<head>
<meta charset=utf-8>
<title>Tests for the effect of setting a CSS animation's
AnimationPlayer.currentTime</title>
Animation.currentTime</title>
<style>
.animated-div {
@ -200,19 +200,19 @@ function EventWatcher(watchedNode, eventTypes)
// active interval. (If there is no delay, they are the same.)
// Called when currentTime is set to zero (the beginning of the start delay).
function checkStateOnSettingCurrentTimeToZero(player)
function checkStateOnSettingCurrentTimeToZero(animation)
{
// We don't test player.currentTime since our caller just set it.
// We don't test animation.currentTime since our caller just set it.
assert_equals(player.playState, 'running',
'AnimationPlayer.playState should be "running" at the start of ' +
assert_equals(animation.playState, 'running',
'Animation.playState should be "running" at the start of ' +
'the start delay');
assert_equals(player.source.target.style.animationPlayState, 'running',
'AnimationPlayer.source.target.style.animationPlayState should be ' +
assert_equals(animation.source.target.style.animationPlayState, 'running',
'Animation.source.target.style.animationPlayState should be ' +
'"running" at the start of the start delay');
var div = player.source.target;
var div = animation.source.target;
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
assert_equals(marginLeft, UNANIMATED_POSITION,
'the computed value of margin-left should be unaffected ' +
@ -220,24 +220,24 @@ function checkStateOnSettingCurrentTimeToZero(player)
}
// Called when the ready Promise's callbacks should happen
function checkStateOnReadyPromiseResolved(player)
function checkStateOnReadyPromiseResolved(animation)
{
// the 0.0001 here is for rounding error
assert_less_than_equal(player.currentTime,
player.timeline.currentTime - player.startTime + 0.0001,
'AnimationPlayer.currentTime should be less than the local time ' +
assert_less_than_equal(animation.currentTime,
animation.timeline.currentTime - animation.startTime + 0.0001,
'Animation.currentTime should be less than the local time ' +
'equivalent of the timeline\'s currentTime on the first paint tick ' +
'after animation creation');
assert_equals(player.playState, 'running',
'AnimationPlayer.playState should be "running" on the first paint ' +
assert_equals(animation.playState, 'running',
'Animation.playState should be "running" on the first paint ' +
'tick after animation creation');
assert_equals(player.source.target.style.animationPlayState, 'running',
'AnimationPlayer.source.target.style.animationPlayState should be ' +
assert_equals(animation.source.target.style.animationPlayState, 'running',
'Animation.source.target.style.animationPlayState should be ' +
'"running" on the first paint tick after animation creation');
var div = player.source.target;
var div = animation.source.target;
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
assert_equals(marginLeft, UNANIMATED_POSITION,
'the computed value of margin-left should be unaffected ' +
@ -245,30 +245,30 @@ function checkStateOnReadyPromiseResolved(player)
}
// Called when currentTime is set to the time the active interval starts.
function checkStateAtActiveIntervalStartTime(player)
function checkStateAtActiveIntervalStartTime(animation)
{
// We don't test player.currentTime since our caller just set it.
// We don't test animation.currentTime since our caller just set it.
assert_equals(player.playState, 'running',
'AnimationPlayer.playState should be "running" at the start of ' +
assert_equals(animation.playState, 'running',
'Animation.playState should be "running" at the start of ' +
'the active interval');
assert_equals(player.source.target.style.animationPlayState, 'running',
'AnimationPlayer.source.target.style.animationPlayState should be ' +
assert_equals(animation.source.target.style.animationPlayState, 'running',
'Animation.source.target.style.animationPlayState should be ' +
'"running" at the start of the active interval');
var div = player.source.target;
var div = animation.source.target;
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
assert_between_inclusive(marginLeft, INITIAL_POSITION, TEN_PCT_POSITION,
'the computed value of margin-left should be close to the value at the ' +
'beginning of the animation');
}
function checkStateAtFiftyPctOfActiveInterval(player)
function checkStateAtFiftyPctOfActiveInterval(animation)
{
// We don't test player.currentTime since our caller just set it.
// We don't test animation.currentTime since our caller just set it.
var div = player.source.target;
var div = animation.source.target;
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
assert_equals(marginLeft, FIFTY_PCT_POSITION,
'the computed value of margin-left should be half way through the ' +
@ -276,19 +276,19 @@ function checkStateAtFiftyPctOfActiveInterval(player)
}
// Called when currentTime is set to the time the active interval ends.
function checkStateAtActiveIntervalEndTime(player)
function checkStateAtActiveIntervalEndTime(animation)
{
// We don't test player.currentTime since our caller just set it.
// We don't test animation.currentTime since our caller just set it.
assert_equals(player.playState, 'finished',
'AnimationPlayer.playState should be "finished" at the end of ' +
assert_equals(animation.playState, 'finished',
'Animation.playState should be "finished" at the end of ' +
'the active interval');
assert_equals(player.source.target.style.animationPlayState, "running",
'AnimationPlayer.source.target.style.animationPlayState should be ' +
assert_equals(animation.source.target.style.animationPlayState, "running",
'Animation.source.target.style.animationPlayState should be ' +
'"finished" at the end of the active interval');
var div = player.source.target;
var div = animation.source.target;
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
assert_equals(marginLeft, UNANIMATED_POSITION,
'the computed value of margin-left should be unaffected ' +
@ -303,19 +303,19 @@ test(function(t)
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
// Animations shouldn't start until the next paint tick, so:
assert_equals(player.currentTime, 0,
'AnimationPlayer.currentTime should be zero when an animation ' +
assert_equals(animation.currentTime, 0,
'Animation.currentTime should be zero when an animation ' +
'is initially created');
assert_equals(player.playState, "pending",
'AnimationPlayer.playState should be "pending" when an animation ' +
assert_equals(animation.playState, "pending",
'Animation.playState should be "pending" when an animation ' +
'is initially created');
assert_equals(player.source.target.style.animationPlayState, 'running',
'AnimationPlayer.source.target.style.animationPlayState should be ' +
assert_equals(animation.source.target.style.animationPlayState, 'running',
'Animation.source.target.style.animationPlayState should be ' +
'"running" when an animation is initially created');
// XXX Ideally we would have a test to check the ready Promise is initially
@ -324,13 +324,13 @@ test(function(t)
// will be called (async) regardless of whether the Promise was resolved in
// the past or is resolved in the future.
// Just so that player is running instead of paused when we set currentTime:
player.startTime = player.timeline.currentTime;
// So that animation is running instead of paused when we set currentTime:
animation.startTime = animation.timeline.currentTime;
assert_approx_equals(player.currentTime, 0, 0.0001, // rounding error
assert_approx_equals(animation.currentTime, 0, 0.0001, // rounding error
'Check setting of currentTime actually works');
checkStateOnSettingCurrentTimeToZero(player);
checkStateOnSettingCurrentTimeToZero(animation);
}, 'Sanity test to check round-tripping assigning to new animation\'s ' +
'currentTime');
@ -341,24 +341,26 @@ async_test(function(t) {
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
player.ready.then(t.step_func(function() {
checkStateOnReadyPromiseResolved(player);
animation.ready.then(t.step_func(function() {
checkStateOnReadyPromiseResolved(animation);
player.currentTime = currentTimeForStartOfActiveInterval(player.timeline);
animation.currentTime =
currentTimeForStartOfActiveInterval(animation.timeline);
return eventWatcher.waitForEvent('animationstart');
})).then(t.step_func(function() {
checkStateAtActiveIntervalStartTime(player);
checkStateAtActiveIntervalStartTime(animation);
player.currentTime =
currentTimeForFiftyPercentThroughActiveInterval(player.timeline);
checkStateAtFiftyPctOfActiveInterval(player);
animation.currentTime =
currentTimeForFiftyPercentThroughActiveInterval(animation.timeline);
checkStateAtFiftyPctOfActiveInterval(animation);
player.currentTime = currentTimeForEndOfActiveInterval(player.timeline);
animation.currentTime =
currentTimeForEndOfActiveInterval(animation.timeline);
return eventWatcher.waitForEvent('animationend');
})).then(t.step_func(function() {
checkStateAtActiveIntervalEndTime(player);
checkStateAtActiveIntervalEndTime(animation);
eventWatcher.stopWatching();
})).catch(t.step_func(function(reason) {
@ -375,14 +377,14 @@ async_test(function(t) {
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
// Just so that player is running instead of paused when we set currentTime:
player.startTime = player.timeline.currentTime;
// So that animation is running instead of paused when we set currentTime:
animation.startTime = animation.timeline.currentTime;
player.currentTime = currentTimeForEndOfActiveInterval(player.timeline);
animation.currentTime = currentTimeForEndOfActiveInterval(animation.timeline);
var previousTimelineTime = player.timeline.currentTime;
var previousTimelineTime = animation.timeline.currentTime;
// Skipping over the active interval will dispatch an 'animationstart' then
// an 'animationend' event. We need to wait for these events before we start
@ -398,10 +400,10 @@ async_test(function(t) {
// Now we can start the tests for skipping backwards, but first we check
// that after the events we're still in the same end time state:
checkStateAtActiveIntervalEndTime(player);
checkStateAtActiveIntervalEndTime(animation);
player.currentTime =
currentTimeForFiftyPercentThroughActiveInterval(player.timeline);
animation.currentTime =
currentTimeForFiftyPercentThroughActiveInterval(animation.timeline);
// Despite going backwards from after the end of the animation (to being
// in the active interval), we now expect an 'animationstart' event
@ -412,19 +414,20 @@ async_test(function(t) {
// be dispatched synchronously. We need to call waitForEvent first
// otherwise eventWatcher will assert that the event was unexpected.
var promise = eventWatcher.waitForEvent('animationstart');
checkStateAtFiftyPctOfActiveInterval(player);
checkStateAtFiftyPctOfActiveInterval(animation);
return promise;
})).then(t.step_func(function() {
player.currentTime = currentTimeForStartOfActiveInterval(player.timeline);
checkStateAtActiveIntervalStartTime(player);
animation.currentTime =
currentTimeForStartOfActiveInterval(animation.timeline);
checkStateAtActiveIntervalStartTime(animation);
player.currentTime = 0;
animation.currentTime = 0;
// Despite going backwards from just after the active interval starts to
// the animation start time, we now expect an animationend event
// because we went from inside to outside the active interval.
return eventWatcher.waitForEvent('animationend');
})).then(t.step_func(function() {
checkStateOnReadyPromiseResolved(player);
checkStateOnReadyPromiseResolved(animation);
eventWatcher.stopWatching();
})).catch(t.step_func(function(reason) {
@ -435,9 +438,9 @@ async_test(function(t) {
// This must come after we've set up the Promise chain, since requesting
// computed style will force events to be dispatched.
// XXX For some reason this fails occasionally (either the player.playState
// XXX For some reason this fails occasionally (either the animation.playState
// check or the marginLeft check).
//checkStateAtActiveIntervalEndTime(player);
//checkStateAtActiveIntervalEndTime(animation);
}, 'Skipping backwards through animation');
@ -454,10 +457,10 @@ async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(div, CSS_ANIM_EVENTS);
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
player.currentTime = currentTimeForActivePhase(player.timeline);
player.currentTime = currentTimeForBeforePhase(player.timeline);
animation.currentTime = currentTimeForActivePhase(animation.timeline);
animation.currentTime = currentTimeForBeforePhase(animation.timeline);
waitForTwoAnimationFrames().then(function() {
eventWatcher.stopWatching();
@ -469,10 +472,10 @@ async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(div, CSS_ANIM_EVENTS);
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
player.currentTime = currentTimeForAfterPhase(player.timeline);
player.currentTime = currentTimeForBeforePhase(player.timeline);
animation.currentTime = currentTimeForAfterPhase(animation.timeline);
animation.currentTime = currentTimeForBeforePhase(animation.timeline);
waitForTwoAnimationFrames().then(function() {
eventWatcher.stopWatching();
@ -484,11 +487,11 @@ async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(div, CSS_ANIM_EVENTS);
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
eventWatcher.waitForEvent('animationstart').then(function() {
player.currentTime = currentTimeForBeforePhase(player.timeline);
player.currentTime = currentTimeForActivePhase(player.timeline);
animation.currentTime = currentTimeForBeforePhase(animation.timeline);
animation.currentTime = currentTimeForActivePhase(animation.timeline);
waitForTwoAnimationFrames().then(function() {
eventWatcher.stopWatching();
@ -496,18 +499,18 @@ async_test(function(t) {
});
});
// get us into the initial state:
player.currentTime = currentTimeForActivePhase(player.timeline);
animation.currentTime = currentTimeForActivePhase(animation.timeline);
}, 'Redundant change, active -> before, then back');
async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(div, CSS_ANIM_EVENTS);
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
eventWatcher.waitForEvent('animationstart').then(function() {
player.currentTime = currentTimeForAfterPhase(player.timeline);
player.currentTime = currentTimeForActivePhase(player.timeline);
animation.currentTime = currentTimeForAfterPhase(animation.timeline);
animation.currentTime = currentTimeForActivePhase(animation.timeline);
waitForTwoAnimationFrames().then(function() {
eventWatcher.stopWatching();
@ -515,19 +518,19 @@ async_test(function(t) {
});
});
// get us into the initial state:
player.currentTime = currentTimeForActivePhase(player.timeline);
animation.currentTime = currentTimeForActivePhase(animation.timeline);
}, 'Redundant change, active -> after, then back');
async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(div, CSS_ANIM_EVENTS);
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
eventWatcher.waitForEvents(['animationstart',
'animationend']).then(function() {
player.currentTime = currentTimeForBeforePhase(player.timeline);
player.currentTime = currentTimeForAfterPhase(player.timeline);
animation.currentTime = currentTimeForBeforePhase(animation.timeline);
animation.currentTime = currentTimeForAfterPhase(animation.timeline);
waitForTwoAnimationFrames().then(function() {
eventWatcher.stopWatching();
@ -535,19 +538,19 @@ async_test(function(t) {
});
});
// get us into the initial state:
player.currentTime = currentTimeForAfterPhase(player.timeline);
animation.currentTime = currentTimeForAfterPhase(animation.timeline);
}, 'Redundant change, after -> before, then back');
async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(div, CSS_ANIM_EVENTS);
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
eventWatcher.waitForEvents(['animationstart',
'animationend']).then(function() {
player.currentTime = currentTimeForActivePhase(player.timeline);
player.currentTime = currentTimeForAfterPhase(player.timeline);
animation.currentTime = currentTimeForActivePhase(animation.timeline);
animation.currentTime = currentTimeForAfterPhase(animation.timeline);
waitForTwoAnimationFrames().then(function() {
eventWatcher.stopWatching();
@ -555,7 +558,7 @@ async_test(function(t) {
});
});
// get us into the initial state:
player.currentTime = currentTimeForAfterPhase(player.timeline);
animation.currentTime = currentTimeForAfterPhase(animation.timeline);
}, 'Redundant change, after -> active, then back');
@ -563,18 +566,18 @@ async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
player.ready.then(t.step_func(function() {
animation.ready.then(t.step_func(function() {
var exception;
try {
player.currentTime = null;
animation.currentTime = null;
} catch (e) {
exception = e;
}
assert_equals(exception.name, 'TypeError',
'Expect TypeError exception on trying to set ' +
'AnimationPlayer.currentTime to null');
'Animation.currentTime to null');
})).catch(t.step_func(function(reason) {
assert_unreached(reason);
})).then(function() {
@ -587,26 +590,26 @@ async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
div.style.animation = 'anim 100s';
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
var pauseTime;
player.ready.then(t.step_func(function() {
assert_not_equals(player.currentTime, null,
'AnimationPlayer.currentTime not null on ready Promise resolve');
player.pause();
return player.ready;
animation.ready.then(t.step_func(function() {
assert_not_equals(animation.currentTime, null,
'Animation.currentTime not null on ready Promise resolve');
animation.pause();
return animation.ready;
})).then(t.step_func(function() {
pauseTime = player.currentTime;
pauseTime = animation.currentTime;
return waitForFrame();
})).then(t.step_func(function() {
assert_equals(player.currentTime, pauseTime,
'AnimationPlayer.currentTime is unchanged after pausing');
assert_equals(animation.currentTime, pauseTime,
'Animation.currentTime is unchanged after pausing');
})).catch(t.step_func(function(reason) {
assert_unreached(reason);
})).then(function() {
t.done();
});
}, 'AnimationPlayer.currentTime after pausing');
}, 'Animation.currentTime after pausing');
</script>
</body>

View File

@ -19,25 +19,25 @@ const ANIM_DURATION = 100000; // ms
async_test(function(t) {
var div = addDiv(t);
div.style.animation = ANIM_PROP_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
var previousFinishedPromise = player.finished;
var previousFinishedPromise = animation.finished;
player.ready.then(t.step_func(function() {
assert_equals(player.finished, previousFinishedPromise,
animation.ready.then(t.step_func(function() {
assert_equals(animation.finished, previousFinishedPromise,
'Finished promise is the same object when playing starts');
player.pause();
assert_equals(player.finished, previousFinishedPromise,
animation.pause();
assert_equals(animation.finished, previousFinishedPromise,
'Finished promise does not change when pausing');
player.play();
assert_equals(player.finished, previousFinishedPromise,
animation.play();
assert_equals(animation.finished, previousFinishedPromise,
'Finished promise does not change when play() unpauses');
player.currentTime = ANIM_DURATION;
animation.currentTime = ANIM_DURATION;
return player.finished;
return animation.finished;
})).then(t.step_func(function() {
assert_equals(player.finished, previousFinishedPromise,
assert_equals(animation.finished, previousFinishedPromise,
'Finished promise is the same object when playing completes');
t.done();
}));
@ -46,22 +46,22 @@ async_test(function(t) {
async_test(function(t) {
var div = addDiv(t);
div.style.animation = ANIM_PROP_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
var previousFinishedPromise = player.finished;
var previousFinishedPromise = animation.finished;
player.currentTime = ANIM_DURATION;
animation.currentTime = ANIM_DURATION;
player.finished.then(t.step_func(function() {
assert_equals(player.finished, previousFinishedPromise,
animation.finished.then(t.step_func(function() {
assert_equals(animation.finished, previousFinishedPromise,
'Finished promise is the same object when playing completes');
player.play();
assert_not_equals(player.finished, previousFinishedPromise,
animation.play();
assert_not_equals(animation.finished, previousFinishedPromise,
'Finished promise changes when replaying animation');
previousFinishedPromise = player.finished;
player.play();
assert_equals(player.finished, previousFinishedPromise,
previousFinishedPromise = animation.finished;
animation.play();
assert_equals(animation.finished, previousFinishedPromise,
'Finished promise is the same after redundant play() call');
t.done();
@ -71,24 +71,24 @@ async_test(function(t) {
async_test(function(t) {
var div = addDiv(t);
div.style.animation = ANIM_PROP_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
var previousFinishedPromise;
player.currentTime = ANIM_DURATION;
animation.currentTime = ANIM_DURATION;
player.finished.then(function() {
previousFinishedPromise = player.finished;
player.playbackRate = -1;
assert_not_equals(player.finished, previousFinishedPromise,
animation.finished.then(function() {
previousFinishedPromise = animation.finished;
animation.playbackRate = -1;
assert_not_equals(animation.finished, previousFinishedPromise,
'Finished promise should be replaced when reversing a ' +
'finished promise');
player.currentTime = 0;
return player.finished;
animation.currentTime = 0;
return animation.finished;
}).then(t.step_func(function() {
previousFinishedPromise = player.finished;
player.play();
assert_not_equals(player.finished, previousFinishedPromise,
previousFinishedPromise = animation.finished;
animation.play();
assert_not_equals(animation.finished, previousFinishedPromise,
'Finished promise is replaced after play() call on ' +
'finished, reversed animation');
t.done();
@ -98,15 +98,15 @@ async_test(function(t) {
async_test(function(t) {
var div = addDiv(t);
div.style.animation = ANIM_PROP_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
var previousFinishedPromise = player.finished;
var previousFinishedPromise = animation.finished;
player.currentTime = ANIM_DURATION;
animation.currentTime = ANIM_DURATION;
player.finished.then(t.step_func(function() {
player.currentTime = ANIM_DURATION + 1000;
assert_equals(player.finished, previousFinishedPromise,
animation.finished.then(t.step_func(function() {
animation.currentTime = ANIM_DURATION + 1000;
assert_equals(animation.finished, previousFinishedPromise,
'Finished promise is unchanged jumping past end of ' +
'finished animation');
@ -117,36 +117,36 @@ async_test(function(t) {
async_test(function(t) {
var div = addDiv(t);
div.style.animation = ANIM_PROP_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
player.currentTime = ANIM_DURATION;
player.finished.then(t.step_func(function(resolvedPlayer) {
assert_equals(resolvedPlayer, player,
'Object identity of player passed to Promise callback'
+ ' matches the player object owning the Promise');
animation.currentTime = ANIM_DURATION;
animation.finished.then(t.step_func(function(resolvedAnimation) {
assert_equals(resolvedAnimation, animation,
'Object identity of animation passed to Promise callback'
+ ' matches the animation object owning the Promise');
t.done();
}));
}, 'The finished promise is fulfilled with its AnimationPlayer');
}, 'The finished promise is fulfilled with its Animation');
async_test(function(t) {
var div = addDiv(t);
// Set up pending animation
div.style.animation = ANIM_PROP_VAL;
var player = div.getAnimationPlayers()[0];
var previousFinishedPromise = player.finished;
var animation = div.getAnimations()[0];
var previousFinishedPromise = animation.finished;
// Set up listeners on finished promise
player.finished.then(t.step_func(function() {
animation.finished.then(t.step_func(function() {
assert_unreached('finished promise is fulfilled');
})).catch(t.step_func(function(err) {
assert_not_equals(player.finished, previousFinishedPromise,
assert_not_equals(animation.finished, previousFinishedPromise,
'Finished promise should change after the original is ' +
'rejected');
assert_equals(err.name, 'AbortError',
'finished promise is rejected with AbortError');
assert_equals(player.playState, 'idle',
'Player is idle after animation was cancelled');
assert_equals(animation.playState, 'idle',
'Animation is idle after animation was cancelled');
})).then(t.step_func(function() {
t.done();
}));
@ -167,20 +167,20 @@ async_test(function(t) {
// Set up pending animation
div.style.animation = ANIM_PROP_VAL;
var player = div.getAnimationPlayers()[0];
var previousFinishedPromise = player.finished;
var animation = div.getAnimations()[0];
var previousFinishedPromise = animation.finished;
// Set up listeners on finished promise
player.finished.then(t.step_func(function() {
animation.finished.then(t.step_func(function() {
assert_unreached('finished promise was fulfilled');
})).catch(t.step_func(function(err) {
assert_not_equals(player.finished, previousFinishedPromise,
assert_not_equals(animation.finished, previousFinishedPromise,
'Finished promise should change after the original is ' +
'rejected');
assert_equals(err.name, 'AbortError',
'finished promise is rejected with AbortError');
assert_equals(player.playState, 'idle',
'Player is idle after animation was cancelled');
assert_equals(animation.playState, 'idle',
'Animation is idle after animation was cancelled');
})).then(t.step_func(function() {
t.done();
}));
@ -195,14 +195,14 @@ async_test(function(t) {
async_test(function(t) {
var div = addDiv(t);
div.style.animation = ANIM_PROP_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
const HALF_DUR = ANIM_DURATION / 2;
const QUARTER_DUR = ANIM_DURATION / 4;
player.currentTime = HALF_DUR;
animation.currentTime = HALF_DUR;
div.style.animationDuration = QUARTER_DUR + 'ms';
// Player should now be finished
// Animation should now be finished
// Below we use gotNextFrame to check that shortening of the animation
// duration causes the finished promise to resolve, rather than it just
@ -216,15 +216,15 @@ async_test(function(t) {
gotNextFrame = true;
});
player.finished.then(t.step_func(function() {
animation.finished.then(t.step_func(function() {
assert_false(gotNextFrame, 'shortening of the animation duration should ' +
'resolve the finished promise');
assert_equals(player.currentTime, HALF_DUR,
assert_equals(animation.currentTime, HALF_DUR,
'currentTime should be unchanged when duration shortened');
var previousFinishedPromise = player.finished;
var previousFinishedPromise = animation.finished;
div.style.animationDuration = ANIM_DURATION + 'ms'; // now active again
window.getComputedStyle(div).animationDuration; // flush style
assert_not_equals(player.finished, previousFinishedPromise,
assert_not_equals(animation.finished, previousFinishedPromise,
'Finished promise should change after lengthening the ' +
'duration causes the animation to become active');
t.done();
@ -234,17 +234,17 @@ async_test(function(t) {
async_test(function(t) {
var div = addDiv(t);
div.style.animation = ANIM_PROP_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
player.ready.then(function() {
player.playbackRate = 0;
player.currentTime = ANIM_DURATION + 1000;
animation.ready.then(function() {
animation.playbackRate = 0;
animation.currentTime = ANIM_DURATION + 1000;
return waitForTwoAnimationFrames();
}).then(t.step_func(function() {
t.done();
}));
player.finished.then(t.step_func(function() {
animation.finished.then(t.step_func(function() {
assert_unreached('finished promise should not resolve when playbackRate ' +
'is zero');
}));
@ -253,11 +253,11 @@ async_test(function(t) {
async_test(function(t) {
var div = addDiv(t);
div.style.animation = ANIM_PROP_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
player.ready.then(function() {
player.playbackRate = -1;
return player.finished;
animation.ready.then(function() {
animation.playbackRate = -1;
return animation.finished;
}).then(t.step_func(function() {
t.done();
}));
@ -266,20 +266,20 @@ async_test(function(t) {
async_test(function(t) {
var div = addDiv(t);
div.style.animation = ANIM_PROP_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
var previousFinishedPromise = player.finished;
var previousFinishedPromise = animation.finished;
player.currentTime = ANIM_DURATION;
animation.currentTime = ANIM_DURATION;
player.finished.then(function() {
animation.finished.then(function() {
div.style.animationPlayState = 'running';
return waitForTwoAnimationFrames();
}).then(t.step_func(function() {
assert_equals(player.finished, previousFinishedPromise,
assert_equals(animation.finished, previousFinishedPromise,
'Should not replay when animation-play-state changes to ' +
'"running" on finished animation');
assert_equals(player.currentTime, ANIM_DURATION,
assert_equals(animation.currentTime, ANIM_DURATION,
'currentTime should not change when animation-play-state ' +
'changes to "running" on finished animation');
t.done();

View File

@ -15,59 +15,59 @@ async_test(function(t) {
var cs = window.getComputedStyle(div);
div.style.animation = 'anim 1000s';
var player = div.getAnimationPlayers()[0];
assert_equals(player.playState, 'pending');
var animation = div.getAnimations()[0];
assert_equals(animation.playState, 'pending');
player.ready.then(t.step_func(function() {
assert_equals(player.playState, 'running');
animation.ready.then(t.step_func(function() {
assert_equals(animation.playState, 'running');
t.done();
}));
}, 'Player returns correct playState when running');
}, 'Animation returns correct playState when running');
async_test(function(t) {
var div = addDiv(t);
var cs = window.getComputedStyle(div);
div.style.animation = 'anim 1000s paused';
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
// FIXME: When we turn on async pausing later in this patch series, enable
// this
// assert_equals(player.playState, 'pending');
// assert_equals(animation.playState, 'pending');
player.ready.then(t.step_func(function() {
assert_equals(player.playState, 'paused');
animation.ready.then(t.step_func(function() {
assert_equals(animation.playState, 'paused');
t.done();
}));
}, 'Player returns correct playState when paused');
}, 'Animation returns correct playState when paused');
async_test(function(t) {
var div = addDiv(t);
var cs = window.getComputedStyle(div);
div.style.animation = 'anim 1000s';
var player = div.getAnimationPlayers()[0];
player.pause();
var animation = div.getAnimations()[0];
animation.pause();
// FIXME: When we turn on async pausing later in this patch series, enable
// this
// assert_equals(player.playState, 'pending');
// assert_equals(animation.playState, 'pending');
player.ready.then(t.step_func(function() {
assert_equals(player.playState, 'paused');
animation.ready.then(t.step_func(function() {
assert_equals(animation.playState, 'paused');
t.done();
}));
}, 'Player.playState updates when paused by script');
}, 'Animation.playState updates when paused by script');
test(function(t) {
var div = addDiv(t);
var cs = window.getComputedStyle(div);
div.style.animation = 'anim 1000s paused';
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
div.style.animationPlayState = 'running';
// This test also checks that calling playState flushes style
assert_equals(player.playState, 'pending',
'Player.playState reports pending after updating'
+ ' animation-play-state (got: ' + player.playState + ')');
}, 'Player.playState updates when resumed by setting style');
assert_equals(animation.playState, 'pending',
'Animation.playState reports pending after updating'
+ ' animation-play-state (got: ' + animation.playState + ')');
}, 'Animation.playState updates when resumed by setting style');
</script>

View File

@ -15,19 +15,19 @@
async_test(function(t) {
var div = addDiv(t);
div.style.animation = 'abc 100s';
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
var originalReadyPromise = player.ready;
player.ready.then(function() {
assert_equals(player.ready, originalReadyPromise,
var originalReadyPromise = animation.ready;
animation.ready.then(function() {
assert_equals(animation.ready, originalReadyPromise,
'Ready promise is the same object when playing completes');
player.pause();
animation.pause();
// TODO: When we implement deferred pausing (bug 1109390), change this to
// assert_not_equals and wait on the new promise before continuing.
assert_equals(player.ready, originalReadyPromise,
assert_equals(animation.ready, originalReadyPromise,
'Ready promise does not change when pausing (for now)');
player.play();
assert_not_equals(player.ready, originalReadyPromise,
animation.play();
assert_not_equals(animation.ready, originalReadyPromise,
'Ready promise object identity differs after calling'
+ ' play()');
t.done();
@ -38,11 +38,11 @@ async_test(function(t) {
test(function(t) {
var div = addDiv(t);
div.style.animation = 'abc 100s paused';
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
var originalReadyPromise = player.ready;
var originalReadyPromise = animation.ready;
div.style.animationPlayState = 'running';
assert_not_equals(player.ready, originalReadyPromise,
assert_not_equals(animation.ready, originalReadyPromise,
'After updating animation-play-state a new ready promise'
+ ' object is created');
}, 'A new ready promise is created when setting animation-play-state: running');
@ -50,12 +50,12 @@ test(function(t) {
async_test(function(t) {
var div = addDiv(t);
div.style.animation = 'abc 100s';
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
player.ready.then(function() {
var promiseBeforeCallingPlay = player.ready;
player.play();
assert_equals(player.ready, promiseBeforeCallingPlay,
animation.ready.then(function() {
var promiseBeforeCallingPlay = animation.ready;
animation.play();
assert_equals(animation.ready, promiseBeforeCallingPlay,
'Ready promise has same object identity after redundant call'
+ ' to play()');
t.done();
@ -65,32 +65,33 @@ async_test(function(t) {
async_test(function(t) {
var div = addDiv(t);
div.style.animation = 'abc 100s';
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
player.ready.then(function(resolvedPlayer) {
assert_equals(resolvedPlayer, player,
'Object identity of player passed to Promise callback'
+ ' matches the player object owning the Promise');
animation.ready.then(function(resolvedAnimation) {
assert_equals(resolvedAnimation, animation,
'Object identity of Animation passed to Promise callback'
+ ' matches the Animation object owning the Promise');
t.done();
});
}, 'The ready promise is fulfilled with its AnimationPlayer');
}, 'The ready promise is fulfilled with its Animation');
async_test(function(t) {
var div = addDiv(t);
// Set up pending animation
div.style.animation = 'abc 100s';
var player = div.getAnimationPlayers()[0];
assert_equals(player.playState, 'pending', 'Player is initially pending');
var animation = div.getAnimations()[0];
assert_equals(animation.playState, 'pending',
'Animation is initially pending');
// Set up listeners on ready promise
player.ready.then(t.step_func(function() {
animation.ready.then(t.step_func(function() {
assert_unreached('ready promise is fulfilled');
})).catch(t.step_func(function(err) {
assert_equals(err.name, 'AbortError',
'ready promise is rejected with AbortError');
assert_equals(player.playState, 'idle',
'Player is idle after animation was cancelled');
assert_equals(animation.playState, 'idle',
'Animation is idle after animation was cancelled');
})).then(t.step_func(function() {
t.done();
}));
@ -111,17 +112,18 @@ async_test(function(t) {
// Set up pending animation
div.style.animation = 'abc 100s';
var player = div.getAnimationPlayers()[0];
assert_equals(player.playState, 'pending', 'Player is initially pending');
var animation = div.getAnimations()[0];
assert_equals(animation.playState, 'pending',
'Animation is initially pending');
// Set up listeners on ready promise
player.ready.then(t.step_func(function() {
animation.ready.then(t.step_func(function() {
assert_unreached('ready promise was fulfilled');
})).catch(t.step_func(function(err) {
assert_equals(err.name, 'AbortError',
'ready promise is rejected with AbortError');
assert_equals(player.playState, 'idle',
'Player is idle after animation was cancelled');
assert_equals(animation.playState, 'idle',
'Animation is idle after animation was cancelled');
})).then(t.step_func(function() {
t.done();
}));

View File

@ -3,7 +3,7 @@
<head>
<meta charset=utf-8>
<title>Tests for the effect of setting a CSS animation's
AnimationPlayer.startTime</title>
Animation.startTime</title>
<style>
.animated-div {
@ -200,21 +200,21 @@ function EventWatcher(watchedNode, eventTypes)
// active interval. (If there is no delay, they are the same.)
// Called when the ready Promise's callbacks should happen
function checkStateOnReadyPromiseResolved(player)
function checkStateOnReadyPromiseResolved(animation)
{
assert_less_than_equal(player.startTime, player.timeline.currentTime,
'AnimationPlayer.startTime should be less than the timeline\'s ' +
assert_less_than_equal(animation.startTime, animation.timeline.currentTime,
'Animation.startTime should be less than the timeline\'s ' +
'currentTime on the first paint tick after animation creation');
assert_equals(player.playState, 'running',
'AnimationPlayer.playState should be "running" on the first paint ' +
assert_equals(animation.playState, 'running',
'Animation.playState should be "running" on the first paint ' +
'tick after animation creation');
assert_equals(player.source.target.style.animationPlayState, 'running',
'AnimationPlayer.source.target.style.animationPlayState should be ' +
assert_equals(animation.source.target.style.animationPlayState, 'running',
'Animation.source.target.style.animationPlayState should be ' +
'"running" on the first paint tick after animation creation');
var div = player.source.target;
var div = animation.source.target;
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
assert_equals(marginLeft, UNANIMATED_POSITION,
'the computed value of margin-left should be unaffected ' +
@ -222,30 +222,30 @@ function checkStateOnReadyPromiseResolved(player)
}
// Called when startTime is set to the time the active interval starts.
function checkStateAtActiveIntervalStartTime(player)
function checkStateAtActiveIntervalStartTime(animation)
{
// We don't test player.startTime since our caller just set it.
// We don't test animation.startTime since our caller just set it.
assert_equals(player.playState, 'running',
'AnimationPlayer.playState should be "running" at the start of ' +
assert_equals(animation.playState, 'running',
'Animation.playState should be "running" at the start of ' +
'the active interval');
assert_equals(player.source.target.style.animationPlayState, 'running',
'AnimationPlayer.source.target.style.animationPlayState should be ' +
assert_equals(animation.source.target.style.animationPlayState, 'running',
'Animation.source.target.style.animationPlayState should be ' +
'"running" at the start of the active interval');
var div = player.source.target;
var div = animation.source.target;
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
assert_between_inclusive(marginLeft, INITIAL_POSITION, TEN_PCT_POSITION,
'the computed value of margin-left should be close to the value at the ' +
'beginning of the animation');
}
function checkStateAtFiftyPctOfActiveInterval(player)
function checkStateAtFiftyPctOfActiveInterval(animation)
{
// We don't test player.startTime since our caller just set it.
// We don't test animation.startTime since our caller just set it.
var div = player.source.target;
var div = animation.source.target;
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
assert_equals(marginLeft, FIFTY_PCT_POSITION,
'the computed value of margin-left should be half way through the ' +
@ -253,19 +253,19 @@ function checkStateAtFiftyPctOfActiveInterval(player)
}
// Called when startTime is set to the time the active interval ends.
function checkStateAtActiveIntervalEndTime(player)
function checkStateAtActiveIntervalEndTime(animation)
{
// We don't test player.startTime since our caller just set it.
// We don't test animation.startTime since our caller just set it.
assert_equals(player.playState, 'finished',
'AnimationPlayer.playState should be "finished" at the end of ' +
assert_equals(animation.playState, 'finished',
'Animation.playState should be "finished" at the end of ' +
'the active interval');
assert_equals(player.source.target.style.animationPlayState, "running",
'AnimationPlayer.source.target.style.animationPlayState should be ' +
assert_equals(animation.source.target.style.animationPlayState, "running",
'Animation.source.target.style.animationPlayState should be ' +
'"finished" at the end of the active interval');
var div = player.source.target;
var div = animation.source.target;
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
assert_equals(marginLeft, UNANIMATED_POSITION,
'the computed value of margin-left should be unaffected ' +
@ -276,23 +276,23 @@ function checkStateAtActiveIntervalEndTime(player)
test(function(t)
{
var div = addDiv(t, { 'style': 'animation: anim 100s' });
var player = div.getAnimationPlayers()[0];
assert_equals(player.startTime, null, 'startTime is unresolved');
var animation = div.getAnimations()[0];
assert_equals(animation.startTime, null, 'startTime is unresolved');
}, 'startTime of a newly created (play-pending) animation is unresolved');
test(function(t)
{
var div = addDiv(t, { 'style': 'animation: anim 100s paused' });
var player = div.getAnimationPlayers()[0];
assert_equals(player.startTime, null, 'startTime is unresolved');
var animation = div.getAnimations()[0];
assert_equals(animation.startTime, null, 'startTime is unresolved');
}, 'startTime of a newly created (pause-pending) animation is unresolved');
async_test(function(t)
{
var div = addDiv(t, { 'style': 'animation: anim 100s' });
var player = div.getAnimationPlayers()[0];
player.ready.then(t.step_func(function() {
assert_true(player.startTime > 0,
var animation = div.getAnimations()[0];
animation.ready.then(t.step_func(function() {
assert_true(animation.startTime > 0,
'startTime is resolved when running');
t.done();
}));
@ -301,9 +301,9 @@ async_test(function(t)
async_test(function(t)
{
var div = addDiv(t, { 'style': 'animation: anim 100s paused' });
var player = div.getAnimationPlayers()[0];
player.ready.then(t.step_func(function() {
assert_equals(player.startTime, null,
var animation = div.getAnimations()[0];
animation.ready.then(t.step_func(function() {
assert_equals(animation.startTime, null,
'startTime is unresolved when paused');
t.done();
}));
@ -312,18 +312,18 @@ async_test(function(t)
async_test(function(t)
{
var div = addDiv(t, { 'style': 'animation: anim 100s' });
var player = div.getAnimationPlayers()[0];
player.ready.then(t.step_func(function() {
var animation = div.getAnimations()[0];
animation.ready.then(t.step_func(function() {
div.style.animationPlayState = 'paused';
getComputedStyle(div).animationPlayState;
/* FIXME: Switch this on once deferred pausing is enabled
assert_not_equals(player.startTime, null,
assert_not_equals(animation.startTime, null,
'startTime is resolved when pause-pending');
*/
div.style.animationPlayState = 'running';
getComputedStyle(div).animationPlayState;
assert_equals(player.startTime, null,
assert_equals(animation.startTime, null,
'startTime is unresolved when play-pending');
t.done();
}));
@ -332,16 +332,16 @@ async_test(function(t)
async_test(function(t)
{
var div = addDiv(t, { 'style': 'animation: anim 100s' });
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
// Seek to end to put us in the finished state
// FIXME: Once we implement finish(), use that here.
player.currentTime = 100 * 1000;
player.ready.then(t.step_func(function() {
animation.currentTime = 100 * 1000;
animation.ready.then(t.step_func(function() {
// Call play() which puts us back in the running state
player.play();
animation.play();
// FIXME: Enable this once we implement finishing behavior (bug 1074630)
/*
assert_equals(player.startTime, null, 'startTime is unresolved');
assert_equals(animation.startTime, null, 'startTime is unresolved');
*/
t.done();
}));
@ -353,10 +353,10 @@ test(function(t)
var div = addDiv(t, {'class': 'animated-div'});
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
var currentTime = player.timeline.currentTime;
player.startTime = currentTime;
assert_approx_equals(player.startTime, currentTime, 0.0001, // rounding error
var animation = div.getAnimations()[0];
var currentTime = animation.timeline.currentTime;
animation.startTime = currentTime;
assert_approx_equals(animation.startTime, currentTime, 0.0001, // rounding error
'Check setting of startTime actually works');
}, 'Sanity test to check round-tripping assigning to a new animation\'s ' +
'startTime');
@ -368,24 +368,24 @@ async_test(function(t) {
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
player.ready.then(t.step_func(function() {
checkStateOnReadyPromiseResolved(player);
animation.ready.then(t.step_func(function() {
checkStateOnReadyPromiseResolved(animation);
player.startTime = startTimeForStartOfActiveInterval(player.timeline);
animation.startTime = startTimeForStartOfActiveInterval(animation.timeline);
return eventWatcher.waitForEvent('animationstart');
})).then(t.step_func(function() {
checkStateAtActiveIntervalStartTime(player);
checkStateAtActiveIntervalStartTime(animation);
player.startTime =
startTimeForFiftyPercentThroughActiveInterval(player.timeline);
checkStateAtFiftyPctOfActiveInterval(player);
animation.startTime =
startTimeForFiftyPercentThroughActiveInterval(animation.timeline);
checkStateAtFiftyPctOfActiveInterval(animation);
player.startTime = startTimeForEndOfActiveInterval(player.timeline);
animation.startTime = startTimeForEndOfActiveInterval(animation.timeline);
return eventWatcher.waitForEvent('animationend');
})).then(t.step_func(function() {
checkStateAtActiveIntervalEndTime(player);
checkStateAtActiveIntervalEndTime(animation);
eventWatcher.stopWatching();
})).catch(t.step_func(function(reason) {
@ -402,11 +402,11 @@ async_test(function(t) {
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
player.startTime = startTimeForEndOfActiveInterval(player.timeline);
animation.startTime = startTimeForEndOfActiveInterval(animation.timeline);
var previousTimelineTime = player.timeline.currentTime;
var previousTimelineTime = animation.timeline.currentTime;
// Skipping over the active interval will dispatch an 'animationstart' then
// an 'animationend' event. We need to wait for these events before we start
@ -422,10 +422,10 @@ async_test(function(t) {
// Now we can start the tests for skipping backwards, but first we check
// that after the events we're still in the same end time state:
checkStateAtActiveIntervalEndTime(player);
checkStateAtActiveIntervalEndTime(animation);
player.startTime =
startTimeForFiftyPercentThroughActiveInterval(player.timeline);
animation.startTime =
startTimeForFiftyPercentThroughActiveInterval(animation.timeline);
// Despite going backwards from after the end of the animation (to being
// in the active interval), we now expect an 'animationstart' event
@ -436,19 +436,19 @@ async_test(function(t) {
// be dispatched synchronously. We need to call waitForEvent first
// otherwise eventWatcher will assert that the event was unexpected.
var promise = eventWatcher.waitForEvent('animationstart');
checkStateAtFiftyPctOfActiveInterval(player);
checkStateAtFiftyPctOfActiveInterval(animation);
return promise;
})).then(t.step_func(function() {
player.startTime = startTimeForStartOfActiveInterval(player.timeline);
checkStateAtActiveIntervalStartTime(player);
animation.startTime = startTimeForStartOfActiveInterval(animation.timeline);
checkStateAtActiveIntervalStartTime(animation);
player.startTime = player.timeline.currentTime;
animation.startTime = animation.timeline.currentTime;
// Despite going backwards from just after the active interval starts to
// the animation start time, we now expect an animationend event
// because we went from inside to outside the active interval.
return eventWatcher.waitForEvent('animationend');
})).then(t.step_func(function() {
checkStateOnReadyPromiseResolved(player);
checkStateOnReadyPromiseResolved(animation);
eventWatcher.stopWatching();
})).catch(t.step_func(function(reason) {
@ -459,9 +459,9 @@ async_test(function(t) {
// This must come after we've set up the Promise chain, since requesting
// computed style will force events to be dispatched.
// XXX For some reason this fails occasionally (either the player.playState
// XXX For some reason this fails occasionally (either the animation.playState
// check or the marginLeft check).
//checkStateAtActiveIntervalEndTime(player);
//checkStateAtActiveIntervalEndTime(animation);
}, 'Skipping backwards through animation');
@ -478,10 +478,10 @@ async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(div, CSS_ANIM_EVENTS);
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
player.startTime = startTimeForActivePhase(player.timeline);
player.startTime = startTimeForBeforePhase(player.timeline);
animation.startTime = startTimeForActivePhase(animation.timeline);
animation.startTime = startTimeForBeforePhase(animation.timeline);
waitForTwoAnimationFrames().then(function() {
eventWatcher.stopWatching();
@ -493,10 +493,10 @@ async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(div, CSS_ANIM_EVENTS);
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
player.startTime = startTimeForAfterPhase(player.timeline);
player.startTime = startTimeForBeforePhase(player.timeline);
animation.startTime = startTimeForAfterPhase(animation.timeline);
animation.startTime = startTimeForBeforePhase(animation.timeline);
waitForTwoAnimationFrames().then(function() {
eventWatcher.stopWatching();
@ -508,11 +508,11 @@ async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(div, CSS_ANIM_EVENTS);
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
eventWatcher.waitForEvent('animationstart').then(function() {
player.startTime = startTimeForBeforePhase(player.timeline);
player.startTime = startTimeForActivePhase(player.timeline);
animation.startTime = startTimeForBeforePhase(animation.timeline);
animation.startTime = startTimeForActivePhase(animation.timeline);
waitForTwoAnimationFrames().then(function() {
eventWatcher.stopWatching();
@ -520,18 +520,18 @@ async_test(function(t) {
});
});
// get us into the initial state:
player.startTime = startTimeForActivePhase(player.timeline);
animation.startTime = startTimeForActivePhase(animation.timeline);
}, 'Redundant change, active -> before, then back');
async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(div, CSS_ANIM_EVENTS);
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
eventWatcher.waitForEvent('animationstart').then(function() {
player.startTime = startTimeForAfterPhase(player.timeline);
player.startTime = startTimeForActivePhase(player.timeline);
animation.startTime = startTimeForAfterPhase(animation.timeline);
animation.startTime = startTimeForActivePhase(animation.timeline);
waitForTwoAnimationFrames().then(function() {
eventWatcher.stopWatching();
@ -539,19 +539,19 @@ async_test(function(t) {
});
});
// get us into the initial state:
player.startTime = startTimeForActivePhase(player.timeline);
animation.startTime = startTimeForActivePhase(animation.timeline);
}, 'Redundant change, active -> after, then back');
async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(div, CSS_ANIM_EVENTS);
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
eventWatcher.waitForEvents(['animationstart',
'animationend']).then(function() {
player.startTime = startTimeForBeforePhase(player.timeline);
player.startTime = startTimeForAfterPhase(player.timeline);
animation.startTime = startTimeForBeforePhase(animation.timeline);
animation.startTime = startTimeForAfterPhase(animation.timeline);
waitForTwoAnimationFrames().then(function() {
eventWatcher.stopWatching();
@ -559,19 +559,19 @@ async_test(function(t) {
});
});
// get us into the initial state:
player.startTime = startTimeForAfterPhase(player.timeline);
animation.startTime = startTimeForAfterPhase(animation.timeline);
}, 'Redundant change, after -> before, then back');
async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
var eventWatcher = new EventWatcher(div, CSS_ANIM_EVENTS);
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
eventWatcher.waitForEvents(['animationstart',
'animationend']).then(function() {
player.startTime = startTimeForActivePhase(player.timeline);
player.startTime = startTimeForAfterPhase(player.timeline);
animation.startTime = startTimeForActivePhase(animation.timeline);
animation.startTime = startTimeForAfterPhase(animation.timeline);
waitForTwoAnimationFrames().then(function() {
eventWatcher.stopWatching();
@ -579,7 +579,7 @@ async_test(function(t) {
});
});
// get us into the initial state:
player.startTime = startTimeForAfterPhase(player.timeline);
animation.startTime = startTimeForAfterPhase(animation.timeline);
}, 'Redundant change, after -> active, then back');
@ -587,18 +587,18 @@ async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
div.style.animation = ANIM_PROPERTY_VAL;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
var storedCurrentTime;
player.ready.then(t.step_func(function() {
storedCurrentTime = player.currentTime;
player.startTime = null;
return player.ready;
animation.ready.then(t.step_func(function() {
storedCurrentTime = animation.currentTime;
animation.startTime = null;
return animation.ready;
})).catch(t.step_func(function(reason) {
assert_unreached(reason);
})).then(function() {
assert_equals(player.currentTime, storedCurrentTime,
assert_equals(animation.currentTime, storedCurrentTime,
'Test that hold time is correct');
t.done();
});
@ -609,27 +609,27 @@ async_test(function(t) {
var div = addDiv(t, {'class': 'animated-div'});
div.style.animation = 'anim 100s';
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
player.ready.then(t.step_func(function() {
var savedStartTime = player.startTime;
animation.ready.then(t.step_func(function() {
var savedStartTime = animation.startTime;
assert_not_equals(player.startTime, null,
'AnimationPlayer.startTime not null on ready Promise resolve');
assert_not_equals(animation.startTime, null,
'Animation.startTime not null on ready Promise resolve');
player.pause();
return player.ready;
animation.pause();
return animation.ready;
})).then(t.step_func(function() {
assert_equals(player.startTime, null,
'AnimationPlayer.startTime is null after paused');
assert_equals(player.playState, 'paused',
'AnimationPlayer.playState is "paused" after pause() call');
assert_equals(animation.startTime, null,
'Animation.startTime is null after paused');
assert_equals(animation.playState, 'paused',
'Animation.playState is "paused" after pause() call');
})).catch(t.step_func(function(reason) {
assert_unreached(reason);
})).then(function() {
t.done();
});
}, 'AnimationPlayer.startTime after paused');
}, 'Animation.startTime after paused');
</script>
</body>

View File

@ -13,8 +13,8 @@
test(function(t) {
var div = addDiv(t);
div.style.animation = 'anim 100s';
var players = div.getAnimationPlayers();
assert_equals(players[0].source.target, div,
var animation = div.getAnimations()[0];
assert_equals(animation.source.target, div,
'Animation.target is the animatable div');
}, 'Returned CSS animations have the correct Animation.target');

View File

@ -17,84 +17,84 @@ async_test(function(t) {
var div = addDiv(t);
div.style.animation = 'anim1 100s';
var originalPlayer = div.getAnimationPlayers()[0];
var originalAnimation = div.getAnimations()[0];
var originalStartTime;
var originalCurrentTime;
// Wait a moment so we can confirm the startTime doesn't change (and doesn't
// simply reflect the current time).
originalPlayer.ready.then(function() {
originalStartTime = originalPlayer.startTime;
originalCurrentTime = originalPlayer.currentTime;
originalAnimation.ready.then(function() {
originalStartTime = originalAnimation.startTime;
originalCurrentTime = originalAnimation.currentTime;
// Wait a moment so we can confirm the startTime doesn't change (and
// doesn't simply reflect the current time).
return waitForFrame();
}).then(t.step_func(function() {
div.style.animationDuration = '200s';
var player = div.getAnimationPlayers()[0];
assert_equals(player, originalPlayer,
'The same AnimationPlayer is returned after updating'
var animation = div.getAnimations()[0];
assert_equals(animation, originalAnimation,
'The same Animation is returned after updating'
+ ' animation duration');
assert_equals(player.startTime, originalStartTime,
'AnimationPlayers returned by getAnimationPlayers preserve'
assert_equals(animation.startTime, originalStartTime,
'Animations returned by getAnimations preserve'
+ ' their startTime even when they are updated');
// Sanity check
assert_not_equals(player.currentTime, originalCurrentTime,
'AnimationPlayer.currentTime has updated in next'
assert_not_equals(animation.currentTime, originalCurrentTime,
'Animation.currentTime has updated in next'
+ ' requestAnimationFrame callback');
t.done();
}));
}, 'AnimationPlayers preserve their startTime when changed');
}, 'Animations preserve their startTime when changed');
test(function(t) {
var div = addDiv(t);
div.style.animation = 'anim1 100s, anim1 100s';
// Store original state
var players = div.getAnimationPlayers();
var player1 = players[0];
var player2 = players[1];
var animations = div.getAnimations();
var animation1 = animations[0];
var animation2 = animations[1];
// Update first in list
div.style.animationDuration = '200s, 100s';
players = div.getAnimationPlayers();
assert_equals(players[0], player1,
'First player is in same position after update');
assert_equals(players[1], player2,
'Second player is in same position after update');
}, 'Updated AnimationPlayers maintain their order in the list');
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');
async_test(function(t) {
var div = addDiv(t);
div.style.animation = 'anim1 200s, anim1 100s';
// Store original state
var players = div.getAnimationPlayers();
var player1 = players[0];
var player2 = players[1];
var animations = div.getAnimations();
var animation1 = animations[0];
var animation2 = animations[1];
// Wait before continuing so we can compare start times (otherwise the
// new player objects and existing player objects will all have the same
// new Animation objects and existing Animation objects will all have the same
// start time).
waitForAllPlayers(players).then(waitForFrame).then(t.step_func(function() {
waitForAllAnimations(animations).then(waitForFrame).then(t.step_func(function() {
// Swap duration of first and second in list and prepend animation at the
// same time
div.style.animation = 'anim1 100s, anim1 100s, anim1 200s';
players = div.getAnimationPlayers();
assert_true(players[0] !== player1 && players[0] !== player2,
'New player is prepended to start of list');
assert_equals(players[1], player1,
'First player is in second position after update');
assert_equals(players[2], player2,
'Second player is in third position after update');
assert_equals(players[1].startTime, players[2].startTime,
'Old players have the same start time');
// TODO: Check that players[0].startTime === null
return players[0].ready;
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');
// TODO: Check that animations[0].startTime === null
return animations[0].ready;
})).then(t.step_func(function() {
assert_true(players[0].startTime > players[1].startTime,
'New player has later start time');
assert_true(animations[0].startTime > animations[1].startTime,
'New Animation has later start time');
t.done();
}));
}, 'Only the startTimes of existing animations are preserved');
@ -102,58 +102,58 @@ async_test(function(t) {
async_test(function(t) {
var div = addDiv(t);
div.style.animation = 'anim1 100s, anim1 100s';
var secondPlayer = div.getAnimationPlayers()[1];
var secondAnimation = div.getAnimations()[1];
// Wait before continuing so we can compare start times
secondPlayer.ready.then(waitForFrame).then(t.step_func(function() {
secondAnimation.ready.then(waitForFrame).then(t.step_func(function() {
// Trim list of animations
div.style.animationName = 'anim1';
var players = div.getAnimationPlayers();
assert_equals(players.length, 1, 'List of players was trimmed');
assert_equals(players[0], secondPlayer,
'Remaining player is the second one in the list');
assert_equals(typeof(players[0].startTime), 'number',
'Remaining player has resolved startTime');
assert_true(players[0].startTime < players[0].timeline.currentTime,
'Remaining player preserves startTime');
var 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_true(animations[0].startTime < animations[0].timeline.currentTime,
'Remaining Animation preserves startTime');
t.done();
}));
}, 'Animations are removed from the start of the list while preserving'
+ ' the state of existing players');
+ ' the state of existing Animations');
async_test(function(t) {
var div = addDiv(t);
div.style.animation = 'anim1 100s';
var firstAddedPlayer = div.getAnimationPlayers()[0],
secondAddedPlayer,
players;
var firstAddedAnimation = div.getAnimations()[0],
secondAddedAnimation,
animations;
// Wait and add second player
firstAddedPlayer.ready.then(waitForFrame).then(t.step_func(function() {
// Wait and add second Animation
firstAddedAnimation.ready.then(waitForFrame).then(t.step_func(function() {
div.style.animation = 'anim1 100s, anim1 100s';
secondAddedPlayer = div.getAnimationPlayers()[0];
secondAddedAnimation = div.getAnimations()[0];
// Wait again and add another player
return secondAddedPlayer.ready.then(waitForFrame);
// Wait again and add another Animation
return secondAddedAnimation.ready.then(waitForFrame);
})).then(t.step_func(function() {
div.style.animation = 'anim1 100s, anim2 100s, anim1 100s';
players = div.getAnimationPlayers();
assert_not_equals(firstAddedPlayer, secondAddedPlayer,
'New players are added to start of the list');
assert_equals(players[0], secondAddedPlayer,
'Second player remains in same position after'
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(players[2], firstAddedPlayer,
'First player remains in same position after'
assert_equals(animations[2], firstAddedAnimation,
'First Animation remains in same position after'
+ ' interleaving');
return players[1].ready;
return animations[1].ready;
})).then(t.step_func(function() {
assert_true(players[1].startTime > players[0].startTime,
'Interleaved player starts later than existing players');
assert_true(players[0].startTime > players[2].startTime,
'Original players retain their start time');
assert_true(animations[1].startTime > animations[0].startTime,
'Interleaved animation starts later than existing animations');
assert_true(animations[0].startTime > animations[2].startTime,
'Original animations retain their start time');
t.done();
}));
}, 'Player state is preserved when interleaving animations in list');
}, 'Animation state is preserved when interleaving animations in list');
</script>

View File

@ -21,21 +21,21 @@
test(function(t) {
var div = addDiv(t);
assert_equals(div.getAnimationPlayers().length, 0,
'getAnimationPlayers returns an empty sequence for an element'
assert_equals(div.getAnimations().length, 0,
'getAnimations returns an empty sequence for an element'
+ ' with no animations');
}, 'getAnimationPlayers for non-animated content');
}, 'getAnimations for non-animated content');
async_test(function(t) {
var div = addDiv(t);
// Add an animation
div.style.animation = 'anim1 100s';
var players = div.getAnimationPlayers();
assert_equals(players.length, 1,
'getAnimationPlayers returns a player running CSS Animations');
players[0].ready.then(t.step_func(function() {
var startTime = players[0].startTime;
var animations = div.getAnimations();
assert_equals(animations.length, 1,
'getAnimations returns an Animation running CSS Animations');
animations[0].ready.then(t.step_func(function() {
var startTime = animations[0].startTime;
assert_true(startTime > 0 && startTime <= document.timeline.currentTime,
'CSS animation has a sensible start time');
@ -46,31 +46,31 @@ async_test(function(t) {
return waitForFrame();
})).then(t.step_func(function() {
div.style.animation = 'anim1 100s, anim2 100s';
players = div.getAnimationPlayers();
assert_equals(players.length, 2,
'getAnimationPlayers returns one player for each value of'
animations = div.getAnimations();
assert_equals(animations.length, 2,
'getAnimations returns one Animation for each value of'
+ ' animation-name');
// Wait until both players are ready
// (We don't make any assumptions about the order of the players since
// Wait until both Animations are ready
// (We don't make any assumptions about the order of the Animations since
// that is the purpose of the following test.)
return waitForAllPlayers(players);
return waitForAllAnimations(animations);
})).then(t.step_func(function() {
assert_true(players[0].startTime < players[1].startTime,
'Additional players for CSS animations start after the original'
assert_true(animations[0].startTime < animations[1].startTime,
'Additional Animations for CSS animations start after the original'
+ ' animation and appear later in the list');
t.done();
}));
}, 'getAnimationPlayers for CSS Animations');
}, 'getAnimations for CSS Animations');
test(function(t) {
var div = addDiv(t);
// Add an animation that targets multiple properties
div.style.animation = 'multiPropAnim 100s';
assert_equals(div.getAnimationPlayers().length, 1,
'getAnimationPlayers returns only one player for a CSS Animation'
assert_equals(div.getAnimations().length, 1,
'getAnimations returns only one Animation for a CSS Animation'
+ ' that targets multiple properties');
}, 'getAnimationPlayers for multi-property animations');
}, 'getAnimations for multi-property animations');
async_test(function(t) {
var div = addDiv(t);
@ -81,173 +81,173 @@ async_test(function(t) {
window.getComputedStyle(div).backgroundColor;
// Wait until a frame after the animation starts, then add a transition
var players = div.getAnimationPlayers();
players[0].ready.then(waitForFrame).then(t.step_func(function() {
var animations = div.getAnimations();
animations[0].ready.then(waitForFrame).then(t.step_func(function() {
div.style.transition = 'all 100s';
div.style.backgroundColor = 'green';
players = div.getAnimationPlayers();
assert_equals(players.length, 2,
'getAnimationPlayers returns players for both animations and'
animations = div.getAnimations();
assert_equals(animations.length, 2,
'getAnimations returns Animations for both animations and'
+ ' transitions that run simultaneously');
return waitForAllPlayers(players);
return waitForAllAnimations(animations);
})).then(t.step_func(function() {
assert_true(players[0].startTime > players[1].startTime,
'players for transitions appear before animations even if they'
assert_true(animations[0].startTime > animations[1].startTime,
'Animations for transitions appear before animations even if they'
+ ' start later');
t.done();
}));
}, 'getAnimationPlayers for both CSS Animations and Transitions at once');
}, 'getAnimations for both CSS Animations and Transitions at once');
async_test(function(t) {
var div = addDiv(t);
// Set up event listener
div.addEventListener('animationend', t.step_func(function() {
assert_equals(div.getAnimationPlayers().length, 0,
'getAnimationPlayers does not return players for finished '
assert_equals(div.getAnimations().length, 0,
'getAnimations does not return Animations for finished '
+ ' (and non-forwards-filling) CSS Animations');
t.done();
}));
// Add a very short animation
div.style.animation = 'anim1 0.01s';
}, 'getAnimationPlayers for CSS Animations that have finished');
}, 'getAnimations for CSS Animations that have finished');
async_test(function(t) {
var div = addDiv(t);
// Set up event listener
div.addEventListener('animationend', t.step_func(function() {
assert_equals(div.getAnimationPlayers().length, 1,
'getAnimationPlayers returns players for CSS Animations that have'
assert_equals(div.getAnimations().length, 1,
'getAnimations returns Animations for CSS Animations that have'
+ ' finished but are filling forwards');
t.done();
}));
// Add a very short animation
div.style.animation = 'anim1 0.01s forwards';
}, 'getAnimationPlayers for CSS Animations that have finished but are'
}, 'getAnimations for CSS Animations that have finished but are'
+ ' forwards filling');
test(function(t) {
var div = addDiv(t);
div.style.animation = 'none 100s';
var players = div.getAnimationPlayers();
assert_equals(players.length, 0,
'getAnimationPlayers returns an empty sequence for an element'
var animations = div.getAnimations();
assert_equals(animations.length, 0,
'getAnimations returns an empty sequence for an element'
+ ' with animation-name: none');
div.style.animation = 'none 100s, anim1 100s';
players = div.getAnimationPlayers();
assert_equals(players.length, 1,
'getAnimationPlayers returns players only for those CSS Animations whose'
animations = div.getAnimations();
assert_equals(animations.length, 1,
'getAnimations returns Animations only for those CSS Animations whose'
+ ' animation-name is not none');
}, 'getAnimationPlayers for CSS Animations with animation-name: none');
}, 'getAnimations for CSS Animations with animation-name: none');
test(function(t) {
var div = addDiv(t);
div.style.animation = 'missing 100s';
var players = div.getAnimationPlayers();
assert_equals(players.length, 0,
'getAnimationPlayers returns an empty sequence for an element'
var animations = div.getAnimations();
assert_equals(animations.length, 0,
'getAnimations returns an empty sequence for an element'
+ ' with animation-name: missing');
div.style.animation = 'anim1 100s, missing 100s';
players = div.getAnimationPlayers();
assert_equals(players.length, 1,
'getAnimationPlayers returns players only for those CSS Animations whose'
animations = div.getAnimations();
assert_equals(animations.length, 1,
'getAnimations returns Animations only for those CSS Animations whose'
+ ' animation-name is found');
}, 'getAnimationPlayers for CSS Animations with animation-name: missing');
}, 'getAnimations for CSS Animations with animation-name: missing');
async_test(function(t) {
var div = addDiv(t);
div.style.animation = 'anim1 100s, notyet 100s';
var players = div.getAnimationPlayers();
assert_equals(players.length, 1,
'getAnimationPlayers initally only returns players for CSS Animations whose'
var animations = div.getAnimations();
assert_equals(animations.length, 1,
'getAnimations initally only returns Animations for CSS Animations whose'
+ ' animation-name is found');
players[0].ready.then(waitForFrame).then(t.step_func(function() {
animations[0].ready.then(waitForFrame).then(t.step_func(function() {
var keyframes = '@keyframes notyet { to { left: 100px; } }';
document.styleSheets[0].insertRule(keyframes, 0);
players = div.getAnimationPlayers();
assert_equals(players.length, 2,
'getAnimationPlayers includes player when @keyframes rule is added'
animations = div.getAnimations();
assert_equals(animations.length, 2,
'getAnimations includes Animation when @keyframes rule is added'
+ ' later');
return waitForAllPlayers(players);
return waitForAllAnimations(animations);
})).then(t.step_func(function() {
assert_true(players[0].startTime < players[1].startTime,
'Newly added player has a later start time');
assert_true(animations[0].startTime < animations[1].startTime,
'Newly added animation has a later start time');
document.styleSheets[0].deleteRule(0);
t.done();
}));
}, 'getAnimationPlayers for CSS Animations where the @keyframes rule is added'
}, 'getAnimations for CSS Animations where the @keyframes rule is added'
+ ' later');
test(function(t) {
var div = addDiv(t);
div.style.animation = 'anim1 100s, anim1 100s';
assert_equals(div.getAnimationPlayers().length, 2,
'getAnimationPlayers returns one player for each CSS animation-name'
assert_equals(div.getAnimations().length, 2,
'getAnimations returns one Animation for each CSS animation-name'
+ ' even if the names are duplicated');
}, 'getAnimationPlayers for CSS Animations with duplicated animation-name');
}, 'getAnimations for CSS Animations with duplicated animation-name');
test(function(t) {
var div = addDiv(t);
div.style.animation = 'empty 100s';
assert_equals(div.getAnimationPlayers().length, 1,
'getAnimationPlayers returns players for CSS animations with an'
assert_equals(div.getAnimations().length, 1,
'getAnimations returns Animations for CSS animations with an'
+ ' empty keyframes rule');
}, 'getAnimationPlayers for CSS Animations with empty keyframes rule');
}, 'getAnimations for CSS Animations with empty keyframes rule');
async_test(function(t) {
var div = addDiv(t);
div.style.animation = 'anim1 100s 100s';
var players = div.getAnimationPlayers();
assert_equals(players.length, 1,
'getAnimationPlayers returns animations for CSS animations whose'
var animations = div.getAnimations();
assert_equals(animations.length, 1,
'getAnimations returns animations for CSS animations whose'
+ ' delay makes them start later');
players[0].ready.then(waitForFrame).then(t.step_func(function() {
assert_true(players[0].startTime <= document.timeline.currentTime,
'For CSS Animations in delay phase, the start time of the player is'
animations[0].ready.then(waitForFrame).then(t.step_func(function() {
assert_true(animations[0].startTime <= document.timeline.currentTime,
'For CSS Animations in delay phase, the start time of the Animation is'
+ ' not in the future');
t.done();
}));
}, 'getAnimationPlayers for CSS animations in delay phase');
}, 'getAnimations for CSS animations in delay phase');
test(function(t) {
var div = addDiv(t);
div.style.animation = 'anim1 0s 100s';
assert_equals(div.getAnimationPlayers().length, 1,
'getAnimationPlayers returns animations for CSS animations whose'
assert_equals(div.getAnimations().length, 1,
'getAnimations returns animations for CSS animations whose'
+ ' duration is zero');
div.remove();
}, 'getAnimationPlayers for zero-duration CSS Animations');
}, 'getAnimations for zero-duration CSS Animations');
test(function(t) {
var div = addDiv(t);
div.style.animation = 'anim1 100s';
var originalPlayer = div.getAnimationPlayers()[0];
var originalAnimation = div.getAnimations()[0];
// Update pause state (an AnimationPlayer change)
// Update pause state (an Animation change)
div.style.animationPlayState = 'paused';
var pausedPlayer = div.getAnimationPlayers()[0];
assert_equals(pausedPlayer.playState, 'paused',
'player\'s paused state is updated');
assert_equals(originalPlayer, pausedPlayer,
'getAnimationPlayers returns the same objects even when their'
var pausedAnimation = div.getAnimations()[0];
assert_equals(pausedAnimation.playState, 'paused',
'animation\'s paused state is updated');
assert_equals(originalAnimation, pausedAnimation,
'getAnimations returns the same objects even when their'
+ ' play state changes');
// Update duration (an Animation change)
div.style.animationDuration = '200s';
var extendedPlayer = div.getAnimationPlayers()[0];
// FIXME: Check extendedPlayer.source.timing.duration has changed once the
var extendedAnimation = div.getAnimations()[0];
// FIXME: Check extendedAnimation.source.timing.duration has changed once the
// API is available
assert_equals(originalPlayer, extendedPlayer,
'getAnimationPlayers returns the same objects even when their'
assert_equals(originalAnimation, extendedAnimation,
'getAnimations returns the same objects even when their'
+ ' duration changes');
}, 'getAnimationPlayers returns objects with the same identity');
}, 'getAnimations returns objects with the same identity');
</script>

View File

@ -16,7 +16,7 @@ test(function(t) {
div.style.transition = 'all 100s';
div.style.left = '100px';
assert_equals(div.getAnimationPlayers()[0].source.effect.name, '',
assert_equals(div.getAnimations()[0].source.effect.name, '',
'Animation effects for transitions have an empty name');
}, 'Effect name for transitions');

View File

@ -21,23 +21,23 @@ async_test(function(t) {
div.style.marginLeft = '10000px';
cs.marginLeft;
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
assert_equals(getMarginLeft(cs), 0,
'Initial value of margin-left is zero');
var previousAnimVal = getMarginLeft(cs);
player.ready.then(waitForFrame).then(t.step_func(function() {
animation.ready.then(waitForFrame).then(t.step_func(function() {
assert_true(getMarginLeft(cs) > previousAnimVal,
'margin-left is initially increasing');
previousAnimVal = getMarginLeft(cs);
player.pause();
animation.pause();
return waitForFrame();
})).then(t.step_func(function() {
assert_equals(getMarginLeft(cs), previousAnimVal,
'margin-left does not increase after calling pause()');
previousAnimVal = getMarginLeft(cs);
player.play();
return player.ready.then(waitForFrame);
animation.play();
return animation.ready.then(waitForFrame);
})).then(t.step_func(function() {
assert_true(getMarginLeft(cs) > previousAnimVal,
'margin-left increases after calling play()');

View File

@ -15,19 +15,19 @@ async_test(function(t) {
div.style.transform = 'translate(10px)';
window.getComputedStyle(div).transform;
var player = div.getAnimationPlayers()[0];
var originalReadyPromise = player.ready;
var animation = div.getAnimations()[0];
var originalReadyPromise = animation.ready;
player.ready.then(t.step_func(function() {
assert_equals(player.ready, originalReadyPromise,
animation.ready.then(t.step_func(function() {
assert_equals(animation.ready, originalReadyPromise,
'Ready promise is the same object when playing completes');
player.pause();
animation.pause();
// TODO: When we implement deferred pausing, change this to
// assert_not_equals and wait on the new promise before continuing.
assert_equals(player.ready, originalReadyPromise,
assert_equals(animation.ready, originalReadyPromise,
'Ready promise does not change when pausing (for now)');
player.play();
assert_not_equals(player.ready, originalReadyPromise,
animation.play();
assert_not_equals(animation.ready, originalReadyPromise,
'Ready promise object identity differs after calling'
+ ' play()');
t.done();
@ -45,17 +45,17 @@ async_test(function(t) {
div.style.transform = 'translate(10px)';
window.getComputedStyle(div).transform;
var player = div.getAnimationPlayers()[0];
assert_equals(player.playState, 'pending', 'Player is initially pending');
var animation = div.getAnimations()[0];
assert_equals(animation.playState, 'pending', 'Animation is initially pending');
// Set up listeners on ready promise
player.ready.then(t.step_func(function() {
animation.ready.then(t.step_func(function() {
assert_unreached('ready promise was fulfilled');
})).catch(t.step_func(function(err) {
assert_equals(err.name, 'AbortError',
'ready promise is rejected with AbortError');
assert_equals(player.playState, 'idle',
'Player is idle after transition was cancelled');
assert_equals(animation.playState, 'idle',
'Animation is idle after transition was cancelled');
})).then(t.step_func(function() {
t.done();
}));
@ -77,17 +77,17 @@ async_test(function(t) {
div.style.marginLeft = '100px';
window.getComputedStyle(div).marginLeft;
var player = div.getAnimationPlayers()[0];
assert_equals(player.playState, 'pending', 'Player is initially pending');
var animation = div.getAnimations()[0];
assert_equals(animation.playState, 'pending', 'Animation is initially pending');
// Set up listeners on ready promise
player.ready.then(t.step_func(function() {
animation.ready.then(t.step_func(function() {
assert_unreached('ready promise was fulfilled');
})).catch(t.step_func(function(err) {
assert_equals(err.name, 'AbortError',
'ready promise is rejected with AbortError');
assert_equals(player.playState, 'idle',
'Player is idle after transition was cancelled');
assert_equals(animation.playState, 'idle',
'Animation is idle after transition was cancelled');
})).then(t.step_func(function() {
t.done();
}));

View File

@ -3,7 +3,7 @@
<head>
<meta charset=utf-8>
<title>Tests for the effect of setting a CSS transition's
AnimationPlayer.startTime</title>
Animation.startTime</title>
<style>
.animated-div {
@ -191,17 +191,17 @@ function EventWatcher(watchedNode, eventTypes)
// active interval. (If there is no delay, they are the same.)
// Called when the ready Promise's callbacks should happen
function checkStateOnReadyPromiseResolved(player)
function checkStateOnReadyPromiseResolved(animation)
{
assert_less_than_equal(player.startTime, player.timeline.currentTime,
'AnimationPlayer.startTime should be less than the timeline\'s ' +
assert_less_than_equal(animation.startTime, animation.timeline.currentTime,
'Animation.startTime should be less than the timeline\'s ' +
'currentTime on the first paint tick after animation creation');
assert_equals(player.playState, 'running',
'AnimationPlayer.playState should be "running" on the first paint ' +
assert_equals(animation.playState, 'running',
'Animation.playState should be "running" on the first paint ' +
'tick after animation creation');
var div = player.source.target;
var div = animation.source.target;
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
assert_equals(marginLeft, INITIAL_POSITION,
'the computed value of margin-left should be unaffected ' +
@ -209,26 +209,26 @@ function checkStateOnReadyPromiseResolved(player)
}
// Called when startTime is set to the time the active interval starts.
function checkStateAtActiveIntervalStartTime(player)
function checkStateAtActiveIntervalStartTime(animation)
{
// We don't test player.startTime since our caller just set it.
// We don't test animation.startTime since our caller just set it.
assert_equals(player.playState, 'running',
'AnimationPlayer.playState should be "running" at the start of ' +
assert_equals(animation.playState, 'running',
'Animation.playState should be "running" at the start of ' +
'the active interval');
var div = player.source.target;
var div = animation.source.target;
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
assert_between_inclusive(marginLeft, INITIAL_POSITION, TEN_PCT_POSITION,
'the computed value of margin-left should be close to the value at the ' +
'beginning of the animation');
}
function checkStateAtFiftyPctOfActiveInterval(player)
function checkStateAtFiftyPctOfActiveInterval(animation)
{
// We don't test player.startTime since our caller just set it.
// We don't test animation.startTime since our caller just set it.
var div = player.source.target;
var div = animation.source.target;
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
assert_equals(marginLeft, FIFTY_PCT_POSITION,
'the computed value of margin-left should be half way through the ' +
@ -236,15 +236,15 @@ function checkStateAtFiftyPctOfActiveInterval(player)
}
// Called when startTime is set to the time the active interval ends.
function checkStateAtActiveIntervalEndTime(player)
function checkStateAtActiveIntervalEndTime(animation)
{
// We don't test player.startTime since our caller just set it.
// We don't test animation.startTime since our caller just set it.
assert_equals(player.playState, 'finished',
'AnimationPlayer.playState should be "finished" at the end of ' +
assert_equals(animation.playState, 'finished',
'Animation.playState should be "finished" at the end of ' +
'the active interval');
var div = player.source.target;
var div = animation.source.target;
var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
assert_equals(marginLeft, END_POSITION,
'the computed value of margin-left should be the final transitioned-to ' +
@ -257,8 +257,8 @@ test(function(t)
flushComputedStyle(div);
div.style.marginLeft = '200px'; // initiate transition
var player = div.getAnimationPlayers()[0];
assert_equals(player.startTime, null, 'startTime is unresolved');
var animation = div.getAnimations()[0];
assert_equals(animation.startTime, null, 'startTime is unresolved');
}, 'startTime of a newly created transition is unresolved');
@ -268,10 +268,10 @@ test(function(t)
flushComputedStyle(div);
div.style.marginLeft = '200px'; // initiate transition
var player = div.getAnimationPlayers()[0];
var currentTime = player.timeline.currentTime;
player.startTime = currentTime;
assert_approx_equals(player.startTime, currentTime, 0.0001, // rounding error
var animation = div.getAnimations()[0];
var currentTime = animation.timeline.currentTime;
animation.startTime = currentTime;
assert_approx_equals(animation.startTime, currentTime, 0.0001, // rounding error
'Check setting of startTime actually works');
}, 'Sanity test to check round-tripping assigning to new animation\'s ' +
'startTime');
@ -284,22 +284,22 @@ async_test(function(t) {
flushComputedStyle(div);
div.style.marginLeft = '200px'; // initiate transition
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
player.ready.then(t.step_func(function() {
checkStateOnReadyPromiseResolved(player);
animation.ready.then(t.step_func(function() {
checkStateOnReadyPromiseResolved(animation);
player.startTime = startTimeForStartOfActiveInterval(player.timeline);
checkStateAtActiveIntervalStartTime(player);
animation.startTime = startTimeForStartOfActiveInterval(animation.timeline);
checkStateAtActiveIntervalStartTime(animation);
player.startTime =
startTimeForFiftyPercentThroughActiveInterval(player.timeline);
checkStateAtFiftyPctOfActiveInterval(player);
animation.startTime =
startTimeForFiftyPercentThroughActiveInterval(animation.timeline);
checkStateAtFiftyPctOfActiveInterval(animation);
player.startTime = startTimeForEndOfActiveInterval(player.timeline);
animation.startTime = startTimeForEndOfActiveInterval(animation.timeline);
return eventWatcher.waitForEvent('transitionend');
})).then(t.step_func(function() {
checkStateAtActiveIntervalEndTime(player);
checkStateAtActiveIntervalEndTime(animation);
eventWatcher.stopWatching();
})).catch(t.step_func(function(reason) {
@ -317,17 +317,18 @@ test(function(t) {
flushComputedStyle(div);
div.style.marginLeft = '200px'; // initiate transition
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
// Unlike in the case of CSS animations, we cannot skip to the end and skip
// backwards since when we reach the end the transition effect is removed and
// changes to the AnimationPlayer object no longer affect the element. For
// changes to the Animation object no longer affect the element. For
// this reason we only skip forwards as far as the 90% through point.
player.startTime = startTimeForFiftyPercentThroughActiveInterval(player.timeline);
checkStateAtFiftyPctOfActiveInterval(player);
animation.startTime =
startTimeForFiftyPercentThroughActiveInterval(animation.timeline);
checkStateAtFiftyPctOfActiveInterval(animation);
player.startTime = startTimeForStartOfActiveInterval(player.timeline);
animation.startTime = startTimeForStartOfActiveInterval(animation.timeline);
// Despite going backwards from being in the active interval to being before
// it, we now expect an 'animationend' event because the animation should go
@ -341,7 +342,7 @@ test(function(t) {
eventWatcher.stopWatching();
t.done();
});
checkStateAtActiveIntervalStartTime(player);
checkStateAtActiveIntervalStartTime(animation);
}, 'Skipping backwards through transition');
@ -351,18 +352,18 @@ async_test(function(t) {
flushComputedStyle(div);
div.style.marginLeft = '200px'; // initiate transition
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
var storedCurrentTime;
player.ready.then(t.step_func(function() {
storedCurrentTime = player.currentTime;
player.startTime = null;
return player.ready;
animation.ready.then(t.step_func(function() {
storedCurrentTime = animation.currentTime;
animation.startTime = null;
return animation.ready;
})).catch(t.step_func(function(reason) {
assert_unreached(reason);
})).then(function() {
assert_equals(player.currentTime, storedCurrentTime,
assert_equals(animation.currentTime, storedCurrentTime,
'Test that hold time is correct');
t.done();
});
@ -375,27 +376,27 @@ async_test(function(t) {
flushComputedStyle(div);
div.style.marginLeft = '200px'; // initiate transition
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
player.ready.then(t.step_func(function() {
var savedStartTime = player.startTime;
animation.ready.then(t.step_func(function() {
var savedStartTime = animation.startTime;
assert_not_equals(player.startTime, null,
'AnimationPlayer.startTime not null on ready Promise resolve');
assert_not_equals(animation.startTime, null,
'Animation.startTime not null on ready Promise resolve');
player.pause();
return player.ready;
animation.pause();
return animation.ready;
})).then(t.step_func(function() {
assert_equals(player.startTime, null,
'AnimationPlayer.startTime is null after paused');
assert_equals(player.playState, 'paused',
'AnimationPlayer.playState is "paused" after pause() call');
assert_equals(animation.startTime, null,
'Animation.startTime is null after paused');
assert_equals(animation.playState, 'paused',
'Animation.playState is "paused" after pause() call');
})).catch(t.step_func(function(reason) {
assert_unreached(reason);
})).then(function() {
t.done();
});
}, 'AnimationPlayer.startTime after paused');
}, 'Animation.startTime after paused');
</script>
</body>

View File

@ -15,8 +15,8 @@ test(function(t) {
div.style.transition = 'left 100s';
div.style.left = '100px';
var players = div.getAnimationPlayers();
assert_equals(players[0].source.target, div,
var animation = div.getAnimations()[0];
assert_equals(animation.source.target, div,
'Animation.target is the animatable div');
}, 'Returned CSS transitions have the correct Animation.target');

View File

@ -19,38 +19,38 @@ async_test(function(t) {
div.style.left = '100px';
div.style.top = '100px';
var players = div.getAnimationPlayers();
assert_equals(players.length, 2,
'getAnimationPlayers() returns one player per transitioning property');
waitForAllPlayers(players).then(t.step_func(function() {
var startTime = players[0].startTime;
var animations = div.getAnimations();
assert_equals(animations.length, 2,
'getAnimations() returns one Animation per transitioning property');
waitForAllAnimations(animations).then(t.step_func(function() {
var startTime = animations[0].startTime;
assert_true(startTime > 0 && startTime <= document.timeline.currentTime,
'CSS transitions have sensible start times');
assert_equals(players[0].startTime, players[1].startTime,
assert_equals(animations[0].startTime, animations[1].startTime,
'CSS transitions started together have the same start time');
// Wait a moment then add a third transition
return waitForFrame();
})).then(t.step_func(function() {
div.style.backgroundColor = 'green';
players = div.getAnimationPlayers();
assert_equals(players.length, 3,
'getAnimationPlayers returns players for all running CSS Transitions');
return waitForAllPlayers(players);
animations = div.getAnimations();
assert_equals(animations.length, 3,
'getAnimations returns Animations for all running CSS Transitions');
return waitForAllAnimations(animations);
})).then(t.step_func(function() {
assert_true(players[1].startTime < players[2].startTime,
'Player for additional CSS transition starts after the original'
assert_true(animations[1].startTime < animations[2].startTime,
'Animation for additional CSS transition starts after the original'
+ ' transitions and appears later in the list');
t.done();
}));
}, 'getAnimationPlayers for CSS Transitions');
}, 'getAnimations for CSS Transitions');
async_test(function(t) {
var div = addDiv(t);
// Set up event listener
div.addEventListener('transitionend', t.step_func(function() {
assert_equals(div.getAnimationPlayers().length, 0,
'getAnimationPlayers does not return finished CSS Transitions');
assert_equals(div.getAnimations().length, 0,
'getAnimations does not return finished CSS Transitions');
t.done();
}));
@ -61,7 +61,7 @@ async_test(function(t) {
div.style.transition = 'all 0.01s';
div.style.left = '100px';
window.getComputedStyle(div).left;
}, 'getAnimationPlayers for CSS Transitions that have finished');
}, 'getAnimations for CSS Transitions that have finished');
test(function(t) {
var div = addDiv(t);
@ -73,10 +73,10 @@ test(function(t) {
div.style.transition = 'all 100s';
div.style.animationDuration = '100s';
assert_equals(div.getAnimationPlayers().length, 0,
'getAnimationPlayers returns an empty sequence for a transition'
assert_equals(div.getAnimations().length, 0,
'getAnimations returns an empty sequence for a transition'
+ ' of a non-animatable property');
}, 'getAnimationPlayers for transition on non-animatable property');
}, 'getAnimations for transition on non-animatable property');
test(function(t) {
var div = addDiv(t);
@ -86,9 +86,9 @@ test(function(t) {
div.style.transition = 'all 100s';
div.style.setProperty('-vendor-unsupported', '100px', '');
assert_equals(div.getAnimationPlayers().length, 0,
'getAnimationPlayers returns an empty sequence for a transition'
assert_equals(div.getAnimations().length, 0,
'getAnimations returns an empty sequence for a transition'
+ ' of an unsupported property');
}, 'getAnimationPlayers for transition on unsupported property');
}, 'getAnimations for transition on unsupported property');
</script>

View File

@ -52,9 +52,9 @@ async_test(function(t) {
var promiseCallbackDone = false;
waitForDocLoad().then(function() {
div.style.animation = 'empty 1000s';
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
player.ready.then(function() {
animation.ready.then(function() {
promiseCallbackDone = true;
}).catch(function() {
assert_unreached('ready promise was rejected');
@ -74,7 +74,7 @@ async_test(function(t) {
+ ' within three animation frames');
t.done();
}));
}, 'AnimationPlayer.ready is resolved for an empty animation');
}, 'Animation.ready is resolved for an empty animation');
// Test that compositor animations with delays get synced correctly
//
@ -95,9 +95,9 @@ async_test(function(t) {
var div = addDiv(t);
div.classList.add('target');
div.style.animation = 'animTransform 100s -50s forwards';
var player = div.getAnimationPlayers()[0];
var animation = div.getAnimations()[0];
player.ready.then(t.step_func(function() {
animation.ready.then(t.step_func(function() {
var transformStr =
SpecialPowers.DOMWindowUtils.getOMTAStyle(div, 'transform');

View File

@ -39,12 +39,14 @@ function waitForFrame() {
}
/**
* Wrapper that takes a sequence of N players and returns:
* Wrapper that takes a sequence of N animations and returns:
*
* Promise.all([players[0].ready, players[1].ready, ... players[N-1].ready]);
* Promise.all([animations[0].ready, animations[1].ready, ... animations[N-1].ready]);
*/
function waitForAllPlayers(players) {
return Promise.all(players.map(function(player) { return player.ready; }));
function waitForAllAnimations(animations) {
return Promise.all(animations.map(function(animation) {
return animation.ready;
}));
}
/**