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:
Hiroyuki Ikezoe 2017-12-07 10:06:02 +09:00
Родитель 70ec3f1b1b
Коммит 49e012c030
2 изменённых файлов: 426 добавлений и 451 удалений

Просмотреть файл

@ -272,99 +272,6 @@ function assert_records_any_order(expected, desc) {
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
// the animation-fill-mode property dispatches an added notification and
// then a removed notification.
@ -412,90 +319,6 @@ function assert_records_any_order(expected, desc) {
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
// dispatches a changed notification.
addAsyncAnimTest("finish_from_pause", aOptions, function*() {
@ -551,53 +374,6 @@ function assert_records_any_order(expected, desc) {
"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
// notification.
addAsyncAnimTest("play", aOptions, function*() {
@ -642,233 +418,6 @@ function assert_records_any_order(expected, desc) {
"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
// cancelling change will only send an animation removal notification.
addAsyncAnimTest("coalesce_change_cancel", aOptions, function*() {

Просмотреть файл

@ -1028,6 +1028,432 @@ function runTest() {
"records after other transition ends");
}, "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 => {