[Web Animations] Turn Web Animations with CSS integration on for test runners
[WebKit-https.git] / LayoutTests / imported / mozilla / css-transitions / test_event-dispatch.html
1 <!doctype html>
2 <meta charset=utf-8>
3 <title>Tests for CSS-Transition events</title>
4 <link rel="help" href="https://drafts.csswg.org/css-transitions-2/#transition-events">
5 <script src="../../../resources/testharness.js"></script>
6 <script src="../../../resources/testharnessreport.js"></script>
7 <script src="../resources/testcommon.js"></script>
8 <body>
9 <div id="log"></div>
10 <script>
11 'use strict';
12
13 /**
14  * Helper class to record the elapsedTime member of each event.
15  * The EventWatcher class in testharness.js allows us to wait on
16  * multiple events in a certain order but only records the event
17  * parameters of the most recent event.
18  */
19 function TransitionEventHandler(target) {
20   this.target = target;
21   this.target.ontransitionrun = evt => {
22     this.transitionrun = evt.elapsedTime;
23   };
24   this.target.ontransitionstart = evt => {
25     this.transitionstart = evt.elapsedTime;
26   };
27   this.target.ontransitionend = evt => {
28     this.transitionend = evt.elapsedTime;
29   };
30   this.target.ontransitioncancel = evt => {
31     this.transitioncancel = evt.elapsedTime;
32   };
33 }
34
35 TransitionEventHandler.prototype.clear = () => {
36   this.transitionrun    = undefined;
37   this.transitionstart  = undefined;
38   this.transitionend    = undefined;
39   this.transitioncancel = undefined;
40 };
41
42 function setupTransition(t, transitionStyle) {
43   const div = addDiv(t, { style: 'transition: ' + transitionStyle });
44   // Note that this TransitionEventHandler should be created before EventWatcher
45   // to capture all events in the handler prior to the EventWatcher since
46   // testharness.js proceeds when the EventWatcher received watching events.
47   const handler = new TransitionEventHandler(div);
48   const watcher = new EventWatcher(t, div, [ 'transitionrun',
49                                            'transitionstart',
50                                            'transitionend',
51                                            'transitioncancel' ]);
52   flushComputedStyle(div);
53
54   div.style.marginLeft = '100px';
55   const transition = div.getAnimations()[0];
56
57   return { transition, watcher, div, handler };
58 }
59
60 // On the next frame (i.e. when events are queued), whether or not the
61 // transition is still pending depends on the implementation.
62 promise_test(t => {
63   const { transition, watcher } =
64     setupTransition(t, 'margin-left 100s 100s');
65   return watcher.wait_for('transitionrun').then(evt => {
66     assert_equals(evt.elapsedTime, 0.0);
67   });
68 }, 'Idle -> Pending or Before');
69
70 promise_test(t => {
71   const { transition, watcher } =
72     setupTransition(t, 'margin-left 100s 100s');
73   // Force the transition to leave the idle phase
74   transition.startTime = document.timeline.currentTime;
75   return watcher.wait_for('transitionrun').then(evt => {
76     assert_equals(evt.elapsedTime, 0.0);
77   });
78 }, 'Idle -> Before');
79
80 promise_test(t => {
81   const { transition, watcher, div, handler } =
82     setupTransition(t, 'margin-left 100s 100s');
83
84   // Seek to Active phase.
85   transition.currentTime = 100 * MS_PER_SEC;
86   // transition.pause();
87   return watcher.wait_for([ 'transitionrun',
88                             'transitionstart' ]).then(evt => {
89     assert_equals(handler.transitionrun, 0.0);
90     assert_equals(handler.transitionstart, 0.0);
91   });
92 }, 'Idle or Pending -> Active');
93
94 promise_test(t => {
95   const { transition, watcher, div, handler } =
96     setupTransition(t, 'margin-left 100s 100s');
97
98   // Seek to After phase.
99   transition.finish();
100   return watcher.wait_for([ 'transitionrun',
101                             'transitionstart',
102                             'transitionend' ]).then(evt => {
103     assert_equals(handler.transitionrun, 0.0);
104     assert_equals(handler.transitionstart, 0.0);
105     assert_equals(handler.transitionend, 100.0);
106   });
107 }, 'Idle or Pending -> After');
108
109 // Timeout
110 promise_test(t => {
111   const { transition, watcher, div } =
112     setupTransition(t, 'margin-left 100s 100s');
113
114   return Promise.all([ watcher.wait_for('transitionrun'),
115                        transition.ready ]).then(() => {
116     // Make idle
117     div.style.display = 'none';
118     flushComputedStyle(div);
119     return watcher.wait_for('transitioncancel');
120   }).then(evt => {
121     assert_equals(evt.elapsedTime, 0.0);
122   });
123 }, 'Before -> Idle (display: none)');
124
125 promise_test(t => {
126   const { transition, watcher } =
127     setupTransition(t, 'margin-left 100s 100s');
128
129   return Promise.all([ watcher.wait_for('transitionrun'),
130                        transition.ready ]).then(() => {
131     // Make idle
132     transition.timeline = null;
133     return watcher.wait_for('transitioncancel');
134   }).then(evt => {
135     assert_equals(evt.elapsedTime, 0.0);
136   });
137 }, 'Before -> Idle (Animation.timeline = null)');
138
139 promise_test(t => {
140   const { transition, watcher } =
141     setupTransition(t, 'margin-left 100s 100s');
142
143   return Promise.all([ watcher.wait_for('transitionrun'),
144                        transition.ready ]).then(() => {
145     transition.currentTime = 100 * MS_PER_SEC;
146     return watcher.wait_for('transitionstart');
147   }).then(evt => {
148     assert_equals(evt.elapsedTime, 0.0);
149   });
150 }, 'Before -> Active');
151
152 promise_test(t => {
153   const { transition, watcher, div, handler } =
154     setupTransition(t, 'margin-left 100s 100s');
155
156   return Promise.all([ watcher.wait_for('transitionrun'),
157                        transition.ready ]).then(() => {
158     // Seek to After phase.
159     transition.currentTime = 200 * MS_PER_SEC;
160     return watcher.wait_for([ 'transitionstart', 'transitionend' ]);
161   }).then(evt => {
162     assert_equals(handler.transitionstart, 0.0);
163     assert_equals(handler.transitionend, 100.0);
164   });
165 }, 'Before -> After');
166
167 promise_test(t => {
168   const { transition, watcher, div } =
169     setupTransition(t, 'margin-left 100s');
170
171   // Seek to Active start position.
172   transition.pause();
173   return watcher.wait_for([ 'transitionrun',
174                             'transitionstart' ]).then(evt => {
175     // Make idle
176     div.style.display = 'none';
177     flushComputedStyle(div);
178     return watcher.wait_for('transitioncancel');
179   }).then(evt => {
180     assert_equals(evt.elapsedTime, 0.0);
181   });
182 }, 'Active -> Idle, no delay (display: none)');
183
184 promise_test(t => {
185   const { transition, watcher } =
186     setupTransition(t, 'margin-left 100s');
187
188   return watcher.wait_for([ 'transitionrun',
189                             'transitionstart' ]).then(evt => {
190     // Make idle
191     transition.currentTime = 0;
192     transition.timeline = null;
193     return watcher.wait_for('transitioncancel');
194   }).then(evt => {
195     assert_equals(evt.elapsedTime, 0.0);
196   });
197 }, 'Active -> Idle, no delay (Animation.timeline = null)');
198
199 promise_test(t => {
200   const { transition, watcher, div } =
201     setupTransition(t, 'margin-left 100s 100s');
202   // Pause so the currentTime is fixed and we can accurately compare the event
203   // time in transition cancel events.
204   transition.pause();
205
206   // Seek to Active phase.
207   transition.currentTime = 100 * MS_PER_SEC;
208   return watcher.wait_for([ 'transitionrun',
209                             'transitionstart' ]).then(evt => {
210     // Make idle
211     div.style.display = 'none';
212     flushComputedStyle(div);
213     return watcher.wait_for('transitioncancel');
214   }).then(evt => {
215     assert_equals(evt.elapsedTime, 0.0);
216   });
217 }, 'Active -> Idle, with positive delay (display: none)');
218
219 promise_test(t => {
220   const { transition, watcher } =
221     setupTransition(t, 'margin-left 100s 100s');
222
223   // Seek to Active phase.
224   transition.currentTime = 100 * MS_PER_SEC;
225   return watcher.wait_for([ 'transitionrun',
226                             'transitionstart' ]).then(evt => {
227     // Make idle
228     transition.currentTime = 100 * MS_PER_SEC;
229     transition.timeline = null;
230     return watcher.wait_for('transitioncancel');
231   }).then(evt => {
232     assert_equals(evt.elapsedTime, 0.0);
233   });
234 }, 'Active -> Idle, with positive delay (Animation.timeline = null)');
235
236 promise_test(t => {
237   const { transition, watcher, div } =
238     setupTransition(t, 'margin-left 100s -50s');
239
240   // Pause so the currentTime is fixed and we can accurately compare the event
241   // time in transition cancel events.
242   transition.pause();
243
244   return watcher.wait_for([ 'transitionrun',
245                             'transitionstart' ]).then(evt => {
246     // Make idle
247     div.style.display = 'none';
248     flushComputedStyle(div);
249     return watcher.wait_for('transitioncancel');
250   }).then(evt => {
251     assert_equals(evt.elapsedTime, 50.0);
252   });
253 }, 'Active -> Idle, with negative delay (display: none)');
254
255 promise_test(t => {
256   const { transition, watcher } =
257     setupTransition(t, 'margin-left 100s -50s');
258
259   return watcher.wait_for([ 'transitionrun',
260                             'transitionstart' ]).then(evt => {
261     // Make idle
262     transition.currentTime = 50 * MS_PER_SEC;
263     transition.timeline = null;
264     return watcher.wait_for('transitioncancel');
265   }).then(evt => {
266     assert_equals(evt.elapsedTime, 0.0);
267   });
268 }, 'Active -> Idle, with negative delay (Animation.timeline = null)');
269
270 promise_test(t => {
271   const { transition, watcher } =
272     setupTransition(t, 'margin-left 100s 100s');
273   // Seek to Active phase.
274   transition.currentTime = 100 * MS_PER_SEC;
275   return watcher.wait_for([ 'transitionrun',
276                             'transitionstart' ]).then(evt => {
277     // Seek to Before phase.
278     transition.currentTime = 0;
279     return watcher.wait_for('transitionend');
280   }).then(evt => {
281     assert_equals(evt.elapsedTime, 0.0);
282   });
283 }, 'Active -> Before');
284
285 promise_test(t => {
286   const { transition, watcher } =
287     setupTransition(t, 'margin-left 100s 100s');
288   // Seek to Active phase.
289   transition.currentTime = 100 * MS_PER_SEC;
290   return watcher.wait_for([ 'transitionrun',
291                             'transitionstart' ]).then(evt => {
292     // Seek to After phase.
293     transition.currentTime = 200 * MS_PER_SEC;
294     return watcher.wait_for('transitionend');
295   }).then(evt => {
296     assert_equals(evt.elapsedTime, 100.0);
297   });
298 }, 'Active -> After');
299
300 promise_test(t => {
301   const { transition, watcher, div, handler } =
302     setupTransition(t, 'margin-left 100s 100s');
303
304   // Seek to After phase.
305   transition.finish();
306   return watcher.wait_for([ 'transitionrun',
307                             'transitionstart',
308                             'transitionend' ]).then(evt => {
309     // Seek to Before phase.
310     transition.currentTime = 0;
311     return watcher.wait_for([ 'transitionstart', 'transitionend' ]);
312   }).then(evt => {
313     assert_equals(handler.transitionstart, 100.0);
314     assert_equals(handler.transitionend, 0.0);
315   });
316 }, 'After -> Before');
317
318 promise_test(t => {
319   const { transition, watcher } =
320     setupTransition(t, 'margin-left 100s 100s');
321   // Seek to After phase.
322   transition.finish();
323   return watcher.wait_for([ 'transitionrun',
324                             'transitionstart',
325                             'transitionend' ]).then(evt => {
326     // Seek to Active phase.
327     transition.currentTime = 100 * MS_PER_SEC;
328     return watcher.wait_for('transitionstart');
329   }).then(evt => {
330     assert_equals(evt.elapsedTime, 100.0);
331   });
332 }, 'After -> Active');
333
334 promise_test(t => {
335   const { transition, watcher, div, handler } =
336     setupTransition(t, 'margin-left 100s -50s');
337
338   return watcher.wait_for([ 'transitionrun',
339                             'transitionstart' ]).then(() => {
340     assert_equals(handler.transitionrun, 50.0);
341     assert_equals(handler.transitionstart, 50.0);
342     transition.finish();
343     return watcher.wait_for('transitionend');
344   }).then(evt => {
345     assert_equals(evt.elapsedTime, 100.0);
346   });
347 }, 'Calculating the interval start and end time with negative start delay.');
348
349 promise_test(t => {
350   const { transition, watcher, div, handler } =
351     setupTransition(t, 'margin-left 100s 100s');
352
353   return watcher.wait_for('transitionrun').then(evt => {
354     // We can't set the end delay via generated effect timing.
355     // Because CSS-Transition use the AnimationEffectTimingReadOnly.
356     transition.effect = new KeyframeEffect(div,
357                                            { marginleft: [ '0px', '100px' ]},
358                                            { duration: 100 * MS_PER_SEC,
359                                              endDelay: -50 * MS_PER_SEC });
360     // Seek to Before and play.
361     transition.cancel();
362     transition.play();
363     return watcher.wait_for([ 'transitioncancel',
364                               'transitionrun',
365                               'transitionstart' ]);
366   }).then(() => {
367     assert_equals(handler.transitionstart, 0.0);
368
369     // Seek to After phase.
370     transition.finish();
371     return watcher.wait_for('transitionend');
372   }).then(evt => {
373     assert_equals(evt.elapsedTime, 50.0);
374   });
375 }, 'Calculating the interval start and end time with negative end delay.');
376
377 promise_test(t => {
378   const { transition, watcher, div } =
379     setupTransition(t, 'margin-left 100s 100s');
380
381   return watcher.wait_for('transitionrun').then(() => {
382     // Make idle
383     div.style.display = 'none';
384     flushComputedStyle(div);
385     return watcher.wait_for('transitioncancel');
386   }).then(() => {
387     transition.cancel();
388     // Then wait a couple of frames and check that no event was dispatched
389     return waitForAnimationFrames(2);
390   });
391 }, 'Call Animation.cancel after cancelling transition.');
392
393 promise_test(t => {
394   const { transition, watcher, div } =
395     setupTransition(t, 'margin-left 100s 100s');
396
397   return watcher.wait_for('transitionrun').then(evt => {
398     // Make idle
399     div.style.display = 'none';
400     flushComputedStyle(div);
401     transition.play();
402     watcher.wait_for([ 'transitioncancel',
403                        'transitionrun',
404                        'transitionstart' ]);
405   });
406 }, 'Restart transition after cancelling transition immediately');
407
408 promise_test(t => {
409   const { transition, watcher, div } =
410     setupTransition(t, 'margin-left 100s 100s');
411
412   return watcher.wait_for('transitionrun').then(evt => {
413     // Make idle
414     div.style.display = 'none';
415     flushComputedStyle(div);
416     transition.play();
417     transition.cancel();
418     return watcher.wait_for('transitioncancel');
419   }).then(evt => {
420     // Then wait a couple of frames and check that no event was dispatched
421     return waitForAnimationFrames(2);
422   });
423 }, 'Call Animation.cancel after restarting transition immediately');
424
425 promise_test(t => {
426   const { transition, watcher } =
427     setupTransition(t, 'margin-left 100s');
428
429   return watcher.wait_for([ 'transitionrun',
430                             'transitionstart' ]).then(evt => {
431     // Make idle
432     transition.timeline = null;
433     return watcher.wait_for('transitioncancel');
434   }).then(evt => {
435     transition.timeline = document.timeline;
436     transition.play();
437
438     return watcher.wait_for(['transitionrun', 'transitionstart']);
439   });
440 }, 'Set timeline and play transition after clear the timeline');
441
442 promise_test(t => {
443   const { transition, watcher, div } =
444     setupTransition(t, 'margin-left 100s');
445
446   return watcher.wait_for([ 'transitionrun',
447                             'transitionstart' ]).then(() => {
448     transition.cancel();
449     return watcher.wait_for('transitioncancel');
450   }).then(() => {
451     // Make After phase
452     transition.effect = null;
453
454     // Then wait a couple of frames and check that no event was dispatched
455     return waitForAnimationFrames(2);
456   });
457 }, 'Set null target effect after cancel the transition');
458
459 promise_test(t => {
460   const { transition, watcher, div } =
461     setupTransition(t, 'margin-left 100s');
462
463   return watcher.wait_for([ 'transitionrun',
464                             'transitionstart' ]).then(evt => {
465     transition.effect = null;
466     return watcher.wait_for('transitionend');
467   }).then(evt => {
468     transition.cancel();
469
470     // Then wait a couple of frames and check that no event was dispatched
471     return waitForAnimationFrames(2);
472   });
473 }, 'Cancel the transition after clearing the target effect');
474
475 </script>
476 </body>
477 </html>