зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1416693 - Make animation test cases that don't require asynchronous. r=boris
Below list is animation test cases remain in test_animation_observers_async.html * single_animation : waiting for animationend event * single_animation_cancelled_fill : waiting for animaitonend event * tree_ordering : waiting for animationend event * coalesce_change_cancel : testing a non-cancelling change to an animation followed immediately by a cancelling change sends only one removal notification, I am concerned that adding explicit style flush (e.g. getComputedstyle) might change the test purpose. * play : redundant play() seems to be affected by asynchronous. I haven't dug into detail. * finish_from_pause : waiting for Animation.ready to make sure pause pending state to finish. MozReview-Commit-ID: HAelOTwSqgv --HG-- extra : rebase_source : 819e8975028f62580dccd07fedc53d250b71f97a
This commit is contained in:
Родитель
70ec3f1b1b
Коммит
49e012c030
|
@ -272,99 +272,6 @@ function assert_records_any_order(expected, desc) {
|
||||||
e.style = "";
|
e.style = "";
|
||||||
});
|
});
|
||||||
|
|
||||||
// Test that starting a single animation that is cancelled by resetting
|
|
||||||
// the animation-name property dispatches an added notification and
|
|
||||||
// then a removed notification.
|
|
||||||
addAsyncAnimTest("single_animation_cancelled_name", aOptions, function*() {
|
|
||||||
// Start a long animation.
|
|
||||||
e.style = "animation: anim 100s;";
|
|
||||||
|
|
||||||
// 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 Animation addition to
|
|
||||||
// be delivered.
|
|
||||||
yield waitForFrame();
|
|
||||||
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 Animation removal to
|
|
||||||
// be delivered.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: [], changed: [], removed: animations }],
|
|
||||||
"records after animation end");
|
|
||||||
|
|
||||||
e.style = "";
|
|
||||||
});
|
|
||||||
|
|
||||||
// Test that starting a single animation that is cancelled by updating
|
|
||||||
// the animation-duration property dispatches an added notification and
|
|
||||||
// then a removed notification.
|
|
||||||
addAsyncAnimTest("single_animation_cancelled_duration", aOptions, function*() {
|
|
||||||
// Start a long animation.
|
|
||||||
e.style = "animation: anim 100s;";
|
|
||||||
|
|
||||||
// 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 Animation addition to
|
|
||||||
// be delivered.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: animations, changed: [], removed: [] }],
|
|
||||||
"records after animation start");
|
|
||||||
|
|
||||||
// Advance the animation by a second.
|
|
||||||
animations[0].currentTime += 1 * MS_PER_SEC;
|
|
||||||
|
|
||||||
// Cancel the animation by setting animation-duration to a value less
|
|
||||||
// than a second.
|
|
||||||
e.style.animationDuration = "0.1s";
|
|
||||||
|
|
||||||
// Wait for the change MutationRecord from seeking the Animation to
|
|
||||||
// be delivered, followed by a further MutationRecord for the Animation
|
|
||||||
// removal.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: [], changed: animations, removed: [] },
|
|
||||||
{ added: [], changed: [], removed: animations }],
|
|
||||||
"records after animation end");
|
|
||||||
|
|
||||||
e.style = "";
|
|
||||||
});
|
|
||||||
|
|
||||||
// Test that starting a single animation that is cancelled by updating
|
|
||||||
// the animation-delay property dispatches an added notification and
|
|
||||||
// then a removed notification.
|
|
||||||
addAsyncAnimTest("single_animation_cancelled_delay", aOptions, function*() {
|
|
||||||
// Start a long animation.
|
|
||||||
e.style = "animation: anim 100s;";
|
|
||||||
|
|
||||||
// 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 Animation addition to
|
|
||||||
// be delivered.
|
|
||||||
yield waitForFrame();
|
|
||||||
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 Animation removal to
|
|
||||||
// be delivered.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: [], changed: [], removed: animations }],
|
|
||||||
"records after animation end");
|
|
||||||
|
|
||||||
e.style = "";
|
|
||||||
});
|
|
||||||
|
|
||||||
// Test that starting a single animation that is cancelled by updating
|
// Test that starting a single animation that is cancelled by updating
|
||||||
// the animation-fill-mode property dispatches an added notification and
|
// the animation-fill-mode property dispatches an added notification and
|
||||||
// then a removed notification.
|
// then a removed notification.
|
||||||
|
@ -412,90 +319,6 @@ function assert_records_any_order(expected, desc) {
|
||||||
e.style = "";
|
e.style = "";
|
||||||
});
|
});
|
||||||
|
|
||||||
// Test that starting a single animation that is cancelled by updating
|
|
||||||
// the animation-iteration-count property dispatches an added notification
|
|
||||||
// and then a removed notification.
|
|
||||||
addAsyncAnimTest("single_animation_cancelled_iteration_count",
|
|
||||||
aOptions, function*() {
|
|
||||||
// Start a short, repeated animation.
|
|
||||||
e.style = "animation: anim 0.5s infinite;";
|
|
||||||
|
|
||||||
// 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 Animation addition to
|
|
||||||
// be delivered.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: animations, changed: [], removed: [] }],
|
|
||||||
"records after animation start");
|
|
||||||
|
|
||||||
// Advance the animation until we are past the first iteration.
|
|
||||||
animations[0].currentTime += 1 * MS_PER_SEC;
|
|
||||||
|
|
||||||
// The only MutationRecord at this point should be the change from
|
|
||||||
// seeking the Animation.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: [], changed: animations, removed: [] }],
|
|
||||||
"records after seeking animations");
|
|
||||||
|
|
||||||
// Cancel the animation by setting animation-iteration-count.
|
|
||||||
e.style.animationIterationCount = "1";
|
|
||||||
|
|
||||||
// Wait for the single MutationRecord for the Animation removal to
|
|
||||||
// be delivered.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: [], changed: [], removed: animations }],
|
|
||||||
"records after animation end");
|
|
||||||
|
|
||||||
e.style = "";
|
|
||||||
});
|
|
||||||
|
|
||||||
// Test that updating an animation property dispatches a changed notification.
|
|
||||||
[
|
|
||||||
{ name: "duration", prop: "animationDuration", val: "200s" },
|
|
||||||
{ name: "timing", prop: "animationTimingFunction", val: "linear" },
|
|
||||||
{ name: "iteration", prop: "animationIterationCount", val: "2" },
|
|
||||||
{ name: "direction", prop: "animationDirection", val: "reverse" },
|
|
||||||
{ name: "state", prop: "animationPlayState", val: "paused" },
|
|
||||||
{ name: "delay", prop: "animationDelay", val: "-1s" },
|
|
||||||
{ name: "fill", prop: "animationFillMode", val: "both" },
|
|
||||||
].forEach(aChangeTest => {
|
|
||||||
addAsyncAnimTest(`single_animation_change_${aChangeTest.name}`, aOptions, function*() {
|
|
||||||
// Start a long animation.
|
|
||||||
e.style = "animation: anim 100s;";
|
|
||||||
|
|
||||||
// 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 Animation addition to
|
|
||||||
// be delivered.
|
|
||||||
yield waitForFrame();
|
|
||||||
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 Animation change to
|
|
||||||
// be delivered.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: [], changed: animations, removed: [] }],
|
|
||||||
"records after animation change");
|
|
||||||
|
|
||||||
// Cancel the animation.
|
|
||||||
e.style.animationName = "none";
|
|
||||||
|
|
||||||
// Wait for the addition, change and removal MutationRecords to be delivered.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: [], changed: [], removed: animations }],
|
|
||||||
"records after animation end");
|
|
||||||
|
|
||||||
e.style = "";
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Test that calling finish() on a paused (but otherwise finished) animation
|
// Test that calling finish() on a paused (but otherwise finished) animation
|
||||||
// dispatches a changed notification.
|
// dispatches a changed notification.
|
||||||
addAsyncAnimTest("finish_from_pause", aOptions, function*() {
|
addAsyncAnimTest("finish_from_pause", aOptions, function*() {
|
||||||
|
@ -551,53 +374,6 @@ function assert_records_any_order(expected, desc) {
|
||||||
"records after animation end");
|
"records after animation end");
|
||||||
});
|
});
|
||||||
|
|
||||||
// Test that calling finish() on a pause-pending (but otherwise finished)
|
|
||||||
// animation dispatches a changed notification.
|
|
||||||
addAsyncAnimTest("finish_from_pause_pending", aOptions, function*() {
|
|
||||||
// Start a long animation
|
|
||||||
e.style = "animation: anim 100s forwards";
|
|
||||||
|
|
||||||
// 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 Animation addition to
|
|
||||||
// be delivered.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: animations, changed: [], removed: [] }],
|
|
||||||
"records after animation start");
|
|
||||||
|
|
||||||
// Wait until the animation is playing.
|
|
||||||
yield animations[0].ready;
|
|
||||||
|
|
||||||
// Finish and pause.
|
|
||||||
animations[0].finish();
|
|
||||||
animations[0].pause();
|
|
||||||
is(animations[0].playState, "paused",
|
|
||||||
"playState after finishing and calling pause()");
|
|
||||||
|
|
||||||
// Call finish() again to abort the pause
|
|
||||||
animations[0].finish();
|
|
||||||
is(animations[0].playState, "finished",
|
|
||||||
"playState after finishing again");
|
|
||||||
|
|
||||||
// Wait for three MutationRecords for the Animation changes to
|
|
||||||
// be delivered: one for each finish(), pause(), finish() operation.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: [], changed: animations, removed: [] },
|
|
||||||
{ added: [], changed: animations, removed: [] },
|
|
||||||
{ added: [], changed: animations, removed: [] }],
|
|
||||||
"records after finish(), pause(), finish()");
|
|
||||||
|
|
||||||
// Cancel the animation.
|
|
||||||
e.style = "";
|
|
||||||
|
|
||||||
// Wait for the single removal notification.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: [], changed: [], removed: animations }],
|
|
||||||
"records after animation end");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Test that calling play() on a paused Animation dispatches a changed
|
// Test that calling play() on a paused Animation dispatches a changed
|
||||||
// notification.
|
// notification.
|
||||||
addAsyncAnimTest("play", aOptions, function*() {
|
addAsyncAnimTest("play", aOptions, function*() {
|
||||||
|
@ -642,233 +418,6 @@ function assert_records_any_order(expected, desc) {
|
||||||
"records after animation end");
|
"records after animation end");
|
||||||
});
|
});
|
||||||
|
|
||||||
// Test that calling play() on a finished Animation that fills forwards
|
|
||||||
// dispatches a changed notification.
|
|
||||||
addAsyncAnimTest("play_filling_forwards", aOptions, function*() {
|
|
||||||
// Start a long animation with a forwards fill
|
|
||||||
e.style = "animation: anim 100s forwards";
|
|
||||||
|
|
||||||
// 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 Animation addition to
|
|
||||||
// be delivered.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: animations, changed: [], removed: [] }],
|
|
||||||
"records after animation start");
|
|
||||||
|
|
||||||
// Wait until the animation is ready
|
|
||||||
yield animations[0].ready;
|
|
||||||
|
|
||||||
// Seek to the end
|
|
||||||
animations[0].finish();
|
|
||||||
|
|
||||||
// Wait for the single MutationRecord for the Animation change to
|
|
||||||
// be delivered.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: [], changed: animations, removed: [] }],
|
|
||||||
"records after finish()");
|
|
||||||
|
|
||||||
// Since we are filling forwards, calling play() should produce a
|
|
||||||
// change record since the animation remains relevant.
|
|
||||||
animations[0].play();
|
|
||||||
|
|
||||||
// Wait for the single MutationRecord for the Animation change to
|
|
||||||
// be delivered.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: [], changed: animations, removed: [] }],
|
|
||||||
"records after play()");
|
|
||||||
|
|
||||||
// Cancel the animation.
|
|
||||||
e.style = "";
|
|
||||||
|
|
||||||
// Wait for the single removal notification.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: [], changed: [], removed: animations }],
|
|
||||||
"records after animation end");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Test that calling play() on a finished Animation that does *not* fill
|
|
||||||
// forwards dispatches an addition notification.
|
|
||||||
addAsyncAnimTest("play_after_finish", aOptions, function*() {
|
|
||||||
// Start a long animation
|
|
||||||
e.style = "animation: anim 100s";
|
|
||||||
|
|
||||||
// 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 Animation addition to
|
|
||||||
// be delivered.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: animations, changed: [], removed: [] }],
|
|
||||||
"records after animation start");
|
|
||||||
|
|
||||||
// Wait until the animation is ready
|
|
||||||
yield animations[0].ready;
|
|
||||||
|
|
||||||
// Seek to the end
|
|
||||||
animations[0].finish();
|
|
||||||
|
|
||||||
// Wait for the single MutationRecord for the Animation removal to
|
|
||||||
// be delivered.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: [], changed: [], removed: animations }],
|
|
||||||
"records after finish()");
|
|
||||||
|
|
||||||
// Since we are *not* filling forwards, calling play() is equivalent
|
|
||||||
// to creating a new animation since it becomes relevant again.
|
|
||||||
animations[0].play();
|
|
||||||
|
|
||||||
// Wait for the single MutationRecord for the Animation addition to
|
|
||||||
// be delivered.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: animations, changed: [], removed: [] }],
|
|
||||||
"records after play()");
|
|
||||||
|
|
||||||
// Cancel the animation.
|
|
||||||
e.style = "";
|
|
||||||
|
|
||||||
// Wait for the single removal notification.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: [], changed: [], removed: animations }],
|
|
||||||
"records after animation end");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Test that calling pause() on an Animation dispatches a changed
|
|
||||||
// notification.
|
|
||||||
addAsyncAnimTest("pause", aOptions, function*() {
|
|
||||||
// Start a long animation
|
|
||||||
e.style = "animation: anim 100s";
|
|
||||||
|
|
||||||
// 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 Animation addition to
|
|
||||||
// be delivered.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: animations, changed: [], removed: [] }],
|
|
||||||
"records after animation start");
|
|
||||||
|
|
||||||
// Wait until the animation is ready
|
|
||||||
yield animations[0].ready;
|
|
||||||
|
|
||||||
// Pause
|
|
||||||
animations[0].pause();
|
|
||||||
|
|
||||||
// Wait for the single MutationRecord for the Animation change to
|
|
||||||
// be delivered.
|
|
||||||
yield animations[0].ready;
|
|
||||||
assert_records([{ added: [], changed: animations, removed: [] }],
|
|
||||||
"records after pause()");
|
|
||||||
|
|
||||||
// Redundant pause
|
|
||||||
animations[0].pause();
|
|
||||||
|
|
||||||
// Wait to ensure no change is dispatched
|
|
||||||
yield animations[0].ready;
|
|
||||||
assert_records([], "records after redundant pause()");
|
|
||||||
|
|
||||||
// Cancel the animation.
|
|
||||||
e.style = "";
|
|
||||||
// Explicitly flush style to make sure the above style change happens.
|
|
||||||
// That's because after the above `animations[0].ready` we are the state
|
|
||||||
// just before the next tick happens. So if we waited for a
|
|
||||||
// requestAnimationFrame as usual here, we have no chance to process the
|
|
||||||
// style change since requestAnimationFrame is processed prior to styling.
|
|
||||||
flushComputedStyle(e);
|
|
||||||
|
|
||||||
// Wait for the single removal notification.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: [], changed: [], removed: animations }],
|
|
||||||
"records after animation end");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Test that calling pause() on an Animation that is pause-pending
|
|
||||||
// does not dispatch an additional changed notification.
|
|
||||||
addAsyncAnimTest("pause_while_pause_pending", aOptions, function*() {
|
|
||||||
// Start a long animation
|
|
||||||
e.style = "animation: anim 100s";
|
|
||||||
|
|
||||||
// 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 Animation addition to
|
|
||||||
// be delivered.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: animations, changed: [], removed: [] }],
|
|
||||||
"records after animation start");
|
|
||||||
|
|
||||||
// Wait until the animation is ready
|
|
||||||
yield animations[0].ready;
|
|
||||||
|
|
||||||
// Pause
|
|
||||||
animations[0].pause();
|
|
||||||
|
|
||||||
// We are now pause-pending, but pause again
|
|
||||||
animations[0].pause();
|
|
||||||
|
|
||||||
// We should only get a single change record
|
|
||||||
yield animations[0].ready;
|
|
||||||
assert_records([{ added: [], changed: animations, removed: [] }],
|
|
||||||
"records after pause()");
|
|
||||||
|
|
||||||
// Cancel the animation.
|
|
||||||
e.style = "";
|
|
||||||
// Explicitly flush style as with the above test.
|
|
||||||
flushComputedStyle(e);
|
|
||||||
|
|
||||||
// Wait for the single removal notification.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: [], changed: [], removed: animations }],
|
|
||||||
"records after animation end");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Test that calling play() on an Animation that is pause-pending
|
|
||||||
// dispatches a changed notification.
|
|
||||||
addAsyncAnimTest("aborted_pause", aOptions, function*() {
|
|
||||||
// Start a long animation
|
|
||||||
e.style = "animation: anim 100s";
|
|
||||||
|
|
||||||
// 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 Animation addition to
|
|
||||||
// be delivered.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: animations, changed: [], removed: [] }],
|
|
||||||
"records after animation start");
|
|
||||||
|
|
||||||
// Wait until the animation is ready
|
|
||||||
yield animations[0].ready;
|
|
||||||
|
|
||||||
// Pause
|
|
||||||
animations[0].pause();
|
|
||||||
|
|
||||||
// We are now pause-pending. If we play() now, we will abort the pause
|
|
||||||
animations[0].play();
|
|
||||||
|
|
||||||
// We should get two change records
|
|
||||||
yield animations[0].ready;
|
|
||||||
assert_records([{ added: [], changed: animations, removed: [] },
|
|
||||||
{ added: [], changed: animations, removed: [] }],
|
|
||||||
"records after aborting a pause()");
|
|
||||||
|
|
||||||
// Cancel the animation.
|
|
||||||
e.style = "";
|
|
||||||
// Explicitly flush style as with the above test.
|
|
||||||
flushComputedStyle(e);
|
|
||||||
|
|
||||||
// Wait for the single removal notification.
|
|
||||||
yield waitForFrame();
|
|
||||||
assert_records([{ added: [], changed: [], removed: animations }],
|
|
||||||
"records after animation end");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Test that a non-cancelling change to an animation followed immediately by a
|
// Test that a non-cancelling change to an animation followed immediately by a
|
||||||
// cancelling change will only send an animation removal notification.
|
// cancelling change will only send an animation removal notification.
|
||||||
addAsyncAnimTest("coalesce_change_cancel", aOptions, function*() {
|
addAsyncAnimTest("coalesce_change_cancel", aOptions, function*() {
|
||||||
|
|
|
@ -1028,6 +1028,432 @@ function runTest() {
|
||||||
"records after other transition ends");
|
"records after other transition ends");
|
||||||
}, "multiple_transitions");
|
}, "multiple_transitions");
|
||||||
|
|
||||||
|
// Test that starting a single animation that is cancelled by resetting
|
||||||
|
// the animation-name property dispatches an added notification and
|
||||||
|
// then a removed notification.
|
||||||
|
test(t => {
|
||||||
|
var div =
|
||||||
|
addDiv(t, { style: "animation: anim 100s" });
|
||||||
|
var observer =
|
||||||
|
setupSynchronousObserver(t,
|
||||||
|
aOptions.subtree ? div.parentNode : div,
|
||||||
|
aOptions.subtree);
|
||||||
|
|
||||||
|
// The animation should cause the creation of a single Animation.
|
||||||
|
var animations = div.getAnimations();
|
||||||
|
assert_equals(animations.length, 1,
|
||||||
|
"getAnimations().length after animation start");
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: animations, changed: [], removed: [] }],
|
||||||
|
"records after animation start");
|
||||||
|
|
||||||
|
// Cancel the animation by setting animation-name.
|
||||||
|
div.style.animationName = "none";
|
||||||
|
getComputedStyle(div).animationName;
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: [], changed: [], removed: animations }],
|
||||||
|
"records after animation end");
|
||||||
|
}, "single_animation_cancelled_name");
|
||||||
|
|
||||||
|
// Test that starting a single animation that is cancelled by updating
|
||||||
|
// the animation-duration property dispatches an added notification and
|
||||||
|
// then a removed notification.
|
||||||
|
test(t => {
|
||||||
|
var div =
|
||||||
|
addDiv(t, { style: "animation: anim 100s" });
|
||||||
|
var observer =
|
||||||
|
setupSynchronousObserver(t,
|
||||||
|
aOptions.subtree ? div.parentNode : div,
|
||||||
|
aOptions.subtree);
|
||||||
|
|
||||||
|
// The animation should cause the creation of a single Animation.
|
||||||
|
var animations = div.getAnimations();
|
||||||
|
assert_equals(animations.length, 1,
|
||||||
|
"getAnimations().length after animation start");
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: animations, changed: [], removed: [] }],
|
||||||
|
"records after animation start");
|
||||||
|
|
||||||
|
// Advance the animation by a second.
|
||||||
|
animations[0].currentTime += 1 * MS_PER_SEC;
|
||||||
|
|
||||||
|
// Cancel the animation by setting animation-duration to a value less
|
||||||
|
// than a second.
|
||||||
|
div.style.animationDuration = "0.1s";
|
||||||
|
getComputedStyle(div).animationName;
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: [], changed: animations, removed: [] },
|
||||||
|
{ added: [], changed: [], removed: animations }],
|
||||||
|
"records after animation end");
|
||||||
|
}, "single_animation_cancelled_duration");
|
||||||
|
|
||||||
|
// Test that starting a single animation that is cancelled by updating
|
||||||
|
// the animation-delay property dispatches an added notification and
|
||||||
|
// then a removed notification.
|
||||||
|
test(t => {
|
||||||
|
var div =
|
||||||
|
addDiv(t, { style: "animation: anim 100s" });
|
||||||
|
var observer =
|
||||||
|
setupSynchronousObserver(t,
|
||||||
|
aOptions.subtree ? div.parentNode : div,
|
||||||
|
aOptions.subtree);
|
||||||
|
|
||||||
|
// The animation should cause the creation of a single Animation.
|
||||||
|
var animations = div.getAnimations();
|
||||||
|
assert_equals(animations.length, 1,
|
||||||
|
"getAnimations().length after animation start");
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: animations, changed: [], removed: [] }],
|
||||||
|
"records after animation start");
|
||||||
|
|
||||||
|
// Cancel the animation by setting animation-delay.
|
||||||
|
div.style.animationDelay = "-200s";
|
||||||
|
getComputedStyle(div).animationName;
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: [], changed: [], removed: animations }],
|
||||||
|
"records after animation end");
|
||||||
|
}, "single_animation_cancelled_delay");
|
||||||
|
|
||||||
|
// Test that starting a single animation that is cancelled by updating
|
||||||
|
// the animation-iteration-count property dispatches an added notification
|
||||||
|
// and then a removed notification.
|
||||||
|
test(t => {
|
||||||
|
// A short, repeated animation.
|
||||||
|
var div =
|
||||||
|
addDiv(t, { style: "animation: anim 0.5s infinite;" });
|
||||||
|
var observer =
|
||||||
|
setupSynchronousObserver(t,
|
||||||
|
aOptions.subtree ? div.parentNode : div,
|
||||||
|
aOptions.subtree);
|
||||||
|
|
||||||
|
// The animation should cause the creation of a single Animation.
|
||||||
|
var animations = div.getAnimations();
|
||||||
|
assert_equals(animations.length, 1,
|
||||||
|
"getAnimations().length after animation start");
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: animations, changed: [], removed: [] }],
|
||||||
|
"records after animation start");
|
||||||
|
|
||||||
|
// Advance the animation until we are past the first iteration.
|
||||||
|
animations[0].currentTime += 1 * MS_PER_SEC;
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: [], changed: animations, removed: [] }],
|
||||||
|
"records after seeking animations");
|
||||||
|
|
||||||
|
// Cancel the animation by setting animation-iteration-count.
|
||||||
|
div.style.animationIterationCount = "1";
|
||||||
|
getComputedStyle(div).animationName;
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: [], changed: [], removed: animations }],
|
||||||
|
"records after animation end");
|
||||||
|
}, "single_animation_cancelled_iteration_count");
|
||||||
|
|
||||||
|
// Test that updating an animation property dispatches a changed notification.
|
||||||
|
[
|
||||||
|
{ name: "duration", prop: "animationDuration", val: "200s" },
|
||||||
|
{ name: "timing", prop: "animationTimingFunction", val: "linear" },
|
||||||
|
{ name: "iteration", prop: "animationIterationCount", val: "2" },
|
||||||
|
{ name: "direction", prop: "animationDirection", val: "reverse" },
|
||||||
|
{ name: "state", prop: "animationPlayState", val: "paused" },
|
||||||
|
{ name: "delay", prop: "animationDelay", val: "-1s" },
|
||||||
|
{ name: "fill", prop: "animationFillMode", val: "both" },
|
||||||
|
].forEach(aChangeTest => {
|
||||||
|
test(t => {
|
||||||
|
// Start a long animation.
|
||||||
|
var div = addDiv(t, { style: "animation: anim 100s;" });
|
||||||
|
var observer =
|
||||||
|
setupSynchronousObserver(t,
|
||||||
|
aOptions.subtree ? div.parentNode : div,
|
||||||
|
aOptions.subtree);
|
||||||
|
|
||||||
|
// The animation should cause the creation of a single Animation.
|
||||||
|
var animations = div.getAnimations();
|
||||||
|
assert_equals(animations.length, 1,
|
||||||
|
"getAnimations().length after animation start");
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: animations, changed: [], removed: [] }],
|
||||||
|
"records after animation start");
|
||||||
|
|
||||||
|
// Change a property of the animation such that it keeps running.
|
||||||
|
div.style[aChangeTest.prop] = aChangeTest.val;
|
||||||
|
getComputedStyle(div).animationName;
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: [], changed: animations, removed: [] }],
|
||||||
|
"records after animation change");
|
||||||
|
|
||||||
|
// Cancel the animation.
|
||||||
|
div.style.animationName = "none";
|
||||||
|
getComputedStyle(div).animationName;
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: [], changed: [], removed: animations }],
|
||||||
|
"records after animation end");
|
||||||
|
}, `single_animation_change_${aChangeTest.name}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test that calling finish() on a pause-pending (but otherwise finished)
|
||||||
|
// animation dispatches a changed notification.
|
||||||
|
test(t => {
|
||||||
|
var div =
|
||||||
|
addDiv(t, { style: "animation: anim 100s forwards" });
|
||||||
|
var observer =
|
||||||
|
setupSynchronousObserver(t,
|
||||||
|
aOptions.subtree ? div.parentNode : div,
|
||||||
|
aOptions.subtree);
|
||||||
|
|
||||||
|
// The animation should cause the creation of a single Animation.
|
||||||
|
var animations = div.getAnimations();
|
||||||
|
assert_equals(animations.length, 1,
|
||||||
|
"getAnimations().length after animation start");
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: animations, changed: [], removed: [] }],
|
||||||
|
"records after animation start");
|
||||||
|
|
||||||
|
// Finish and pause.
|
||||||
|
animations[0].finish();
|
||||||
|
animations[0].pause();
|
||||||
|
assert_equals(animations[0].playState, "paused",
|
||||||
|
"playState after finishing and calling pause()");
|
||||||
|
|
||||||
|
// Call finish() again to abort the pause
|
||||||
|
animations[0].finish();
|
||||||
|
assert_equals(animations[0].playState, "finished",
|
||||||
|
"playState after finishing again");
|
||||||
|
|
||||||
|
// Wait for three MutationRecords for the Animation changes to
|
||||||
|
// be delivered: one for each finish(), pause(), finish() operation.
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: [], changed: animations, removed: [] },
|
||||||
|
{ added: [], changed: animations, removed: [] },
|
||||||
|
{ added: [], changed: animations, removed: [] }],
|
||||||
|
"records after finish(), pause(), finish()");
|
||||||
|
|
||||||
|
// Cancel the animation.
|
||||||
|
div.style = "";
|
||||||
|
getComputedStyle(div).animationName;
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: [], changed: [], removed: animations }],
|
||||||
|
"records after animation end");
|
||||||
|
}, "finish_from_pause_pending");
|
||||||
|
|
||||||
|
// Test that calling play() on a finished Animation that fills forwards
|
||||||
|
// dispatches a changed notification.
|
||||||
|
test(t => {
|
||||||
|
// Animation with a forwards fill
|
||||||
|
var div =
|
||||||
|
addDiv(t, { style: "animation: anim 100s forwards" });
|
||||||
|
var observer =
|
||||||
|
setupSynchronousObserver(t,
|
||||||
|
aOptions.subtree ? div.parentNode : div,
|
||||||
|
aOptions.subtree);
|
||||||
|
|
||||||
|
// The animation should cause the creation of a single Animation.
|
||||||
|
var animations = div.getAnimations();
|
||||||
|
assert_equals(animations.length, 1,
|
||||||
|
"getAnimations().length after animation start");
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: animations, changed: [], removed: [] }],
|
||||||
|
"records after animation start");
|
||||||
|
|
||||||
|
// Seek to the end
|
||||||
|
animations[0].finish();
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: [], changed: animations, removed: [] }],
|
||||||
|
"records after finish()");
|
||||||
|
|
||||||
|
// Since we are filling forwards, calling play() should produce a
|
||||||
|
// change record since the animation remains relevant.
|
||||||
|
animations[0].play();
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: [], changed: animations, removed: [] }],
|
||||||
|
"records after play()");
|
||||||
|
|
||||||
|
// Cancel the animation.
|
||||||
|
div.style = "";
|
||||||
|
getComputedStyle(div).animationName;
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: [], changed: [], removed: animations }],
|
||||||
|
"records after animation end");
|
||||||
|
}, "play_filling_forwards");
|
||||||
|
|
||||||
|
// Test that calling pause() on an Animation dispatches a changed
|
||||||
|
// notification.
|
||||||
|
test(t => {
|
||||||
|
var div =
|
||||||
|
addDiv(t, { style: "animation: anim 100s" });
|
||||||
|
var observer =
|
||||||
|
setupSynchronousObserver(t,
|
||||||
|
aOptions.subtree ? div.parentNode : div,
|
||||||
|
aOptions.subtree);
|
||||||
|
|
||||||
|
// The animation should cause the creation of a single Animation.
|
||||||
|
var animations = div.getAnimations();
|
||||||
|
assert_equals(animations.length, 1,
|
||||||
|
"getAnimations().length after animation start");
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: animations, changed: [], removed: [] }],
|
||||||
|
"records after animation start");
|
||||||
|
|
||||||
|
// Pause
|
||||||
|
animations[0].pause();
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: [], changed: animations, removed: [] }],
|
||||||
|
"records after pause()");
|
||||||
|
|
||||||
|
// Redundant pause
|
||||||
|
animations[0].pause();
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[], "records after redundant pause()");
|
||||||
|
|
||||||
|
// Cancel the animation.
|
||||||
|
div.style = "";
|
||||||
|
getComputedStyle(div).animationName;
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: [], changed: [], removed: animations }],
|
||||||
|
"records after animation end");
|
||||||
|
}, "pause");
|
||||||
|
|
||||||
|
// Test that calling pause() on an Animation that is pause-pending
|
||||||
|
// does not dispatch an additional changed notification.
|
||||||
|
test(t => {
|
||||||
|
var div =
|
||||||
|
addDiv(t, { style: "animation: anim 100s" });
|
||||||
|
var observer =
|
||||||
|
setupSynchronousObserver(t,
|
||||||
|
aOptions.subtree ? div.parentNode : div,
|
||||||
|
aOptions.subtree);
|
||||||
|
|
||||||
|
// The animation should cause the creation of a single Animation.
|
||||||
|
var animations = div.getAnimations();
|
||||||
|
assert_equals(animations.length, 1,
|
||||||
|
"getAnimations().length after animation start");
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: animations, changed: [], removed: [] }],
|
||||||
|
"records after animation start");
|
||||||
|
|
||||||
|
// Pause
|
||||||
|
animations[0].pause();
|
||||||
|
|
||||||
|
// We are now pause-pending, but pause again
|
||||||
|
animations[0].pause();
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: [], changed: animations, removed: [] }],
|
||||||
|
"records after pause()");
|
||||||
|
|
||||||
|
// Cancel the animation.
|
||||||
|
div.style = "";
|
||||||
|
getComputedStyle(div).animationName;
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: [], changed: [], removed: animations }],
|
||||||
|
"records after animation end");
|
||||||
|
}, "pause_while_pause_pending");
|
||||||
|
|
||||||
|
// Test that calling play() on an Animation that is pause-pending
|
||||||
|
// dispatches a changed notification.
|
||||||
|
test(t => {
|
||||||
|
var div =
|
||||||
|
addDiv(t, { style: "animation: anim 100s" });
|
||||||
|
var observer =
|
||||||
|
setupSynchronousObserver(t,
|
||||||
|
aOptions.subtree ? div.parentNode : div,
|
||||||
|
aOptions.subtree);
|
||||||
|
|
||||||
|
// The animation should cause the creation of a single Animation.
|
||||||
|
var animations = div.getAnimations();
|
||||||
|
assert_equals(animations.length, 1,
|
||||||
|
"getAnimations().length after animation start");
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: animations, changed: [], removed: [] }],
|
||||||
|
"records after animation start");
|
||||||
|
|
||||||
|
// Pause
|
||||||
|
animations[0].pause();
|
||||||
|
|
||||||
|
// We are now pause-pending. If we play() now, we will abort the pause
|
||||||
|
animations[0].play();
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: [], changed: animations, removed: [] },
|
||||||
|
{ added: [], changed: animations, removed: [] }],
|
||||||
|
"records after aborting a pause()");
|
||||||
|
|
||||||
|
// Cancel the animation.
|
||||||
|
div.style = "";
|
||||||
|
getComputedStyle(div).animationName;
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: [], changed: [], removed: animations }],
|
||||||
|
"records after animation end");
|
||||||
|
}, "aborted_pause");
|
||||||
|
|
||||||
|
// Test that calling play() on a finished Animation that does *not* fill
|
||||||
|
// forwards dispatches an addition notification.
|
||||||
|
test(t => {
|
||||||
|
var div =
|
||||||
|
addDiv(t, { style: "animation: anim 100s" });
|
||||||
|
var observer =
|
||||||
|
setupSynchronousObserver(t,
|
||||||
|
aOptions.subtree ? div.parentNode : div,
|
||||||
|
aOptions.subtree);
|
||||||
|
|
||||||
|
// The animation should cause the creation of a single Animation.
|
||||||
|
var animations = div.getAnimations();
|
||||||
|
assert_equals(animations.length, 1,
|
||||||
|
"getAnimations().length after animation start");
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: animations, changed: [], removed: [] }],
|
||||||
|
"records after animation start");
|
||||||
|
|
||||||
|
// Seek to the end
|
||||||
|
animations[0].finish();
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: [], changed: [], removed: animations }],
|
||||||
|
"records after finish()");
|
||||||
|
|
||||||
|
// Since we are *not* filling forwards, calling play() is equivalent
|
||||||
|
// to creating a new animation since it becomes relevant again.
|
||||||
|
animations[0].play();
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: animations, changed: [], removed: [] }],
|
||||||
|
"records after play()");
|
||||||
|
|
||||||
|
// Cancel the animation.
|
||||||
|
div.style = "";
|
||||||
|
getComputedStyle(div).animationName;
|
||||||
|
|
||||||
|
assert_equals_records(observer.takeRecords(),
|
||||||
|
[{ added: [], changed: [], removed: animations }],
|
||||||
|
"records after animation end");
|
||||||
|
}, "play_after_finish");
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test(t => {
|
test(t => {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче