mirror of
https://github.com/servo/servo.git
synced 2025-08-09 15:35:34 +01:00
Update web-platform-tests to revision 8fed98324bc133df221d778c62cbff210d43b0ce
This commit is contained in:
parent
be902d56c0
commit
8a6476740e
246 changed files with 15482 additions and 1281 deletions
|
@ -0,0 +1,29 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>Applying the composited result</title>
|
||||
<link rel="help"
|
||||
href="https://drafts.csswg.org/web-animations-1/#applying-the-composited-result">
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
promise_test(async t => {
|
||||
const div = createDiv(t);
|
||||
div.style.marginLeft = '10px';
|
||||
const animation = div.animate(
|
||||
{ marginLeft: ['100px', '200px'] },
|
||||
100 * MS_PER_SEC
|
||||
);
|
||||
await animation.ready;
|
||||
|
||||
animation.finish();
|
||||
|
||||
const marginLeft = parseFloat(getComputedStyle(div).marginLeft);
|
||||
assert_equals(marginLeft, 10, 'The computed style should be reset');
|
||||
}, 'Finishing an animation that does not fill forwards causes its animation'
|
||||
+ ' style to be cleared');
|
||||
|
||||
</script>
|
|
@ -1,246 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Animation.finish</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animation-finish">
|
||||
<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';
|
||||
|
||||
const gKeyFrames = { 'marginLeft': ['100px', '200px'] };
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
|
||||
animation.playbackRate = 0;
|
||||
|
||||
assert_throws({name: 'InvalidStateError'}, () => {
|
||||
animation.finish();
|
||||
});
|
||||
}, 'Test exceptions when finishing non-running animation');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const animation = div.animate(gKeyFrames,
|
||||
{ duration : 100 * MS_PER_SEC,
|
||||
iterations : Infinity });
|
||||
|
||||
assert_throws({name: 'InvalidStateError'}, () => {
|
||||
animation.finish();
|
||||
});
|
||||
}, 'Test exceptions when finishing infinite animation');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
|
||||
animation.finish();
|
||||
|
||||
assert_equals(animation.currentTime, 100 * MS_PER_SEC,
|
||||
'After finishing, the currentTime should be set to the end ' +
|
||||
'of the active duration');
|
||||
}, 'Test finishing of animation');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
|
||||
// 1s past effect end
|
||||
animation.currentTime =
|
||||
animation.effect.getComputedTiming().endTime + 1 * MS_PER_SEC;
|
||||
animation.finish();
|
||||
|
||||
assert_equals(animation.currentTime, 100 * MS_PER_SEC,
|
||||
'After finishing, the currentTime should be set back to the ' +
|
||||
'end of the active duration');
|
||||
}, 'Test finishing of animation with a current time past the effect end');
|
||||
|
||||
promise_test(t => {
|
||||
const div = createDiv(t);
|
||||
const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
|
||||
animation.currentTime = 100 * MS_PER_SEC;
|
||||
return animation.finished.then(() => {
|
||||
animation.playbackRate = -1;
|
||||
animation.finish();
|
||||
|
||||
assert_equals(animation.currentTime, 0,
|
||||
'After finishing a reversed animation the currentTime ' +
|
||||
'should be set to zero');
|
||||
});
|
||||
}, 'Test finishing of reversed animation');
|
||||
|
||||
promise_test(t => {
|
||||
const div = createDiv(t);
|
||||
const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
|
||||
animation.currentTime = 100 * MS_PER_SEC;
|
||||
return animation.finished.then(() => {
|
||||
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');
|
||||
});
|
||||
}, 'Test finishing of reversed animation with a current time less than zero');
|
||||
|
||||
promise_test(t => {
|
||||
const div = createDiv(t);
|
||||
const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
|
||||
animation.pause();
|
||||
return animation.ready.then(() => {
|
||||
animation.finish();
|
||||
|
||||
assert_equals(animation.playState, 'finished',
|
||||
'The play state of a paused animation should become ' +
|
||||
'"finished" after finish() is called');
|
||||
assert_times_equal(animation.startTime,
|
||||
animation.timeline.currentTime - 100 * MS_PER_SEC,
|
||||
'The start time of a paused animation should be set ' +
|
||||
'after calling finish()');
|
||||
});
|
||||
}, 'Test finish() while paused');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
|
||||
animation.pause();
|
||||
// Update playbackRate so we can test that the calculated startTime
|
||||
// respects it
|
||||
animation.playbackRate = 2;
|
||||
// While animation is still pause-pending call finish()
|
||||
animation.finish();
|
||||
|
||||
assert_equals(animation.playState, 'finished',
|
||||
'The play state of a pause-pending animation should become ' +
|
||||
'"finished" after finish() is called');
|
||||
assert_times_equal(animation.startTime,
|
||||
animation.timeline.currentTime - 100 * MS_PER_SEC / 2,
|
||||
'The start time of a pause-pending animation should ' +
|
||||
'be set after calling finish()');
|
||||
}, 'Test finish() while pause-pending with positive playbackRate');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
|
||||
animation.pause();
|
||||
animation.playbackRate = -2;
|
||||
animation.finish();
|
||||
|
||||
assert_equals(animation.playState, 'finished',
|
||||
'The play state of a pause-pending animation should become ' +
|
||||
'"finished" after finish() is called');
|
||||
assert_equals(animation.startTime, animation.timeline.currentTime,
|
||||
'The start time of a pause-pending animation should be ' +
|
||||
'set after calling finish()');
|
||||
}, 'Test finish() while pause-pending with negative playbackRate');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
|
||||
animation.playbackRate = 0.5;
|
||||
animation.finish();
|
||||
|
||||
assert_equals(animation.playState, 'finished',
|
||||
'The play state of a play-pending animation should become ' +
|
||||
'"finished" after finish() is called');
|
||||
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 after calling finish()');
|
||||
}, 'Test finish() while play-pending');
|
||||
|
||||
// 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(t => {
|
||||
const div = createDiv(t);
|
||||
const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
|
||||
return animation.ready.then(() => {
|
||||
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 calling finish() the play ' +
|
||||
'state of an animation should become "finished" immediately');
|
||||
});
|
||||
}, 'Test finish() during aborted pause');
|
||||
|
||||
promise_test(t => {
|
||||
const div = createDiv(t);
|
||||
div.style.marginLeft = '10px';
|
||||
const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
|
||||
return animation.ready.then(() => {
|
||||
animation.finish();
|
||||
const marginLeft = parseFloat(getComputedStyle(div).marginLeft);
|
||||
|
||||
assert_equals(marginLeft, 10,
|
||||
'The computed style should be reset when finish() is ' +
|
||||
'called');
|
||||
});
|
||||
}, 'Test resetting of computed style');
|
||||
|
||||
promise_test(t => {
|
||||
const div = createDiv(t);
|
||||
const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
|
||||
let resolvedFinished = false;
|
||||
animation.finished.then(() => {
|
||||
resolvedFinished = true;
|
||||
});
|
||||
|
||||
return animation.ready.then(() => {
|
||||
animation.finish();
|
||||
}).then(() => {
|
||||
assert_true(resolvedFinished,
|
||||
'Animation.finished should be resolved soon after ' +
|
||||
'Animation.finish()');
|
||||
});
|
||||
}, 'Test finish() resolves finished promise synchronously');
|
||||
|
||||
promise_test(t => {
|
||||
const effect = new KeyframeEffectReadOnly(null, gKeyFrames, 100 * MS_PER_SEC);
|
||||
const animation = new Animation(effect, document.timeline);
|
||||
let resolvedFinished = false;
|
||||
animation.finished.then(() => {
|
||||
resolvedFinished = true;
|
||||
});
|
||||
|
||||
return animation.ready.then(() => {
|
||||
animation.finish();
|
||||
}).then(() => {
|
||||
assert_true(resolvedFinished,
|
||||
'Animation.finished should be resolved soon after ' +
|
||||
'Animation.finish()');
|
||||
});
|
||||
}, 'Test finish() resolves finished promise synchronously with an animation ' +
|
||||
'without a target');
|
||||
|
||||
promise_test(t => {
|
||||
const effect = new KeyframeEffectReadOnly(null, gKeyFrames, 100 * MS_PER_SEC);
|
||||
const animation = new Animation(effect, document.timeline);
|
||||
animation.play();
|
||||
|
||||
let resolvedFinished = false;
|
||||
animation.finished.then(() => {
|
||||
resolvedFinished = true;
|
||||
});
|
||||
|
||||
return animation.ready.then(() => {
|
||||
animation.currentTime = animation.effect.getComputedTiming().endTime - 1;
|
||||
return waitForAnimationFrames(2);
|
||||
}).then(() => {
|
||||
assert_true(resolvedFinished,
|
||||
'Animation.finished should be resolved soon after ' +
|
||||
'Animation finishes normally');
|
||||
});
|
||||
}, 'Test normally finished animation resolves finished promise synchronously ' +
|
||||
'with an animation without a target');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -29,6 +29,7 @@ interface Animation : EventTarget {
|
|||
void finish ();
|
||||
void play ();
|
||||
void pause ();
|
||||
void updatePlaybackRate (double playbackRate);
|
||||
void reverse ();
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Animation.playbackRate</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animation-playbackrate">
|
||||
<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';
|
||||
|
||||
function assert_playbackrate(animation,
|
||||
previousAnimationCurrentTime,
|
||||
previousTimelineCurrentTime,
|
||||
description) {
|
||||
const animationCurrentTimeDifference =
|
||||
animation.currentTime - previousAnimationCurrentTime;
|
||||
const timelineCurrentTimeDifference =
|
||||
animation.timeline.currentTime - previousTimelineCurrentTime;
|
||||
|
||||
assert_times_equal(animationCurrentTimeDifference,
|
||||
timelineCurrentTimeDifference * animation.playbackRate,
|
||||
description);
|
||||
}
|
||||
|
||||
promise_test(t => {
|
||||
const div = createDiv(t);
|
||||
const animation = div.animate(null, 100 * MS_PER_SEC);
|
||||
return animation.ready.then(() => {
|
||||
animation.currentTime = 7 * MS_PER_SEC; // ms
|
||||
animation.playbackRate = 0.5;
|
||||
|
||||
assert_equals(animation.currentTime, 7 * MS_PER_SEC,
|
||||
'Reducing Animation.playbackRate should not change the currentTime ' +
|
||||
'of a playing animation');
|
||||
animation.playbackRate = 2;
|
||||
assert_equals(animation.currentTime, 7 * MS_PER_SEC,
|
||||
'Increasing Animation.playbackRate should not change the currentTime ' +
|
||||
'of a playing animation');
|
||||
});
|
||||
}, 'Test the initial effect of setting playbackRate on currentTime');
|
||||
|
||||
promise_test(t => {
|
||||
const div = createDiv(t);
|
||||
const animation = div.animate(null, 100 * MS_PER_SEC);
|
||||
animation.playbackRate = 2;
|
||||
let previousTimelineCurrentTime;
|
||||
let previousAnimationCurrentTime;
|
||||
return animation.ready.then(() => {
|
||||
previousAnimationCurrentTime = animation.currentTime;
|
||||
previousTimelineCurrentTime = animation.timeline.currentTime;
|
||||
return waitForAnimationFrames(1);
|
||||
}).then(() => {
|
||||
assert_playbackrate(animation,
|
||||
previousAnimationCurrentTime,
|
||||
previousTimelineCurrentTime,
|
||||
'animation.currentTime should be 2 times faster than timeline.');
|
||||
});
|
||||
}, 'Test the effect of setting playbackRate on currentTime');
|
||||
|
||||
promise_test(t => {
|
||||
const div = createDiv(t);
|
||||
const animation = div.animate(null, 100 * MS_PER_SEC);
|
||||
animation.playbackRate = 2;
|
||||
let previousTimelineCurrentTime;
|
||||
let previousAnimationCurrentTime;
|
||||
return animation.ready.then(() => {
|
||||
previousAnimationCurrentTime = animation.currentTime;
|
||||
previousTimelineCurrentTime = animation.timeline.currentTime;
|
||||
animation.playbackRate = 1;
|
||||
return waitForAnimationFrames(1);
|
||||
}).then(() => {
|
||||
assert_equals(animation.playbackRate, 1,
|
||||
'sanity check: animation.playbackRate is still 1.');
|
||||
assert_playbackrate(animation,
|
||||
previousAnimationCurrentTime,
|
||||
previousTimelineCurrentTime,
|
||||
'animation.currentTime should be the same speed as timeline now.');
|
||||
});
|
||||
}, 'Test the effect of setting playbackRate while playing animation');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -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 => {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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');
|
||||
|
|
@ -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>
|
|
@ -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 => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue