OLD | NEW |
| (Empty) |
1 <!DOCTYPE html> | |
2 <meta charset=utf-8> | |
3 <title>Tests for updating the finished state of an animation</title> | |
4 <link rel="help" href="https://w3c.github.io/web-animations/#updating-the-finish
ed-state"> | |
5 <script src="/resources/testharness.js"></script> | |
6 <script src="/resources/testharnessreport.js"></script> | |
7 <script src="../../testcommon.js"></script> | |
8 <body> | |
9 <div id="log"></div> | |
10 <script> | |
11 'use strict'; | |
12 | |
13 // | |
14 // NOTE TO THE POOR PERSON WHO HAS TO MERGE THIS WITH THE TEST OF THE SAME | |
15 // NAME FROM BLINK | |
16 // | |
17 // There is a pull request from Blink at: | |
18 // | |
19 // https://github.com/w3c/web-platform-tests/pull/3328 | |
20 // | |
21 // which this file will surely conflict with. | |
22 // | |
23 // However, those tests cover a different part of the same algorithm. They | |
24 // are mostly concerned with testing events and promises rather than the | |
25 // timing part of the algorithm. | |
26 // | |
27 // The tests below cover the first part of the algorithm. So, please keep both | |
28 // sets of tests and delete this comment. Preferably put the tests in this | |
29 // file first. | |
30 // | |
31 // Thank you! | |
32 // | |
33 | |
34 | |
35 // CASE 1: playback rate > 0 and current time >= target effect end | |
36 // (Also the start time is resolved and there is pending task) | |
37 | |
38 // Did seek = false | |
39 promise_test(function(t) { | |
40 var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); | |
41 | |
42 // Here and in the following tests we wait until ready resolves as | |
43 // otherwise we don't have a resolved start time. We test the case | |
44 // where the start time is unresolved in a subsequent test. | |
45 return anim.ready.then(function() { | |
46 // Seek to 1ms before the target end and wait a frame (> 16ms) | |
47 anim.currentTime = 100 * MS_PER_SEC - 1; | |
48 return waitForAnimationFrames(1); | |
49 }).then(function() { | |
50 assert_equals(anim.currentTime, 100 * MS_PER_SEC, | |
51 'Hold time is set to target end clamping current time'); | |
52 }); | |
53 }, 'Updating the finished state when playing past end'); | |
54 | |
55 // Did seek = true | |
56 promise_test(function(t) { | |
57 var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); | |
58 return anim.ready.then(function() { | |
59 anim.currentTime = 200 * MS_PER_SEC; | |
60 return waitForAnimationFrames(1); | |
61 }).then(function() { | |
62 assert_equals(anim.currentTime, 200 * MS_PER_SEC, | |
63 'Hold time is set so current time should NOT change'); | |
64 }); | |
65 }, 'Updating the finished state when seeking past end'); | |
66 | |
67 // Test current time == target end | |
68 // | |
69 // We can't really write a test for current time == target end with | |
70 // did seek = false since that would imply setting up an animation where | |
71 // the next animation frame time happens to exactly align with the target end. | |
72 // | |
73 // Fortunately, we don't need to test that case since even if the implementation | |
74 // fails to set the hold time on such a tick, it should be mostly unobservable | |
75 // (on the subsequent tick the hold time will be set to the same value anyway). | |
76 | |
77 // Did seek = true | |
78 promise_test(function(t) { | |
79 var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); | |
80 return anim.ready.then(function() { | |
81 anim.currentTime = 100 * MS_PER_SEC; | |
82 return waitForAnimationFrames(1); | |
83 }).then(function() { | |
84 assert_equals(anim.currentTime, 100 * MS_PER_SEC, | |
85 'Hold time is set so current time should NOT change'); | |
86 }); | |
87 }, 'Updating the finished state when seeking exactly to end'); | |
88 | |
89 | |
90 // CASE 2: playback rate < 0 and current time <= 0 | |
91 // (Also the start time is resolved and there is pending task) | |
92 | |
93 // Did seek = false | |
94 promise_test(function(t) { | |
95 var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); | |
96 anim.playbackRate = -1; | |
97 anim.play(); // Make sure animation is not initially finished | |
98 return anim.ready.then(function() { | |
99 // Seek to 1ms before 0 end and wait a frame (> 16ms) | |
100 anim.currentTime = 1; | |
101 return waitForAnimationFrames(1); | |
102 }).then(function() { | |
103 assert_equals(anim.currentTime, 0 * MS_PER_SEC, | |
104 'Hold time is set to zero clamping current time'); | |
105 }); | |
106 }, 'Updating the finished state when playing in reverse past zero'); | |
107 | |
108 // Did seek = true | |
109 promise_test(function(t) { | |
110 var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); | |
111 anim.playbackRate = -1; | |
112 anim.play(); | |
113 return anim.ready.then(function() { | |
114 anim.currentTime = -100 * MS_PER_SEC; | |
115 return waitForAnimationFrames(1); | |
116 }).then(function() { | |
117 assert_equals(anim.currentTime, -100 * MS_PER_SEC, | |
118 'Hold time is set so current time should NOT change'); | |
119 }); | |
120 }, 'Updating the finished state when seeking a reversed animation past zero'); | |
121 | |
122 // As before, it's difficult to test current time == 0 for did seek = false but | |
123 // it doesn't really matter. | |
124 | |
125 // Did seek = true | |
126 promise_test(function(t) { | |
127 var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); | |
128 anim.playbackRate = -1; | |
129 anim.play(); | |
130 return anim.ready.then(function() { | |
131 anim.currentTime = 0; | |
132 return waitForAnimationFrames(1); | |
133 }).then(function() { | |
134 assert_equals(anim.currentTime, 0 * MS_PER_SEC, | |
135 'Hold time is set so current time should NOT change'); | |
136 }); | |
137 }, 'Updating the finished state when seeking a reversed animation exactly' | |
138 + ' to zero'); | |
139 | |
140 // CASE 3: playback rate > 0 and current time < target end OR | |
141 // playback rate < 0 and current time > 0 | |
142 // (Also the start time is resolved and there is pending task) | |
143 | |
144 // Did seek = false; playback rate > 0 | |
145 promise_test(function(t) { | |
146 var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); | |
147 | |
148 // We want to test that the hold time is cleared so first we need to | |
149 // put the animation in a state where the hold time is set. | |
150 anim.finish(); | |
151 return anim.ready.then(function() { | |
152 assert_equals(anim.currentTime, 100 * MS_PER_SEC, | |
153 'Hold time is initially set'); | |
154 // Then extend the duration so that the hold time is cleared and on | |
155 // the next tick the current time will increase. | |
156 anim.effect.timing.duration *= 2; | |
157 return waitForAnimationFrames(1); | |
158 }).then(function() { | |
159 assert_greater_than(anim.currentTime, 100 * MS_PER_SEC, | |
160 'Hold time is not set so current time should increase'); | |
161 }); | |
162 }, 'Updating the finished state when playing before end'); | |
163 | |
164 // Did seek = true; playback rate > 0 | |
165 promise_test(function(t) { | |
166 var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); | |
167 anim.finish(); | |
168 return anim.ready.then(function() { | |
169 anim.currentTime = 50 * MS_PER_SEC; | |
170 // When did seek = true, updating the finished state: (i) updates | |
171 // the animation's start time and (ii) clears the hold time. | |
172 // We can test both by checking that the currentTime is initially | |
173 // updated and then increases. | |
174 assert_equals(anim.currentTime, 50 * MS_PER_SEC, 'Start time is updated'); | |
175 return waitForAnimationFrames(1); | |
176 }).then(function() { | |
177 assert_greater_than(anim.currentTime, 50 * MS_PER_SEC, | |
178 'Hold time is not set so current time should increase'); | |
179 }); | |
180 }, 'Updating the finished state when seeking before end'); | |
181 | |
182 // Did seek = false; playback rate < 0 | |
183 // | |
184 // Unfortunately it is not possible to test this case. We need to have | |
185 // a hold time set, a resolved start time, and then perform some | |
186 // operation that updates the finished state with did seek set to true. | |
187 // | |
188 // However, the only situation where this could arrive is when we | |
189 // replace the timeline and that procedure is likely to change. For all | |
190 // other cases we either have an unresolved start time (e.g. when | |
191 // paused), we don't have a set hold time (e.g. regular playback), or | |
192 // the current time is zero (and anything that gets us out of that state | |
193 // will set did seek = true). | |
194 | |
195 // Did seek = true; playback rate < 0 | |
196 promise_test(function(t) { | |
197 var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); | |
198 anim.playbackRate = -1; | |
199 return anim.ready.then(function() { | |
200 anim.currentTime = 50 * MS_PER_SEC; | |
201 assert_equals(anim.currentTime, 50 * MS_PER_SEC, 'Start time is updated'); | |
202 return waitForAnimationFrames(1); | |
203 }).then(function() { | |
204 assert_less_than(anim.currentTime, 50 * MS_PER_SEC, | |
205 'Hold time is not set so current time should decrease'); | |
206 }); | |
207 }, 'Updating the finished state when seeking a reversed animation before end'); | |
208 | |
209 // CASE 4: playback rate == 0 | |
210 | |
211 // current time < 0 | |
212 promise_test(function(t) { | |
213 var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); | |
214 anim.playbackRate = 0; | |
215 return anim.ready.then(function() { | |
216 anim.currentTime = -100 * MS_PER_SEC; | |
217 return waitForAnimationFrames(1); | |
218 }).then(function() { | |
219 assert_equals(anim.currentTime, -100 * MS_PER_SEC, | |
220 'Hold time should not be cleared so current time should' | |
221 + ' NOT change'); | |
222 }); | |
223 }, 'Updating the finished state when playback rate is zero and the' | |
224 + ' current time is less than zero'); | |
225 | |
226 // current time < target end | |
227 promise_test(function(t) { | |
228 var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); | |
229 anim.playbackRate = 0; | |
230 return anim.ready.then(function() { | |
231 anim.currentTime = 50 * MS_PER_SEC; | |
232 return waitForAnimationFrames(1); | |
233 }).then(function() { | |
234 assert_equals(anim.currentTime, 50 * MS_PER_SEC, | |
235 'Hold time should not be cleared so current time should' | |
236 + ' NOT change'); | |
237 }); | |
238 }, 'Updating the finished state when playback rate is zero and the' | |
239 + ' current time is less than end'); | |
240 | |
241 // current time > target end | |
242 promise_test(function(t) { | |
243 var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); | |
244 anim.playbackRate = 0; | |
245 return anim.ready.then(function() { | |
246 anim.currentTime = 200 * MS_PER_SEC; | |
247 return waitForAnimationFrames(1); | |
248 }).then(function() { | |
249 assert_equals(anim.currentTime, 200 * MS_PER_SEC, | |
250 'Hold time should not be cleared so current time should' | |
251 + ' NOT change'); | |
252 }); | |
253 }, 'Updating the finished state when playback rate is zero and the' | |
254 + ' current time is greater than end'); | |
255 | |
256 // CASE 5: current time unresolved | |
257 | |
258 promise_test(function(t) { | |
259 var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); | |
260 anim.cancel(); | |
261 // Trigger a change that will cause the "update the finished state" | |
262 // procedure to run. | |
263 anim.effect.timing.duration = 200 * MS_PER_SEC; | |
264 assert_equals(anim.currentTime, null, | |
265 'The animation hold time / start time should not be updated'); | |
266 // The "update the finished state" procedure is supposed to run after any | |
267 // change to timing, but just in case an implementation defers that, let's | |
268 // wait a frame and check that the hold time / start time has still not been | |
269 // updated. | |
270 return waitForAnimationFrames(1).then(function() { | |
271 assert_equals(anim.currentTime, null, | |
272 'The animation hold time / start time should not be updated'); | |
273 }); | |
274 }, 'Updating the finished state when current time is unresolved'); | |
275 | |
276 // CASE 6: has a pending task | |
277 | |
278 test(function(t) { | |
279 var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); | |
280 anim.cancel(); | |
281 anim.currentTime = 75 * MS_PER_SEC; | |
282 anim.play(); | |
283 // We now have a pending task and a resolved current time. | |
284 // | |
285 // In the next step we will adjust the timing so that the current time | |
286 // is greater than the target end. At this point the "update the finished | |
287 // state" procedure should run and if we fail to check for a pending task | |
288 // we will set the hold time to the target end, i.e. 50ms. | |
289 anim.effect.timing.duration = 50 * MS_PER_SEC; | |
290 assert_equals(anim.currentTime, 75 * MS_PER_SEC, | |
291 'Hold time should not be updated'); | |
292 }, 'Updating the finished state when there is a pending task'); | |
293 | |
294 // CASE 7: start time unresolved | |
295 | |
296 // Did seek = false | |
297 promise_test(function(t) { | |
298 var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); | |
299 anim.cancel(); | |
300 // Make it so that only the start time is unresolved (to avoid overlapping | |
301 // with the test case where current time is unresolved) | |
302 anim.currentTime = 150 * MS_PER_SEC; | |
303 // Trigger a change that will cause the "update the finished state" | |
304 // procedure to run (did seek = false). | |
305 anim.effect.timing.duration = 200 * MS_PER_SEC; | |
306 return waitForAnimationFrames(1).then(function() { | |
307 assert_equals(anim.currentTime, 150 * MS_PER_SEC, | |
308 'The animation hold time should not be updated'); | |
309 assert_equals(anim.startTime, null, | |
310 'The animation start time should not be updated'); | |
311 }); | |
312 }, 'Updating the finished state when start time is unresolved and' | |
313 + ' did seek = false'); | |
314 | |
315 // Did seek = true | |
316 test(function(t) { | |
317 var anim = createDiv(t).animate(null, 100 * MS_PER_SEC); | |
318 anim.cancel(); | |
319 anim.currentTime = 150 * MS_PER_SEC; | |
320 // Trigger a change that will cause the "update the finished state" | |
321 // procedure to run. | |
322 anim.currentTime = 50 * MS_PER_SEC; | |
323 assert_equals(anim.currentTime, 50 * MS_PER_SEC, | |
324 'The animation hold time should not be updated'); | |
325 assert_equals(anim.startTime, null, | |
326 'The animation start time should not be updated'); | |
327 }, 'Updating the finished state when start time is unresolved and' | |
328 + ' did seek = true'); | |
329 | |
330 </script> | |
331 </body> | |
OLD | NEW |