Index: third_party/WebKit/LayoutTests/imported/wpt/web-animations/timing-model/animations/updating-the-finished-state.html |
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/timing-model/animations/updating-the-finished-state.html b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/timing-model/animations/updating-the-finished-state.html |
new file mode 100644 |
index 0000000000000000000000000000000000000000..fc83e1e3590c97ae5f628128f98bf3af73ef7211 |
--- /dev/null |
+++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/timing-model/animations/updating-the-finished-state.html |
@@ -0,0 +1,331 @@ |
+<!DOCTYPE html> |
+<meta charset=utf-8> |
+<title>Tests for updating the finished state of an animation</title> |
+<link rel="help" href="https://w3c.github.io/web-animations/#updating-the-finished-state"> |
+<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'; |
+ |
+// |
+// NOTE TO THE POOR PERSON WHO HAS TO MERGE THIS WITH THE TEST OF THE SAME |
+// NAME FROM BLINK |
+// |
+// There is a pull request from Blink at: |
+// |
+// https://github.com/w3c/web-platform-tests/pull/3328 |
+// |
+// which this file will surely conflict with. |
+// |
+// However, those tests cover a different part of the same algorithm. They |
+// are mostly concerned with testing events and promises rather than the |
+// timing part of the algorithm. |
+// |
+// The tests below cover the first part of the algorithm. So, please keep both |
+// sets of tests and delete this comment. Preferably put the tests in this |
+// file first. |
+// |
+// Thank you! |
+// |
+ |
+ |
+// CASE 1: playback rate > 0 and current time >= target effect end |
+// (Also the start time is resolved and there is pending task) |
+ |
+// Did seek = false |
+promise_test(function(t) { |
+ var 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(function() { |
+ // Seek to 1ms before the target end and wait a frame (> 16ms) |
+ anim.currentTime = 100 * MS_PER_SEC - 1; |
+ return waitForAnimationFrames(1); |
+ }).then(function() { |
+ 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(function(t) { |
+ var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); |
+ return anim.ready.then(function() { |
+ anim.currentTime = 200 * MS_PER_SEC; |
+ return waitForAnimationFrames(1); |
+ }).then(function() { |
+ 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 |
+// |
+// We can't really write a test for current time == target end with |
+// did seek = false since that would imply setting up an animation where |
+// the next animation frame time happens to exactly align with the target end. |
+// |
+// Fortunately, we don't need to test that case since even if the implementation |
+// fails to set the hold time on such a tick, it should be mostly unobservable |
+// (on the subsequent tick the hold time will be set to the same value anyway). |
+ |
+// Did seek = true |
+promise_test(function(t) { |
+ var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); |
+ return anim.ready.then(function() { |
+ anim.currentTime = 100 * MS_PER_SEC; |
+ return waitForAnimationFrames(1); |
+ }).then(function() { |
+ 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'); |
+ |
+ |
+// CASE 2: playback rate < 0 and current time <= 0 |
+// (Also the start time is resolved and there is pending task) |
+ |
+// Did seek = false |
+promise_test(function(t) { |
+ var 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(function() { |
+ // Seek to 1ms before 0 end and wait a frame (> 16ms) |
+ anim.currentTime = 1; |
+ return waitForAnimationFrames(1); |
+ }).then(function() { |
+ 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(function(t) { |
+ var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); |
+ anim.playbackRate = -1; |
+ anim.play(); |
+ return anim.ready.then(function() { |
+ anim.currentTime = -100 * MS_PER_SEC; |
+ return waitForAnimationFrames(1); |
+ }).then(function() { |
+ 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(function(t) { |
+ var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); |
+ anim.playbackRate = -1; |
+ anim.play(); |
+ return anim.ready.then(function() { |
+ anim.currentTime = 0; |
+ return waitForAnimationFrames(1); |
+ }).then(function() { |
+ 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'); |
+ |
+// CASE 3: playback rate > 0 and current time < target end OR |
+// playback rate < 0 and current time > 0 |
+// (Also the start time is resolved and there is pending task) |
+ |
+// Did seek = false; playback rate > 0 |
+promise_test(function(t) { |
+ var 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(function() { |
+ 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 waitForAnimationFrames(1); |
+ }).then(function() { |
+ 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(function(t) { |
+ var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); |
+ anim.finish(); |
+ return anim.ready.then(function() { |
+ 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 waitForAnimationFrames(1); |
+ }).then(function() { |
+ 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 |
+// |
+// Unfortunately it is not possible to test this case. We need to have |
+// a hold time set, a resolved start time, and then perform some |
+// operation that updates the finished state with did seek set to true. |
+// |
+// However, the only situation where this could arrive is when we |
+// replace the timeline and that procedure is likely to change. For all |
+// other cases we either have an unresolved start time (e.g. when |
+// paused), we don't have a set hold time (e.g. regular playback), or |
+// the current time is zero (and anything that gets us out of that state |
+// will set did seek = true). |
+ |
+// Did seek = true; playback rate < 0 |
+promise_test(function(t) { |
+ var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); |
+ anim.playbackRate = -1; |
+ return anim.ready.then(function() { |
+ anim.currentTime = 50 * MS_PER_SEC; |
+ assert_equals(anim.currentTime, 50 * MS_PER_SEC, 'Start time is updated'); |
+ return waitForAnimationFrames(1); |
+ }).then(function() { |
+ 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(function(t) { |
+ var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); |
+ anim.playbackRate = 0; |
+ return anim.ready.then(function() { |
+ anim.currentTime = -100 * MS_PER_SEC; |
+ return waitForAnimationFrames(1); |
+ }).then(function() { |
+ 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(function(t) { |
+ var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); |
+ anim.playbackRate = 0; |
+ return anim.ready.then(function() { |
+ anim.currentTime = 50 * MS_PER_SEC; |
+ return waitForAnimationFrames(1); |
+ }).then(function() { |
+ 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(function(t) { |
+ var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); |
+ anim.playbackRate = 0; |
+ return anim.ready.then(function() { |
+ anim.currentTime = 200 * MS_PER_SEC; |
+ return waitForAnimationFrames(1); |
+ }).then(function() { |
+ 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(function(t) { |
+ var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); |
+ anim.cancel(); |
+ // Trigger a change that will cause the "update the finished state" |
+ // procedure to run. |
+ anim.effect.timing.duration = 200 * MS_PER_SEC; |
+ assert_equals(anim.currentTime, null, |
+ 'The animation hold time / start time should not be updated'); |
+ // The "update the finished state" procedure is supposed to run after any |
+ // 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(function() { |
+ 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 |
+ |
+test(function(t) { |
+ var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); |
+ anim.cancel(); |
+ anim.currentTime = 75 * MS_PER_SEC; |
+ anim.play(); |
+ // We now have a pending task and a resolved current time. |
+ // |
+ // In the next step we will adjust the timing so that the current time |
+ // is greater than the target end. At this point the "update the finished |
+ // state" procedure should run and if we fail to check for a pending task |
+ // we will set the hold time to the target end, i.e. 50ms. |
+ anim.effect.timing.duration = 50 * MS_PER_SEC; |
+ assert_equals(anim.currentTime, 75 * MS_PER_SEC, |
+ 'Hold time should not be updated'); |
+}, 'Updating the finished state when there is a pending task'); |
+ |
+// CASE 7: start time unresolved |
+ |
+// Did seek = false |
+promise_test(function(t) { |
+ var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); |
+ anim.cancel(); |
+ // Make it so that only the start time is unresolved (to avoid overlapping |
+ // with the test case where current time is unresolved) |
+ anim.currentTime = 150 * MS_PER_SEC; |
+ // 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(function() { |
+ 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'); |
+ |
+// Did seek = true |
+test(function(t) { |
+ var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); |
+ anim.cancel(); |
+ anim.currentTime = 150 * MS_PER_SEC; |
+ // Trigger a change that will cause the "update the finished state" |
+ // procedure to run. |
+ anim.currentTime = 50 * MS_PER_SEC; |
+ assert_equals(anim.currentTime, 50 * 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 = true'); |
+ |
+</script> |
+</body> |