Update web-platform-tests to revision 8fed98324bc133df221d778c62cbff210d43b0ce

This commit is contained in:
WPT Sync Bot 2018-02-19 20:08:38 -05:00
parent be902d56c0
commit 8a6476740e
246 changed files with 15482 additions and 1281 deletions

View file

@ -26,29 +26,28 @@ promise_test(t => {
}, 'A play-pending ready promise should be rejected when the animation is'
+ ' canceled');
promise_test(t => {
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
return animation.ready.then(() => {
animation.pause();
// Set up listeners on pause-pending ready promise
const retPromise = animation.ready.then(() => {
assert_unreached('ready promise was fulfilled');
}).catch(err => {
assert_equals(err.name, 'AbortError',
'ready promise is rejected with AbortError');
});
animation.cancel();
return retPromise;
});
await animation.ready;
// Make it pause-pending
animation.pause();
// We need to store the original ready promise since cancel() will
// replace it
const originalPromise = animation.ready;
animation.cancel();
await promise_rejects(t, 'AbortError', originalPromise,
'Cancel should abort ready promise');
}, 'A pause-pending ready promise should be rejected when the animation is'
+ ' canceled');
promise_test(t => {
promise_test(async t => {
const animation = createDiv(t).animate(null);
animation.cancel();
return animation.ready.then(p => {
assert_equals(p, animation);
});
const promiseResult = await animation.ready;
assert_equals(promiseResult, animation);
}, 'When an animation is canceled, it should create a resolved Promise');
test(t => {

View file

@ -11,7 +11,208 @@
<script>
'use strict';
promise_test(t => {
test(t => {
const div = createDiv(t);
const animation = div.animate(null, 100 * MS_PER_SEC);
animation.playbackRate = 0;
assert_throws({name: 'InvalidStateError'}, () => {
animation.finish();
});
}, 'Finishing an animation with a zero playback rate throws');
test(t => {
const div = createDiv(t);
const animation = div.animate(null,
{ duration : 100 * MS_PER_SEC,
iterations : Infinity });
assert_throws({name: 'InvalidStateError'}, () => {
animation.finish();
});
}, 'Finishing an infinite animation throws');
test(t => {
const div = createDiv(t);
const animation = div.animate(null, 100 * MS_PER_SEC);
animation.finish();
assert_time_equals_literal(animation.currentTime, 100 * MS_PER_SEC,
'After finishing, the currentTime should be set to the end of the'
+ ' active duration');
}, 'Finishing an animation seeks to the end time');
test(t => {
const div = createDiv(t);
const animation = div.animate(null, 100 * MS_PER_SEC);
// 1s past effect end
animation.currentTime =
animation.effect.getComputedTiming().endTime + 1 * MS_PER_SEC;
animation.finish();
assert_time_equals_literal(animation.currentTime, 100 * MS_PER_SEC,
'After finishing, the currentTime should be set back to the end of the'
+ ' active duration');
}, 'Finishing an animation with a current time past the effect end jumps'
+ ' back to the end');
promise_test(async t => {
const div = createDiv(t);
const animation = div.animate(null, 100 * MS_PER_SEC);
animation.currentTime = 100 * MS_PER_SEC;
await animation.finished;
animation.playbackRate = -1;
animation.finish();
assert_equals(animation.currentTime, 0,
'After finishing a reversed animation the currentTime ' +
'should be set to zero');
}, 'Finishing a reversed animation jumps to zero time');
promise_test(async t => {
const div = createDiv(t);
const animation = div.animate(null, 100 * MS_PER_SEC);
animation.currentTime = 100 * MS_PER_SEC;
await animation.finished;
animation.playbackRate = -1;
animation.currentTime = -1000;
animation.finish();
assert_equals(animation.currentTime, 0,
'After finishing a reversed animation the currentTime ' +
'should be set back to zero');
}, 'Finishing a reversed animation with a current time less than zero'
+ ' makes it jump back to zero');
promise_test(async t => {
const div = createDiv(t);
const animation = div.animate(null, 100 * MS_PER_SEC);
animation.pause();
await animation.ready;
animation.finish();
assert_equals(animation.playState, 'finished',
'The play state of a paused animation should become ' +
'"finished"');
assert_times_equal(animation.startTime,
animation.timeline.currentTime - 100 * MS_PER_SEC,
'The start time of a paused animation should be set');
}, 'Finishing a paused animation resolves the start time');
test(t => {
const div = createDiv(t);
const animation = div.animate(null, 100 * MS_PER_SEC);
// Update playbackRate so we can test that the calculated startTime
// respects it
animation.playbackRate = 2;
animation.pause();
// While animation is still pause-pending call finish()
animation.finish();
assert_false(animation.pending);
assert_equals(animation.playState, 'finished',
'The play state of a pause-pending animation should become ' +
'"finished"');
assert_times_equal(animation.startTime,
animation.timeline.currentTime - 100 * MS_PER_SEC / 2,
'The start time of a pause-pending animation should ' +
'be set');
}, 'Finishing a pause-pending animation resolves the pending task'
+ ' immediately and update the start time');
test(t => {
const div = createDiv(t);
const animation = div.animate(null, 100 * MS_PER_SEC);
animation.playbackRate = -2;
animation.pause();
animation.finish();
assert_false(animation.pending);
assert_equals(animation.playState, 'finished',
'The play state of a pause-pending animation should become ' +
'"finished"');
assert_times_equal(animation.startTime, animation.timeline.currentTime,
'The start time of a pause-pending animation should be ' +
'set');
}, 'Finishing a pause-pending animation with negative playback rate'
+ ' resolves the pending task immediately');
test(t => {
const div = createDiv(t);
const animation = div.animate(null, 100 * MS_PER_SEC);
animation.playbackRate = 0.5;
animation.finish();
assert_false(animation.pending);
assert_equals(animation.playState, 'finished',
'The play state of a play-pending animation should become ' +
'"finished"');
assert_times_equal(animation.startTime,
animation.timeline.currentTime - 100 * MS_PER_SEC / 0.5,
'The start time of a play-pending animation should ' +
'be set');
}, 'Finishing an animation while play-pending resolves the pending'
+ ' task immediately');
// FIXME: Add a test for when we are play-pending without an active timeline.
// - In that case even after calling finish() we should still be pending but
// the current time should be updated
promise_test(async t => {
const div = createDiv(t);
const animation = div.animate(null, 100 * MS_PER_SEC);
await animation.ready;
animation.pause();
animation.play();
// We are now in the unusual situation of being play-pending whilst having
// a resolved start time. Check that finish() still triggers a transition
// to the finished state immediately.
animation.finish();
assert_equals(animation.playState, 'finished',
'After aborting a pause then finishing an animation its play ' +
'state should become "finished" immediately');
}, 'Finishing an animation during an aborted pause makes it finished'
+ ' immediately');
promise_test(async t => {
const div = createDiv(t);
const animation = div.animate(null, 100 * MS_PER_SEC);
let resolvedFinished = false;
animation.finished.then(() => {
resolvedFinished = true;
});
await animation.ready;
animation.finish();
await Promise.resolve();
assert_true(resolvedFinished, 'finished promise should be resolved');
}, 'Finishing an animation resolves the finished promise synchronously');
promise_test(async t => {
const effect = new KeyframeEffectReadOnly(null, null, 100 * MS_PER_SEC);
const animation = new Animation(effect, document.timeline);
let resolvedFinished = false;
animation.finished.then(() => {
resolvedFinished = true;
});
await animation.ready;
animation.finish();
await Promise.resolve();
assert_true(resolvedFinished, 'finished promise should be resolved');
}, 'Finishing an animation without a target resolves the finished promise'
+ ' synchronously');
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
const promise = animation.ready;
let readyResolved = false;
@ -19,13 +220,69 @@ promise_test(t => {
animation.finish();
animation.ready.then(() => { readyResolved = true; });
return animation.finished.then(p => {
assert_equals(p, animation);
assert_equals(animation.ready, promise);
assert_true(readyResolved);
const promiseResult = await animation.finished;
assert_equals(promiseResult, animation);
assert_equals(animation.ready, promise);
assert_true(readyResolved);
}, 'A pending ready promise is resolved and not replaced when the animation'
+ ' is finished');
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
await animation.ready;
animation.updatePlaybackRate(2);
assert_true(animation.pending);
animation.finish();
assert_false(animation.pending);
assert_equals(animation.playbackRate, 2);
assert_time_equals_literal(animation.currentTime, 100 * MS_PER_SEC);
}, 'A pending playback rate should be applied immediately when an animation'
+ ' is finished');
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
await animation.ready;
animation.updatePlaybackRate(0);
assert_throws('InvalidStateError', () => {
animation.finish();
});
}, 'A pending ready promise should be resolved and not replaced when the'
+ ' animation is finished');
}, 'An exception should be thrown if the effective playback rate is zero');
promise_test(async t => {
const animation = createDiv(t).animate(null, {
duration: 100 * MS_PER_SEC,
iterations: Infinity
});
animation.currentTime = 50 * MS_PER_SEC;
animation.playbackRate = -1;
await animation.ready;
animation.updatePlaybackRate(1);
assert_throws('InvalidStateError', () => {
animation.finish();
});
}, 'An exception should be thrown when finishing if the effective playback rate'
+ ' is positive and the target effect end is infinity');
promise_test(async t => {
const animation = createDiv(t).animate(null, {
duration: 100 * MS_PER_SEC,
iterations: Infinity
});
await animation.ready;
animation.updatePlaybackRate(-1);
animation.finish();
// Should not have thrown
}, 'An exception is NOT thrown when finishing if the effective playback rate'
+ ' is negative and the target effect end is infinity');
</script>
</body>

View file

@ -11,17 +11,36 @@
<script>
'use strict';
promise_test(t => {
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
const promise = animation.ready;
animation.pause();
return promise.then(p => {
assert_equals(p, animation);
assert_equals(animation.ready, promise);
assert_false(animation.pending, 'No longer pause-pending');
});
const promiseResult = await promise;
assert_equals(promiseResult, animation);
assert_equals(animation.ready, promise);
assert_false(animation.pending, 'No longer pause-pending');
}, 'A pending ready promise should be resolved and not replaced when the'
+ ' animation is paused');
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
// Let animation start roughly half-way through
animation.currentTime = 50 * MS_PER_SEC;
await animation.ready;
// Go pause-pending and also set a pending playback rate
animation.pause();
animation.updatePlaybackRate(0.5);
await animation.ready;
// If the current time was updated using the new playback rate it will jump
// back to 25s but if we correctly used the old playback rate the current time
// will be >50s.
assert_greater_than(animation.currentTime, 50 * MS_PER_SEC);
}, 'A pause-pending animation maintains the current time when applying a'
+ ' pending playback rate');
</script>
</body>

View file

@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Play states</title>
<link rel="help" href="https://drafts.csswg.org/web-animations/#play-state">
<link rel="help" href="https://drafts.csswg.org/web-animations/#play-states">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>

View file

@ -45,15 +45,31 @@ test(t => {
}, 'The ready promise should be replaced if the animation is not already'
+ ' pending');
promise_test(t => {
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
const promise = animation.ready;
return promise.then(p => {
assert_equals(p, animation);
assert_equals(animation.ready, promise);
});
const promiseResult = await promise;
assert_equals(promiseResult, animation);
assert_equals(animation.ready, promise);
}, 'A pending ready promise should be resolved and not replaced when the'
+ ' animation enters the running state');
promise_test(async t => {
// Seek animation beyond target end
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.currentTime = -100 * MS_PER_SEC;
await animation.ready;
// Set pending playback rate to the opposite direction
animation.updatePlaybackRate(-1);
assert_true(animation.pending);
assert_equals(animation.playbackRate, 1);
// When we play, we should seek to the target end, NOT to zero (which
// is where we would seek to if we used the playbackRate of 1.
animation.play();
assert_time_equals_literal(animation.currentTime, 100 * MS_PER_SEC);
}, 'A pending playback rate is used when determining auto-rewind behavior');
</script>
</body>

View file

@ -1,8 +1,8 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Reverse an animation</title>
<title>Reversing an animation</title>
<link rel="help"
href="https://drafts.csswg.org/web-animations/#reverse-an-animation">
href="https://drafts.csswg.org/web-animations/#reversing-an-animation-section">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@ -11,38 +11,43 @@
<script>
'use strict';
promise_test(t => {
promise_test(async t => {
const div = createDiv(t);
const animation = div.animate({}, { duration: 100 * MS_PER_SEC,
iterations: Infinity });
await animation.ready;
// Wait a frame because if currentTime is still 0 when we call
// reverse(), it will throw (per spec).
return animation.ready.then(waitForAnimationFrames(1)).then(() => {
assert_greater_than_equal(animation.currentTime, 0,
'currentTime expected to be greater than 0, one frame after starting');
animation.currentTime = 50 * MS_PER_SEC;
const previousPlaybackRate = animation.playbackRate;
animation.reverse();
assert_equals(animation.playbackRate, -previousPlaybackRate,
'playbackRate should be inverted');
});
await waitForAnimationFrames(1);
assert_greater_than_equal(animation.currentTime, 0,
'currentTime expected to be greater than 0, one frame after starting');
animation.currentTime = 50 * MS_PER_SEC;
const previousPlaybackRate = animation.playbackRate;
animation.reverse();
assert_equals(animation.playbackRate, previousPlaybackRate,
'Playback rate should not have changed');
await animation.ready;
assert_equals(animation.playbackRate, -previousPlaybackRate,
'Playback rate should be inverted');
}, 'Reversing an animation inverts the playback rate');
promise_test(t => {
promise_test(async t => {
const div = createDiv(t);
const animation = div.animate({}, { duration: 100 * MS_PER_SEC,
iterations: Infinity });
animation.currentTime = 50 * MS_PER_SEC;
animation.pause();
return animation.ready.then(() => {
animation.reverse();
return animation.ready;
}).then(() => {
assert_equals(animation.playState, 'running',
'Animation.playState should be "running" after reverse()');
});
await animation.ready;
animation.reverse();
await animation.ready;
assert_equals(animation.playState, 'running',
'Animation.playState should be "running" after reverse()');
}, 'Reversing an animation plays a pausing animation');
test(t => {
@ -69,7 +74,7 @@ test(t => {
'The animation is still pending after calling reverse');
}, 'Reversing an animation does not cause it to leave the pending state');
promise_test(t => {
promise_test(async t => {
const div = createDiv(t);
const animation = div.animate({}, { duration: 200 * MS_PER_SEC,
delay: -100 * MS_PER_SEC });
@ -78,10 +83,9 @@ promise_test(t => {
animation.reverse();
return Promise.resolve(() => {
assert_false(readyResolved,
'ready promise should not have been resolved yet');
});
await Promise.resolve();
assert_false(readyResolved,
'ready promise should not have been resolved yet');
}, 'Reversing an animation does not cause it to resolve the ready promise');
test(t => {
@ -149,13 +153,16 @@ test(t => {
}, 'Reversing an animation when playbackRate > 0 and currentTime < 0 ' +
'and the target effect end is positive infinity should throw an exception');
test(t => {
promise_test(async t => {
const animation = createDiv(t).animate({}, { duration: 100 * MS_PER_SEC,
iterations: Infinity });
animation.currentTime = -200 * MS_PER_SEC;
try { animation.reverse(); } catch(e) { }
assert_equals(animation.playbackRate, 1, 'playbackRate is unchanged');
await animation.ready;
assert_equals(animation.playbackRate, 1, 'playbackRate remains unchanged');
}, 'When reversing throws an exception, the playback rate remains unchanged');
@ -191,18 +198,18 @@ test(t => {
'and the target effect end is positive infinity should make it play ' +
'from the start');
test(t => {
promise_test(async t => {
const div = createDiv(t);
const animation = div.animate({}, 100 * MS_PER_SEC);
animation.playbackRate = 0;
animation.currentTime = 50 * MS_PER_SEC;
animation.reverse();
await animation.ready;
assert_equals(animation.playbackRate, 0,
'reverse() should preserve playbackRate if the playbackRate == 0');
assert_equals(animation.currentTime, 50 * MS_PER_SEC,
'reverse() should not affect the currentTime if the playbackRate == 0');
t.done();
}, 'Reversing when when playbackRate == 0 should preserve the current ' +
'time and playback rate');
@ -215,5 +222,33 @@ test(t => {
}, 'Reversing an animation without an active timeline throws an ' +
'InvalidStateError');
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
await animation.ready;
animation.updatePlaybackRate(2);
animation.reverse();
await animation.ready;
assert_equals(animation.playbackRate, -2);
}, 'Reversing should use the negative pending playback rate');
promise_test(async t => {
const animation = createDiv(t).animate(null, {
duration: 100 * MS_PER_SEC,
iterations: Infinity,
});
animation.currentTime = -200 * MS_PER_SEC;
await animation.ready;
animation.updatePlaybackRate(2);
assert_throws('InvalidStateError', () => { animation.reverse(); });
assert_equals(animation.playbackRate, 1);
await animation.ready;
assert_equals(animation.playbackRate, 2);
}, 'When reversing fails, it should restore any previous pending playback'
+ ' rate');
</script>
</body>

View file

@ -0,0 +1,142 @@
<!doctype html>
<meta charset=utf-8>
<title>Seamlessly updating the playback rate of an animation</title>
<link rel="help"
href="https://drafts.csswg.org/web-animations-1/#seamlessly-updating-the-playback-rate-of-an-animation">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
<body>
<div id="log"></div>
<script>
'use strict';
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
await animation.ready;
animation.currentTime = 50 * MS_PER_SEC;
animation.updatePlaybackRate(0.5);
await animation.ready;
// Since the animation is in motion (and we want to test it while it is in
// motion!) we can't assert that the current time == 50s but we can check
// that the current time is NOT re-calculated by simply substituting in the
// new playback rate (i.e. without adjusting the start time). If that were
// the case the currentTime would jump to 25s. So we just test the currentTime
// hasn't gone backwards.
assert_greater_than_equal(animation.currentTime, 50 * MS_PER_SEC,
'Reducing the playback rate should not change the current time ' +
'of a playing animation');
animation.updatePlaybackRate(2);
await animation.ready;
// Likewise, we test here that the current time does not jump to 100s as it
// would if we naively applied a playbackRate of 2 without adjusting the
// startTime.
assert_less_than(animation.currentTime, 100 * MS_PER_SEC,
'Increasing the playback rate should not change the current time ' +
'of a playing animation');
}, 'Updating the playback rate maintains the current time');
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
await animation.ready;
assert_false(animation.pending);
animation.updatePlaybackRate(2);
assert_true(animation.pending);
}, 'Updating the playback rate while running makes the animation pending');
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.currentTime = 50 * MS_PER_SEC;
assert_true(animation.pending);
animation.updatePlaybackRate(0.5);
// Check that the hold time is updated as expected
assert_time_equals_literal(animation.currentTime, 50 * MS_PER_SEC);
await animation.ready;
// As above, check that the currentTime is not calculated by simply
// substituting in the updated playbackRate without updating the startTime.
assert_greater_than_equal(animation.currentTime, 50 * MS_PER_SEC,
'Reducing the playback rate should not change the current time ' +
'of a play-pending animation');
}, 'Updating the playback rate on a play-pending animation maintains'
+ ' the current time');
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.currentTime = 50 * MS_PER_SEC;
await animation.ready;
animation.pause();
animation.updatePlaybackRate(0.5);
assert_greater_than_equal(animation.currentTime, 50 * MS_PER_SEC);
}, 'Updating the playback rate on a pause-pending animation maintains'
+ ' the current time');
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.updatePlaybackRate(2);
animation.updatePlaybackRate(3);
animation.updatePlaybackRate(4);
assert_equals(animation.playbackRate, 1);
await animation.ready;
assert_equals(animation.playbackRate, 4);
}, 'If a pending playback rate is set multiple times, the latest wins');
test(t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.cancel();
animation.updatePlaybackRate(2);
assert_equals(animation.playbackRate, 2);
assert_false(animation.pending);
}, 'In the idle state, the playback rate is applied immediately');
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.pause();
await animation.ready;
animation.updatePlaybackRate(2);
assert_equals(animation.playbackRate, 2);
assert_false(animation.pending);
}, 'In the paused state, the playback rate is applied immediately');
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.finish();
assert_time_equals_literal(animation.currentTime, 100 * MS_PER_SEC);
assert_false(animation.pending);
animation.updatePlaybackRate(2);
assert_equals(animation.playbackRate, 2);
assert_time_equals_literal(animation.currentTime, 100 * MS_PER_SEC);
assert_false(animation.pending);
}, 'Updating the playback rate on a finished animation maintains'
+ ' the current time');
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.finish();
assert_time_equals_literal(animation.currentTime, 100 * MS_PER_SEC);
assert_false(animation.pending);
animation.updatePlaybackRate(0);
assert_equals(animation.playbackRate, 0);
assert_time_equals_literal(animation.currentTime, 100 * MS_PER_SEC);
assert_false(animation.pending);
}, 'Updating the playback rate to zero on a finished animation maintains'
+ ' the current time');
</script>
</body>

View file

@ -0,0 +1,38 @@
<!doctype html>
<meta charset=utf-8>
<title>Setting the current time of an animation</title>
<link rel="help"
href="https://drafts.csswg.org/web-animations-1/#setting-the-current-time-of-an-animation">
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<script src='../../testcommon.js'></script>
<body>
<div id='log'></div>
<script>
'use strict';
promise_test(async t => {
const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
await anim.ready;
anim.pause();
// We should be pause-pending now
assert_true(anim.pending);
assert_equals(anim.playState, 'paused');
// Apply a pending playback rate
anim.updatePlaybackRate(2);
assert_equals(anim.playbackRate, 1);
// Setting the current time should apply the pending playback rate
anim.currentTime = 50 * MS_PER_SEC;
assert_equals(anim.playbackRate, 2);
assert_false(anim.pending);
// Sanity check that the current time is preserved
assert_time_equals_literal(anim.currentTime, 50 * MS_PER_SEC);
}, 'Setting the current time of a pausing animation applies a pending playback'
+ ' rate');
</script>
</body>

View file

@ -0,0 +1,61 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Setting the playback rate of an animation</title>
<link rel="help" href="https://drafts.csswg.org/web-animations/#setting-the-playback-rate-of-an-animation">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
<body>
<div id="log"></div>
<script>
'use strict';
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.playbackRate = 2;
await animation.ready;
const previousAnimationCurrentTime = animation.currentTime;
const previousTimelineCurrentTime = animation.timeline.currentTime;
await waitForAnimationFrames(1);
const animationCurrentTimeDifference =
animation.currentTime - previousAnimationCurrentTime;
const timelineCurrentTimeDifference =
animation.timeline.currentTime - previousTimelineCurrentTime;
assert_times_equal(
animationCurrentTimeDifference,
timelineCurrentTimeDifference * animation.playbackRate,
'The current time should increase two times faster than timeline'
);
}, 'The playback rate affects the rate of progress of the current time');
test(t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.currentTime = 50 * MS_PER_SEC;
animation.playbackRate = 2;
assert_time_equals_literal(animation.currentTime, 50 * MS_PER_SEC);
}, 'Setting the playback rate while play-pending preserves the current time');
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.currentTime = 50 * MS_PER_SEC;
await animation.ready;
animation.playbackRate = 2;
assert_greater_than_equal(animation.currentTime, 50 * MS_PER_SEC);
assert_less_than(animation.currentTime, 100 * MS_PER_SEC);
}, 'Setting the playback rate while playing preserves the current time');
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.currentTime = 50 * MS_PER_SEC;
animation.updatePlaybackRate(2);
animation.playbackRate = 1;
await animation.ready;
assert_equals(animation.playbackRate, 1);
}, 'Setting the playback rate should clear any pending playback rate');
</script>
</body>

View file

@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Set the animation start time</title>
<link rel="help" href="https://drafts.csswg.org/web-animations/#set-the-animation-start-time">
<title>Setting the start time of an animation</title>
<link rel="help" href="https://drafts.csswg.org/web-animations/#setting-the-start-time-of-an-animation">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@ -112,7 +112,7 @@ test(t => {
+ ' start time');
}, 'Setting an unresolved start time sets the hold time');
promise_test(t => {
promise_test(async t => {
const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
document.timeline);
@ -135,13 +135,12 @@ promise_test(t => {
// If we schedule another microtask then it should run immediately after
// the ready promise resolution microtask.
return Promise.resolve().then(() => {
assert_true(readyPromiseCallbackCalled,
'Ready promise callback called after setting startTime');
});
await Promise.resolve();
assert_true(readyPromiseCallbackCalled,
'Ready promise callback called after setting startTime');
}, 'Setting the start time resolves a pending ready promise');
promise_test(t => {
promise_test(async t => {
const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
document.timeline);
@ -163,13 +162,12 @@ promise_test(t => {
assert_false(readyPromiseCallbackCalled,
'Ready promise callback is not called synchronously');
return Promise.resolve().then(() => {
assert_true(readyPromiseCallbackCalled,
'Ready promise callback called after setting startTime');
});
await Promise.resolve();
assert_true(readyPromiseCallbackCalled,
'Ready promise callback called after setting startTime');
}, 'Setting the start time resolves a pending pause task');
promise_test(t => {
promise_test(async t => {
const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
document.timeline);
@ -190,12 +188,60 @@ promise_test(t => {
// Furthermore, that time should persist if we have correctly updated
// the hold time
const finishedCurrentTime = animation.currentTime;
return waitForAnimationFrames(1).then(() => {
assert_equals(animation.currentTime, finishedCurrentTime,
'Current time does not change after seeking past the effect'
+ ' end time by setting the current time');
});
await waitForAnimationFrames(1);
assert_equals(animation.currentTime, finishedCurrentTime,
'Current time does not change after seeking past the effect'
+ ' end time by setting the current time');
}, 'Setting the start time updates the finished state');
promise_test(async t => {
const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
// We should be play-pending now
assert_true(anim.pending);
assert_equals(anim.playState, 'running');
// Apply a pending playback rate
anim.updatePlaybackRate(2);
assert_equals(anim.playbackRate, 1);
assert_true(anim.pending);
// Setting the start time should apply the pending playback rate
anim.startTime = anim.timeline.currentTime - 25 * MS_PER_SEC;
assert_equals(anim.playbackRate, 2);
assert_false(anim.pending);
// Sanity check that the start time is preserved and current time is
// calculated using the new playback rate
assert_times_equal(anim.startTime,
anim.timeline.currentTime - 25 * MS_PER_SEC);
assert_time_equals_literal(anim.currentTime, 50 * MS_PER_SEC);
}, 'Setting the start time of a play-pending animation applies a pending playback rate');
promise_test(async t => {
const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
await anim.ready;
// We should be running now
assert_false(anim.pending);
assert_equals(anim.playState, 'running');
// Apply a pending playback rate
anim.updatePlaybackRate(2);
assert_equals(anim.playbackRate, 1);
assert_true(anim.pending);
// Setting the start time should apply the pending playback rate
anim.startTime = anim.timeline.currentTime - 25 * MS_PER_SEC;
assert_equals(anim.playbackRate, 2);
assert_false(anim.pending);
// Sanity check that the start time is preserved and current time is
// calculated using the new playback rate
assert_times_equal(anim.startTime,
anim.timeline.currentTime - 25 * MS_PER_SEC);
assert_time_equals_literal(anim.currentTime, 50 * MS_PER_SEC);
}, 'Setting the start time of a playing animation applies a pending playback rate');
</script>
</body>

View file

@ -1,6 +1,6 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Setting the target effect</title>
<title>Setting the target effect of an animation</title>
<link rel='help' href='https://drafts.csswg.org/web-animations/#setting-the-target-effect'>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
@ -31,7 +31,7 @@ promise_test(t => {
}, 'If new effect is null and old effect is not null, we reset the pending ' +
'tasks and ready promise is rejected');
promise_test(t => {
promise_test(async t => {
const anim = new Animation();
anim.pause();
assert_true(anim.pending);
@ -40,15 +40,14 @@ promise_test(t => {
{ marginLeft: [ '0px', '100px' ] },
100 * MS_PER_SEC);
assert_true(anim.pending);
await anim.ready;
return anim.ready.then(() => {
assert_false(anim.pending);
assert_equals(anim.playState, 'paused');
});
assert_false(anim.pending);
assert_equals(anim.playState, 'paused');
}, 'If animation has a pending pause task, reschedule that task to run ' +
'as soon as animation is ready.');
promise_test(t => {
promise_test(async t => {
const anim = new Animation();
anim.play();
assert_true(anim.pending);
@ -57,24 +56,23 @@ promise_test(t => {
{ marginLeft: [ '0px', '100px' ] },
100 * MS_PER_SEC);
assert_true(anim.pending);
await anim.ready;
return anim.ready.then(() => {
assert_false(anim.pending);
assert_equals(anim.playState, 'running');
});
assert_false(anim.pending);
assert_equals(anim.playState, 'running');
}, 'If animation has a pending play task, reschedule that task to run ' +
'as soon as animation is ready to play new effect.');
promise_test(t => {
promise_test(async t => {
const animA = createDiv(t).animate({ marginLeft: [ '0px', '100px' ] },
100 * MS_PER_SEC);
const animB = new Animation();
return animA.ready.then(() => {
animB.effect = animA.effect;
assert_equals(animA.effect, null);
assert_equals(animA.playState, 'finished');
});
await animA.ready;
animB.effect = animA.effect;
assert_equals(animA.effect, null);
assert_equals(animA.playState, 'finished');
}, 'When setting the effect of an animation to the effect of an existing ' +
'animation, the existing animation\'s target effect should be set to null.');
@ -95,5 +93,15 @@ test(t => {
'existing animation, the target effect\'s timing is updated to reflect ' +
'the current time of the new animation.');
test(t => {
const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.updatePlaybackRate(2);
assert_equals(anim.playbackRate, 1);
anim.effect = null;
assert_equals(anim.playbackRate, 2);
}, 'Setting the target effect to null causes a pending playback rate to be'
+ ' applied');
</script>
</body>

View file

@ -1,6 +1,6 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Setting the timeline</title>
<title>Setting the timeline of an animation</title>
<link rel="help" href="https://drafts.csswg.org/web-animations/#setting-the-timeline">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
@ -81,7 +81,7 @@ test(t => {
}, 'After setting timeline on an idle animation with a sufficiently ancient'
+ ' start time it is finished');
promise_test(t => {
promise_test(async t => {
const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
null);
@ -94,14 +94,13 @@ promise_test(t => {
assert_true(animation.pending && animation.playState === 'running',
'Animation is still play-pending after setting timeline');
return animation.ready.then(() => {
assert_true(!animation.pending && animation.playState === 'running',
'Animation plays after it finishes pending');
});
await animation.ready;
assert_true(!animation.pending && animation.playState === 'running',
'Animation plays after it finishes pending');
}, 'After setting timeline on a play-pending animation it begins playing'
+ ' after pending');
promise_test(t => {
promise_test(async t => {
const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
null);
@ -116,10 +115,9 @@ promise_test(t => {
assert_true(animation.pending && animation.playState === 'paused',
'Animation is still pause-pending after setting timeline');
return animation.ready.then(() => {
assert_true(!animation.pending && animation.playState === 'paused',
'Animation pauses after it finishes pending');
});
await animation.ready;
assert_true(!animation.pending && animation.playState === 'paused',
'Animation pauses after it finishes pending');
}, 'After setting timeline on a pause-pending animation it becomes paused'
+ ' after pending');
@ -193,7 +191,7 @@ test(t => {
assert_true(animation.pending && animation.playState === 'running');
}, 'After clearing timeline on play-pending animation it is still pending');
promise_test(t => {
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
assert_true(animation.pending && animation.playState === 'running');
@ -201,9 +199,8 @@ promise_test(t => {
animation.timeline = document.timeline;
assert_true(animation.pending && animation.playState === 'running');
return animation.ready.then(() => {
assert_true(!animation.pending && animation.playState === 'running');
});
await animation.ready;
assert_true(!animation.pending && animation.playState === 'running');
}, 'After clearing and re-setting timeline on play-pending animation it'
+ ' begins to play');
@ -220,7 +217,7 @@ test(t => {
assert_true(animation.pending && animation.playState === 'paused');
}, 'After clearing timeline on a pause-pending animation it is still pending');
promise_test(t => {
promise_test(async t => {
const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
document.timeline);
@ -232,13 +229,12 @@ promise_test(t => {
animation.timeline = document.timeline;
assert_true(animation.pending && animation.playState === 'paused');
return animation.ready.then(() => {
assert_true(!animation.pending && animation.playState === 'paused');
});
await animation.ready;
assert_true(!animation.pending && animation.playState === 'paused');
}, 'After clearing and re-setting timeline on a pause-pending animation it'
+ ' completes pausing');
promise_test(t => {
promise_test(async t => {
const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
document.timeline);
@ -250,9 +246,8 @@ promise_test(t => {
animation.timeline = null;
animation.timeline = document.timeline;
return animation.ready.then(() => {
assert_times_equal(animation.startTime, initialStartTime);
});
await animation.ready;
assert_times_equal(animation.startTime, initialStartTime);
}, 'After clearing and re-setting timeline on an animation in the middle of'
+ ' an aborted pause, it continues playing using the same start time');

View file

@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Current time</title>
<link rel="help" href="https://drafts.csswg.org/web-animations/#current-time">
<title>The current time of an animation</title>
<link rel="help" href="https://drafts.csswg.org/web-animations/#the-current-time-of-an-animation">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@ -21,14 +21,13 @@ test(t => {
'state');
}, 'The current time returns the hold time when set');
promise_test(t => {
promise_test(async t => {
const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
null);
return animation.ready.then(() => {
assert_equals(animation.currentTime, null);
});
await animation.ready;
assert_equals(animation.currentTime, null);
}, 'The current time is unresolved when there is no associated timeline ' +
'(and no hold time is set)');
@ -62,14 +61,13 @@ test(t => {
}, 'The current time is calculated from the timeline time, start time and ' +
'playback rate');
promise_test(t => {
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.playbackRate = 0;
return animation.ready.then(() => waitForAnimationFrames(1))
.then(() => {
assert_time_equals_literal(animation.currentTime, 0);
});
await animation.ready;
await waitForAnimationFrames(1);
assert_time_equals_literal(animation.currentTime, 0);
}, 'The current time does not progress if playback rate is 0');
</script>

View file

@ -20,32 +20,33 @@
// (Also the start time is resolved and there is pending task)
// Did seek = false
promise_test(t => {
promise_test(async t => {
const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
// Here and in the following tests we wait until ready resolves as
// otherwise we don't have a resolved start time. We test the case
// where the start time is unresolved in a subsequent test.
return anim.ready.then(() => {
// Seek to 1ms before the target end and then wait 1ms
anim.currentTime = 100 * MS_PER_SEC - 1;
return waitForAnimationFramesWithDelay(1);
}).then(() => {
assert_equals(anim.currentTime, 100 * MS_PER_SEC,
'Hold time is set to target end clamping current time');
});
await anim.ready;
// Seek to 1ms before the target end and then wait 1ms
anim.currentTime = 100 * MS_PER_SEC - 1;
await waitForAnimationFramesWithDelay(1);
assert_equals(anim.currentTime, 100 * MS_PER_SEC,
'Hold time is set to target end clamping current time');
}, 'Updating the finished state when playing past end');
// Did seek = true
promise_test(t => {
promise_test(async t => {
const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
return anim.ready.then(() => {
anim.currentTime = 200 * MS_PER_SEC;
return waitForNextFrame();
}).then(() => {
assert_equals(anim.currentTime, 200 * MS_PER_SEC,
'Hold time is set so current time should NOT change');
});
await anim.ready;
anim.currentTime = 200 * MS_PER_SEC;
await waitForNextFrame();
assert_equals(anim.currentTime, 200 * MS_PER_SEC,
'Hold time is set so current time should NOT change');
}, 'Updating the finished state when seeking past end');
// Test current time == target end
@ -59,15 +60,15 @@ promise_test(t => {
// (on the subsequent tick the hold time will be set to the same value anyway).
// Did seek = true
promise_test(t => {
promise_test(async t => {
const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
return anim.ready.then(() => {
anim.currentTime = 100 * MS_PER_SEC;
return waitForNextFrame();
}).then(() => {
assert_equals(anim.currentTime, 100 * MS_PER_SEC,
'Hold time is set so current time should NOT change');
});
await anim.ready;
anim.currentTime = 100 * MS_PER_SEC;
await waitForNextFrame();
assert_equals(anim.currentTime, 100 * MS_PER_SEC,
'Hold time is set so current time should NOT change');
}, 'Updating the finished state when seeking exactly to end');
@ -75,49 +76,51 @@ promise_test(t => {
// (Also the start time is resolved and there is pending task)
// Did seek = false
promise_test(t => {
promise_test(async t => {
const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.playbackRate = -1;
anim.play(); // Make sure animation is not initially finished
return anim.ready.then(() => {
// Seek to 1ms before 0 and then wait 1ms
anim.currentTime = 1;
return waitForAnimationFramesWithDelay(1);
}).then(() => {
assert_equals(anim.currentTime, 0 * MS_PER_SEC,
'Hold time is set to zero clamping current time');
});
await anim.ready;
// Seek to 1ms before 0 and then wait 1ms
anim.currentTime = 1;
await waitForAnimationFramesWithDelay(1);
assert_equals(anim.currentTime, 0 * MS_PER_SEC,
'Hold time is set to zero clamping current time');
}, 'Updating the finished state when playing in reverse past zero');
// Did seek = true
promise_test(t => {
promise_test(async t => {
const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.playbackRate = -1;
anim.play();
return anim.ready.then(() => {
anim.currentTime = -100 * MS_PER_SEC;
return waitForNextFrame();
}).then(() => {
assert_equals(anim.currentTime, -100 * MS_PER_SEC,
'Hold time is set so current time should NOT change');
});
await anim.ready;
anim.currentTime = -100 * MS_PER_SEC;
await waitForNextFrame();
assert_equals(anim.currentTime, -100 * MS_PER_SEC,
'Hold time is set so current time should NOT change');
}, 'Updating the finished state when seeking a reversed animation past zero');
// As before, it's difficult to test current time == 0 for did seek = false but
// it doesn't really matter.
// Did seek = true
promise_test(t => {
promise_test(async t => {
const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.playbackRate = -1;
anim.play();
return anim.ready.then(() => {
anim.currentTime = 0;
return waitForNextFrame();
}).then(() => {
assert_equals(anim.currentTime, 0 * MS_PER_SEC,
'Hold time is set so current time should NOT change');
});
await anim.ready;
anim.currentTime = 0;
await waitForNextFrame();
assert_equals(anim.currentTime, 0 * MS_PER_SEC,
'Hold time is set so current time should NOT change');
}, 'Updating the finished state when seeking a reversed animation exactly'
+ ' to zero');
@ -126,41 +129,41 @@ promise_test(t => {
// (Also the start time is resolved and there is pending task)
// Did seek = false; playback rate > 0
promise_test(t => {
promise_test(async t => {
const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
// We want to test that the hold time is cleared so first we need to
// put the animation in a state where the hold time is set.
anim.finish();
return anim.ready.then(() => {
assert_equals(anim.currentTime, 100 * MS_PER_SEC,
'Hold time is initially set');
// Then extend the duration so that the hold time is cleared and on
// the next tick the current time will increase.
anim.effect.timing.duration *= 2;
return waitForNextFrame();
}).then(() => {
assert_greater_than(anim.currentTime, 100 * MS_PER_SEC,
'Hold time is not set so current time should increase');
});
await anim.ready;
assert_equals(anim.currentTime, 100 * MS_PER_SEC,
'Hold time is initially set');
// Then extend the duration so that the hold time is cleared and on
// the next tick the current time will increase.
anim.effect.timing.duration *= 2;
await waitForNextFrame();
assert_greater_than(anim.currentTime, 100 * MS_PER_SEC,
'Hold time is not set so current time should increase');
}, 'Updating the finished state when playing before end');
// Did seek = true; playback rate > 0
promise_test(t => {
promise_test(async t => {
const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.finish();
return anim.ready.then(() => {
anim.currentTime = 50 * MS_PER_SEC;
// When did seek = true, updating the finished state: (i) updates
// the animation's start time and (ii) clears the hold time.
// We can test both by checking that the currentTime is initially
// updated and then increases.
assert_equals(anim.currentTime, 50 * MS_PER_SEC, 'Start time is updated');
return waitForNextFrame();
}).then(() => {
assert_greater_than(anim.currentTime, 50 * MS_PER_SEC,
'Hold time is not set so current time should increase');
});
await anim.ready;
anim.currentTime = 50 * MS_PER_SEC;
// When did seek = true, updating the finished state: (i) updates
// the animation's start time and (ii) clears the hold time.
// We can test both by checking that the currentTime is initially
// updated and then increases.
assert_equals(anim.currentTime, 50 * MS_PER_SEC, 'Start time is updated');
await waitForNextFrame();
assert_greater_than(anim.currentTime, 50 * MS_PER_SEC,
'Hold time is not set so current time should increase');
}, 'Updating the finished state when seeking before end');
// Did seek = false; playback rate < 0
@ -177,69 +180,69 @@ promise_test(t => {
// will set did seek = true).
// Did seek = true; playback rate < 0
promise_test(t => {
promise_test(async t => {
const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.playbackRate = -1;
return anim.ready.then(() => {
anim.currentTime = 50 * MS_PER_SEC;
assert_equals(anim.currentTime, 50 * MS_PER_SEC, 'Start time is updated');
return waitForNextFrame();
}).then(() => {
assert_less_than(anim.currentTime, 50 * MS_PER_SEC,
'Hold time is not set so current time should decrease');
});
await anim.ready;
anim.currentTime = 50 * MS_PER_SEC;
assert_equals(anim.currentTime, 50 * MS_PER_SEC, 'Start time is updated');
await waitForNextFrame();
assert_less_than(anim.currentTime, 50 * MS_PER_SEC,
'Hold time is not set so current time should decrease');
}, 'Updating the finished state when seeking a reversed animation before end');
// CASE 4: playback rate == 0
// current time < 0
promise_test(t => {
promise_test(async t => {
const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.playbackRate = 0;
return anim.ready.then(() => {
anim.currentTime = -100 * MS_PER_SEC;
return waitForNextFrame();
}).then(() => {
assert_equals(anim.currentTime, -100 * MS_PER_SEC,
'Hold time should not be cleared so current time should'
+ ' NOT change');
});
await anim.ready;
anim.currentTime = -100 * MS_PER_SEC;
await waitForNextFrame();
assert_equals(anim.currentTime, -100 * MS_PER_SEC,
'Hold time should not be cleared so current time should'
+ ' NOT change');
}, 'Updating the finished state when playback rate is zero and the'
+ ' current time is less than zero');
// current time < target end
promise_test(t => {
promise_test(async t => {
const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.playbackRate = 0;
return anim.ready.then(() => {
anim.currentTime = 50 * MS_PER_SEC;
return waitForNextFrame();
}).then(() => {
assert_equals(anim.currentTime, 50 * MS_PER_SEC,
'Hold time should not be cleared so current time should'
+ ' NOT change');
});
await anim.ready;
anim.currentTime = 50 * MS_PER_SEC;
await waitForNextFrame();
assert_equals(anim.currentTime, 50 * MS_PER_SEC,
'Hold time should not be cleared so current time should'
+ ' NOT change');
}, 'Updating the finished state when playback rate is zero and the'
+ ' current time is less than end');
// current time > target end
promise_test(t => {
promise_test(async t => {
const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.playbackRate = 0;
return anim.ready.then(() => {
anim.currentTime = 200 * MS_PER_SEC;
return waitForNextFrame();
}).then(() => {
assert_equals(anim.currentTime, 200 * MS_PER_SEC,
'Hold time should not be cleared so current time should'
+ ' NOT change');
});
await anim.ready;
anim.currentTime = 200 * MS_PER_SEC;
await waitForNextFrame();
assert_equals(anim.currentTime, 200 * MS_PER_SEC,
'Hold time should not be cleared so current time should'
+ ' NOT change');
}, 'Updating the finished state when playback rate is zero and the'
+ ' current time is greater than end');
// CASE 5: current time unresolved
promise_test(t => {
promise_test(async t => {
const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.cancel();
// Trigger a change that will cause the "update the finished state"
@ -251,10 +254,10 @@ promise_test(t => {
// change to timing, but just in case an implementation defers that, let's
// wait a frame and check that the hold time / start time has still not been
// updated.
return waitForAnimationFrames(1).then(() => {
assert_equals(anim.currentTime, null,
'The animation hold time / start time should not be updated');
});
await waitForAnimationFrames(1);
assert_equals(anim.currentTime, null,
'The animation hold time / start time should not be updated');
}, 'Updating the finished state when current time is unresolved');
// CASE 6: has a pending task
@ -278,7 +281,7 @@ test(t => {
// CASE 7: start time unresolved
// Did seek = false
promise_test(t => {
promise_test(async t => {
const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.cancel();
// Make it so that only the start time is unresolved (to avoid overlapping
@ -287,12 +290,12 @@ promise_test(t => {
// Trigger a change that will cause the "update the finished state"
// procedure to run (did seek = false).
anim.effect.timing.duration = 200 * MS_PER_SEC;
return waitForAnimationFrames(1).then(() => {
assert_equals(anim.currentTime, 150 * MS_PER_SEC,
'The animation hold time should not be updated');
assert_equals(anim.startTime, null,
'The animation start time should not be updated');
});
await waitForAnimationFrames(1);
assert_equals(anim.currentTime, 150 * MS_PER_SEC,
'The animation hold time should not be updated');
assert_equals(anim.startTime, null,
'The animation start time should not be updated');
}, 'Updating the finished state when start time is unresolved and'
+ ' did seek = false');
@ -337,53 +340,61 @@ promise_test(t => {
}, 'Finish notification steps don\'t run when the animation seeks to finish'
+ ' and then seeks back again');
promise_test(t => {
promise_test(async t => {
const animation = createDiv(t).animate(null, 1);
return animation.ready.then(() => {
return waitForFinishEventAndPromise(animation);
});
await animation.ready;
return waitForFinishEventAndPromise(animation);
}, 'Finish notification steps run when the animation completes normally');
promise_test(t => {
promise_test(async t => {
const effect = new KeyframeEffectReadOnly(null, null, 1);
const animation = new Animation(effect, document.timeline);
animation.play();
await animation.ready;
return waitForFinishEventAndPromise(animation);
}, 'Finish notification steps run when an animation without a target'
+ ' effect completes normally');
promise_test(async t => {
const animation = createDiv(t).animate(null, 1);
return animation.ready.then(() => {
animation.currentTime = 10;
return waitForFinishEventAndPromise(animation);
});
await animation.ready;
animation.currentTime = 10;
return waitForFinishEventAndPromise(animation);
}, 'Finish notification steps run when the animation seeks past finish');
promise_test(t => {
promise_test(async t => {
const animation = createDiv(t).animate(null, 1);
return animation.ready.then(() => {
// Register for notifications now since once we seek away from being
// finished the 'finished' promise will be replaced.
const finishNotificationSteps = waitForFinishEventAndPromise(animation);
animation.finish();
animation.currentTime = 0;
animation.pause();
return finishNotificationSteps;
});
await animation.ready;
// Register for notifications now since once we seek away from being
// finished the 'finished' promise will be replaced.
const finishNotificationSteps = waitForFinishEventAndPromise(animation);
animation.finish();
animation.currentTime = 0;
animation.pause();
return finishNotificationSteps;
}, 'Finish notification steps run when the animation completes with .finish(),'
+ ' even if we then seek away');
promise_test(t => {
promise_test(async t => {
const animation = createDiv(t).animate(null, 1);
const initialFinishedPromise = animation.finished;
await animation.finished;
return animation.finished.then(target => {
animation.currentTime = 0;
assert_not_equals(initialFinishedPromise, animation.finished);
});
animation.currentTime = 0;
assert_not_equals(initialFinishedPromise, animation.finished);
}, 'Animation finished promise is replaced after seeking back to start');
promise_test(t => {
promise_test(async t => {
const animation = createDiv(t).animate(null, 1);
const initialFinishedPromise = animation.finished;
await animation.finished;
return animation.finished.then(target => {
animation.play();
assert_not_equals(initialFinishedPromise, animation.finished);
});
animation.play();
assert_not_equals(initialFinishedPromise, animation.finished);
}, 'Animation finished promise is replaced after replaying from start');
async_test(t => {