[Web Animations] Turn Web Animations with CSS integration on for test runners
[WebKit-https.git] / LayoutTests / imported / mozilla / css-animations / test_animation-currenttime.html
1 <!doctype html>
2 <html>
3   <head>
4     <meta charset=utf-8>
5     <title>Tests for the effect of setting a CSS animation's
6            Animation.currentTime</title>
7     <style>
8
9 .animated-div {
10   margin-left: 10px;
11   /* Make it easier to calculate expected values: */
12   animation-timing-function: linear ! important;
13 }
14
15 @keyframes anim {
16   from { margin-left: 100px; }
17   to { margin-left: 200px; }
18 }
19
20     </style>
21     <script src="../../../resources/testharness.js"></script>
22     <script src="../../../resources/testharnessreport.js"></script>
23     <script src="../resources/testcommon.js"></script>
24   </head>
25   <body>
26     <div id="log"></div>
27     <script type="text/javascript">
28
29 'use strict';
30
31 // TODO: We should separate this test(Testing for CSS Animation events /
32 // Testing for currentTime of Web Animation).
33 // e.g:
34 //  CSS Animation events test :
35 //    - check the firing an event using Animation.currentTime
36 //  The current Time of Web Animation test :
37 //    - check an current time value on several situation(init / processing..)
38 //    - Based on W3C Spec, check the behavior of setting current time.
39
40 // TODO: Once the computedTiming property is implemented, add checks to the
41 // checker helpers to ensure that computedTiming's properties are updated as
42 // expected.
43 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1108055
44
45 const CSS_ANIM_EVENTS =
46   ['animationstart', 'animationiteration', 'animationend'];
47
48 test(function(t)
49 {
50   var div = addDiv(t, {'class': 'animated-div'});
51   div.style.animation = "anim 100s";
52   var animation = div.getAnimations()[0];
53
54   // Animations shouldn't start until the next paint tick, so:
55   assert_equals(animation.currentTime, 0,
56     'Animation.currentTime should be zero when an animation ' +
57     'is initially created');
58
59   // Make sure the animation is running before we set the current time.
60   animation.startTime = animation.timeline.currentTime;
61
62   animation.currentTime = 50 * MS_PER_SEC;
63   assert_time_equals_literal(animation.currentTime, 50 * MS_PER_SEC,
64     'Check setting of currentTime actually works');
65 }, 'Sanity test to check round-tripping assigning to new animation\'s ' +
66    'currentTime');
67
68 promise_test(function(t) {
69   var div = addDiv(t, {'class': 'animated-div'});
70   var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
71   div.style.animation = "anim 100s 100s";
72   var animation = div.getAnimations()[0];
73
74   return animation.ready.then(function() {
75     // the 0.0001 here is for rounding error
76     assert_less_than_equal(animation.currentTime,
77       animation.timeline.currentTime - animation.startTime + 0.0001,
78       'Animation.currentTime should be less than the local time ' +
79       'equivalent of the timeline\'s currentTime on the first paint tick ' +
80       'after animation creation');
81
82     animation.currentTime = 100 * MS_PER_SEC;
83     return eventWatcher.wait_for('animationstart');
84   }).then(function() {
85     animation.currentTime = 200 * MS_PER_SEC;
86     return eventWatcher.wait_for('animationend');
87   });
88 }, 'Skipping forward through animation');
89
90 promise_test(function(t) {
91   var div = addDiv(t, {'class': 'animated-div'});
92   var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
93   div.style.animation = "anim 100s 100s";
94   var animation = div.getAnimations()[0];
95   animation.currentTime = 200 * MS_PER_SEC;
96   var previousTimelineTime = animation.timeline.currentTime;
97
98   return eventWatcher.wait_for(['animationstart',
99                                 'animationend']).then(function() {
100     assert_true(document.timeline.currentTime - previousTimelineTime <
101                 100 * MS_PER_SEC,
102                 'Sanity check that seeking worked rather than the events ' +
103                 'firing after normal playback through the very long ' +
104                 'animation duration');
105
106     animation.currentTime = 150 * MS_PER_SEC;
107     return eventWatcher.wait_for('animationstart');
108   }).then(function() {
109     animation.currentTime = 0;
110     return eventWatcher.wait_for('animationend');
111   });
112 }, 'Skipping backwards through animation');
113
114 // Next we have multiple tests to check that redundant currentTime changes do
115 // NOT dispatch events. It's impossible to distinguish between events not being
116 // dispatched and events just taking an incredibly long time to dispatch
117 // without waiting an infinitely long time. Obviously we don't want to do that
118 // (block this test from finishing forever), so instead we just listen for
119 // events until two animation frames (i.e. requestAnimationFrame callbacks)
120 // have happened, then assume that no events will ever be dispatched for the
121 // redundant changes if no events were detected in that time.
122
123 promise_test(function(t) {
124   var div = addDiv(t, {'class': 'animated-div'});
125   var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
126   div.style.animation = "anim 100s 100s";
127   var animation = div.getAnimations()[0];
128
129   animation.currentTime = 150 * MS_PER_SEC;
130   animation.currentTime = 50 * MS_PER_SEC;
131
132   return waitForAnimationFrames(2);
133 }, 'Redundant change, before -> active, then back');
134
135 promise_test(function(t) {
136   var div = addDiv(t, {'class': 'animated-div'});
137   var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
138   div.style.animation = "anim 100s 100s";
139   var animation = div.getAnimations()[0];
140
141   animation.currentTime = 250 * MS_PER_SEC;
142   animation.currentTime = 50 * MS_PER_SEC;
143
144   return waitForAnimationFrames(2);
145 }, 'Redundant change, before -> after, then back');
146
147 promise_test(function(t) {
148   var div = addDiv(t, {'class': 'animated-div'});
149   var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
150   div.style.animation = "anim 100s 100s";
151   var animation = div.getAnimations()[0];
152
153   var retPromise = eventWatcher.wait_for('animationstart').then(function() {
154     animation.currentTime = 50 * MS_PER_SEC;
155     animation.currentTime = 150 * MS_PER_SEC;
156
157     return waitForAnimationFrames(2);
158   });
159   // get us into the initial state:
160   animation.currentTime = 150 * MS_PER_SEC;
161
162   return retPromise;
163 }, 'Redundant change, active -> before, then back');
164
165 promise_test(function(t) {
166   var div = addDiv(t, {'class': 'animated-div'});
167   var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
168   div.style.animation = "anim 100s 100s";
169   var animation = div.getAnimations()[0];
170
171   var retPromise = eventWatcher.wait_for('animationstart').then(function() {
172     animation.currentTime = 250 * MS_PER_SEC;
173     animation.currentTime = 150 * MS_PER_SEC;
174
175     return waitForAnimationFrames(2);
176   });
177   // get us into the initial state:
178   animation.currentTime = 150 * MS_PER_SEC;
179
180   return retPromise;
181 }, 'Redundant change, active -> after, then back');
182
183 promise_test(function(t) {
184   var div = addDiv(t, {'class': 'animated-div'});
185   var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
186   div.style.animation = "anim 100s 100s";
187   var animation = div.getAnimations()[0];
188
189   var retPromise =  eventWatcher.wait_for(['animationstart',
190                                            'animationend']).then(function() {
191     animation.currentTime = 50 * MS_PER_SEC;
192     animation.currentTime = 250 * MS_PER_SEC;
193
194     return waitForAnimationFrames(2);
195   });
196   // get us into the initial state:
197   animation.currentTime = 250 * MS_PER_SEC;
198
199   return retPromise;
200 }, 'Redundant change, after -> before, then back');
201
202 promise_test(function(t) {
203   var div = addDiv(t, {'class': 'animated-div'});
204   var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
205   div.style.animation = "anim 100s 100s";
206   var animation = div.getAnimations()[0];
207
208   var retPromise =  eventWatcher.wait_for(['animationstart',
209                                            'animationend']).then(function() {
210     animation.currentTime = 150 * MS_PER_SEC;
211     animation.currentTime = 250 * MS_PER_SEC;
212
213     return waitForAnimationFrames(2);
214   });
215   // get us into the initial state:
216   animation.currentTime = 250 * MS_PER_SEC;
217
218   return retPromise;
219 }, 'Redundant change, after -> active, then back');
220
221 promise_test(function(t) {
222   var div = addDiv(t, {'class': 'animated-div'});
223   var eventWatcher = new EventWatcher(t, div, CSS_ANIM_EVENTS);
224   div.style.animation = "anim 100s"
225   var animation = div.getAnimations()[0];
226
227   animation.pause();
228   animation.currentTime = 150 * MS_PER_SEC;
229
230   return eventWatcher.wait_for(['animationstart',
231                                 'animationend']).then(function() {
232     animation.currentTime = 50 * MS_PER_SEC;
233     return eventWatcher.wait_for('animationstart');
234   });
235 }, 'Seeking finished -> paused dispatches animationstart');
236
237 promise_test(function(t) {
238   var div = addDiv(t, {'class': 'animated-div'});
239   div.style.animation = "anim 100s";
240
241   var animation = div.getAnimations()[0];
242
243   return animation.ready.then(function() {
244     var exception;
245     try {
246       animation.currentTime = null;
247     } catch (e) {
248       exception = e;
249     }
250     assert_equals(exception.name, 'TypeError',
251       'Expect TypeError exception on trying to set ' +
252       'Animation.currentTime to null');
253   });
254 }, 'Setting currentTime to null');
255
256 promise_test(function(t) {
257   var div = addDiv(t, {'class': 'animated-div'});
258   div.style.animation = 'anim 100s';
259
260   var animation = div.getAnimations()[0];
261   var pauseTime;
262
263   return animation.ready.then(function() {
264     assert_not_equals(animation.currentTime, null,
265       'Animation.currentTime not null on ready Promise resolve');
266     animation.pause();
267     return animation.ready;
268   }).then(function() {
269     pauseTime = animation.currentTime;
270     return waitForFrame();
271   }).then(function() {
272     assert_equals(animation.currentTime, pauseTime,
273       'Animation.currentTime is unchanged after pausing');
274   });
275 }, 'Animation.currentTime after pausing');
276
277 promise_test(function(t) {
278   var div = addDiv(t, {'class': 'animated-div'});
279   div.style.animation = "anim 100s";
280   var animation = div.getAnimations()[0];
281
282   return animation.ready.then(function() {
283     // just before animation ends:
284     animation.currentTime = 100 * MS_PER_SEC - 1;
285     return waitForAnimationFrames(2);
286   }).then(function() {
287     assert_equals(animation.currentTime, 100 * MS_PER_SEC,
288       'Animation.currentTime should not continue to increase after the ' +
289       'animation has finished');
290   });
291 }, 'Animation.currentTime clamping');
292
293 promise_test(function(t) {
294   var div = addDiv(t, {'class': 'animated-div'});
295   div.style.animation = "anim 100s";
296   var animation = div.getAnimations()[0];
297
298   return animation.ready.then(function() {
299     // play backwards:
300     animation.playbackRate = -1;
301
302     // just before animation ends (at the "start"):
303     animation.currentTime = 1;
304
305     return waitForAnimationFrames(2);
306   }).then(function() {
307     assert_equals(animation.currentTime, 0,
308       'Animation.currentTime should not continue to decrease after an ' +
309       'animation running in reverse has finished and currentTime is zero');
310   });
311 }, 'Animation.currentTime clamping for reversed animation');
312
313 test(function(t) {
314   var div = addDiv(t, {'class': 'animated-div'});
315   div.style.animation = 'anim 100s';
316   var animation = div.getAnimations()[0];
317   animation.cancel();
318
319   assert_equals(animation.currentTime, null,
320                 'The currentTime of a cancelled animation should be null');
321 }, 'Animation.currentTime after cancelling');
322
323 promise_test(function(t) {
324   var div = addDiv(t, {'class': 'animated-div'});
325   div.style.animation = 'anim 100s';
326   var animation = div.getAnimations()[0];
327
328   return animation.ready.then(function() {
329     animation.finish();
330
331     // Initiate a pause then abort it
332     animation.pause();
333     animation.play();
334
335     // Wait to return to running state
336     return animation.ready;
337   }).then(function() {
338     assert_true(animation.currentTime < 100 * 1000,
339                 'After aborting a pause when finished, the currentTime should'
340                 + ' jump back towards the start of the animation');
341   });
342 }, 'After aborting a pause when finished, the call to play() should rewind'
343    + ' the current time');
344
345     </script>
346   </body>
347 </html>