[Web Animations] Update WPT tests and move them to imported/w3c/web-platform-tests
[WebKit-https.git] / LayoutTests / imported / w3c / web-platform-tests / web-animations / animation-model / keyframe-effects / effect-value-iteration-composite-operation.html
1 <!doctype html>
2 <meta charset=utf-8>
3 <title>The effect value of a keyframe effect: Applying the iteration composite
4   operation</title>
5 <link rel="help" href="https://drafts.csswg.org/web-animations/#the-effect-value-of-a-keyframe-animation-effect">
6 <link rel="help" href="https://drafts.csswg.org/web-animations/#effect-accumulation-section">
7 <script src=/resources/testharness.js></script>
8 <script src=/resources/testharnessreport.js></script>
9 <script src="../../testcommon.js"></script>
10 <div id="log"></div>
11 <script>
12 'use strict';
13
14 test(t => {
15   const div = createDiv(t);
16   const anim =
17     div.animate({ alignContent: ['flex-start', 'flex-end'] },
18                 { duration: 100 * MS_PER_SEC,
19                   easing: 'linear',
20                   iterations: 10,
21                   iterationComposite: 'accumulate' });
22
23   anim.currentTime = anim.effect.timing.duration / 2;
24   assert_equals(getComputedStyle(div).alignContent, 'flex-end',
25     'Animated align-content style at 50s of the first iteration');
26   anim.currentTime = anim.effect.timing.duration * 2;
27   assert_equals(getComputedStyle(div).alignContent, 'flex-start',
28     'Animated align-content style at 0s of the third iteration');
29   anim.currentTime += anim.effect.timing.duration / 2;
30   assert_equals(getComputedStyle(div).alignContent, 'flex-end',
31     'Animated align-content style at 50s of the third iteration');
32 }, 'iteration composition of discrete type animation (align-content)');
33
34 test(t => {
35   const div = createDiv(t);
36   const anim =
37     div.animate({ marginLeft: ['0px', '10px'] },
38                 { duration: 100 * MS_PER_SEC,
39                   easing: 'linear',
40                   iterations: 10,
41                   iterationComposite: 'accumulate' });
42   anim.pause();
43
44   anim.currentTime = anim.effect.timing.duration / 2;
45   assert_equals(getComputedStyle(div).marginLeft, '5px',
46     'Animated margin-left style at 50s of the first iteration');
47   anim.currentTime = anim.effect.timing.duration * 2;
48   assert_equals(getComputedStyle(div).marginLeft, '20px',
49     'Animated margin-left style at 0s of the third iteration');
50   anim.currentTime += anim.effect.timing.duration / 2;
51   assert_equals(getComputedStyle(div).marginLeft, '25px',
52     'Animated margin-left style at 50s of the third iteration');
53 }, 'iteration composition of <length> type animation');
54
55 test(t => {
56   const parent = createDiv(t);
57   parent.style.width = '100px';
58   const div = createDiv(t);
59   parent.appendChild(div);
60
61   const anim =
62     div.animate({ width: ['0%', '50%'] },
63                 { duration: 100 * MS_PER_SEC,
64                   easing: 'linear',
65                   iterations: 10,
66                   iterationComposite: 'accumulate' });
67   anim.pause();
68
69   anim.currentTime = anim.effect.timing.duration / 2;
70   assert_equals(getComputedStyle(div).width, '25px',
71     'Animated width style at 50s of the first iteration');
72   anim.currentTime = anim.effect.timing.duration * 2;
73   assert_equals(getComputedStyle(div).width, '100px',
74     'Animated width style at 0s of the third iteration');
75   anim.currentTime += anim.effect.timing.duration / 2;
76   assert_equals(getComputedStyle(div).width, '125px',
77     'Animated width style at 50s of the third iteration');
78 }, 'iteration composition of <percentage> type animation');
79
80 test(t => {
81   const div = createDiv(t);
82   const anim =
83     div.animate({ color: ['rgb(0, 0, 0)', 'rgb(120, 120, 120)'] },
84                 { duration: 100 * MS_PER_SEC,
85                   easing: 'linear',
86                   iterations: 10,
87                   iterationComposite: 'accumulate' });
88   anim.pause();
89
90   anim.currentTime = anim.effect.timing.duration / 2;
91   assert_equals(getComputedStyle(div).color, 'rgb(60, 60, 60)',
92     'Animated color style at 50s of the first iteration');
93   anim.currentTime = anim.effect.timing.duration * 2;
94   assert_equals(getComputedStyle(div).color, 'rgb(240, 240, 240)',
95     'Animated color style at 0s of the third iteration');
96   anim.currentTime += anim.effect.timing.duration / 2;
97   assert_equals(getComputedStyle(div).color, 'rgb(255, 255, 255)',
98     'Animated color style at 50s of the third iteration');
99 }, 'iteration composition of <color> type animation');
100
101 test(t => {
102   const div = createDiv(t);
103   const anim =
104     div.animate({ color: ['rgb(0, 120, 0)', 'rgb(60, 60, 60)'] },
105                 { duration: 100 * MS_PER_SEC,
106                   easing: 'linear',
107                   iterations: 10,
108                   iterationComposite: 'accumulate' });
109   anim.pause();
110
111   anim.currentTime = anim.effect.timing.duration / 2;
112   assert_equals(getComputedStyle(div).color, 'rgb(30, 90, 30)',
113     'Animated color style at 50s of the first iteration');
114   anim.currentTime = anim.effect.timing.duration * 2;
115   assert_equals(getComputedStyle(div).color, 'rgb(120, 240, 120)',
116     'Animated color style at 0s of the third iteration');
117   anim.currentTime += anim.effect.timing.duration / 2;
118   // The green color is (240 + 180) / 2 = 210
119   assert_equals(getComputedStyle(div).color, 'rgb(150, 210, 150)',
120     'Animated color style at 50s of the third iteration');
121 }, 'iteration composition of <color> type animation that green component is ' +
122    'decreasing');
123
124    test(t => {
125   const div = createDiv(t);
126   const anim =
127     div.animate({ flexGrow: [0, 10] },
128                 { duration: 100 * MS_PER_SEC,
129                   easing: 'linear',
130                   iterations: 10,
131                   iterationComposite: 'accumulate' });
132   anim.pause();
133
134   anim.currentTime = anim.effect.timing.duration / 2;
135   assert_equals(getComputedStyle(div).flexGrow, '5',
136     'Animated flex-grow style at 50s of the first iteration');
137   anim.currentTime = anim.effect.timing.duration * 2;
138   assert_equals(getComputedStyle(div).flexGrow, '20',
139     'Animated flex-grow style at 0s of the third iteration');
140   anim.currentTime += anim.effect.timing.duration / 2;
141   assert_equals(getComputedStyle(div).flexGrow, '25',
142     'Animated flex-grow style at 50s of the third iteration');
143 }, 'iteration composition of <number> type animation');
144
145 test(t => {
146   const div = createDiv(t);
147   div.style.position = 'absolute';
148   const anim =
149     div.animate({ clip: ['rect(0px, 0px, 0px, 0px)',
150                          'rect(10px, 10px, 10px, 10px)'] },
151                 { duration: 100 * MS_PER_SEC,
152                   easing: 'linear',
153                   iterations: 10,
154                   iterationComposite: 'accumulate' });
155   anim.pause();
156
157   anim.currentTime = anim.effect.timing.duration / 2;
158   assert_equals(getComputedStyle(div).clip, 'rect(5px, 5px, 5px, 5px)',
159     'Animated clip style at 50s of the first iteration');
160   anim.currentTime = anim.effect.timing.duration * 2;
161   assert_equals(getComputedStyle(div).clip, 'rect(20px, 20px, 20px, 20px)',
162     'Animated clip style at 0s of the third iteration');
163   anim.currentTime += anim.effect.timing.duration / 2;
164   assert_equals(getComputedStyle(div).clip, 'rect(25px, 25px, 25px, 25px)',
165     'Animated clip style at 50s of the third iteration');
166 }, 'iteration composition of <shape> type animation');
167
168 test(t => {
169   const div = createDiv(t);
170   const anim =
171     div.animate({ width: ['calc(0vw + 0px)', 'calc(0vw + 10px)'] },
172                 { duration: 100 * MS_PER_SEC,
173                   easing: 'linear',
174                   iterations: 10,
175                   iterationComposite: 'accumulate' });
176   anim.pause();
177
178   anim.currentTime = anim.effect.timing.duration / 2;
179   assert_equals(getComputedStyle(div).width, '5px',
180     'Animated calc width style at 50s of the first iteration');
181   anim.currentTime = anim.effect.timing.duration * 2;
182   assert_equals(getComputedStyle(div).width, '20px',
183     'Animated calc width style at 0s of the third iteration');
184   anim.currentTime += anim.effect.timing.duration / 2;
185   assert_equals(getComputedStyle(div).width, '25px',
186     'Animated calc width style at 50s of the third iteration');
187 }, 'iteration composition of <calc()> value animation');
188
189 test(t => {
190   const parent = createDiv(t);
191   parent.style.width = '100px';
192   const div = createDiv(t);
193   parent.appendChild(div);
194
195   const anim =
196     div.animate({ width: ['calc(0% + 0px)', 'calc(10% + 10px)'] },
197                 { duration: 100 * MS_PER_SEC,
198                   easing: 'linear',
199                   iterations: 10,
200                   iterationComposite: 'accumulate' });
201   anim.pause();
202
203   anim.currentTime = anim.effect.timing.duration / 2;
204   assert_equals(getComputedStyle(div).width, '10px',
205     // 100px * 5% + 5px
206     'Animated calc width style at 50s of the first iteration');
207   anim.currentTime = anim.effect.timing.duration * 2;
208   assert_equals(getComputedStyle(div).width,
209     '40px', // 100px * (10% + 10%) + (10px + 10px)
210     'Animated calc width style at 0s of the third iteration');
211   anim.currentTime += anim.effect.timing.duration / 2;
212   assert_equals(getComputedStyle(div).width,
213     '50px', // (40px + 60px) / 2
214     'Animated calc width style at 50s of the third iteration');
215 }, 'iteration composition of <calc()> value animation that the values can\'t' +
216    'be reduced');
217
218 test(t => {
219   const div = createDiv(t);
220   const anim =
221     div.animate({ opacity: [0, 0.4] },
222                 { duration: 100 * MS_PER_SEC,
223                   easing: 'linear',
224                   iterations: 10,
225                   iterationComposite: 'accumulate' });
226   anim.pause();
227
228   anim.currentTime = anim.effect.timing.duration / 2;
229   assert_equals(getComputedStyle(div).opacity, '0.2',
230     'Animated opacity style at 50s of the first iteration');
231   anim.currentTime = anim.effect.timing.duration * 2;
232   assert_equals(getComputedStyle(div).opacity, '0.8',
233     'Animated opacity style at 0s of the third iteration');
234   anim.currentTime += anim.effect.timing.duration / 2;
235   assert_equals(getComputedStyle(div).opacity, '1', // (0.8 + 1.2) * 0.5
236     'Animated opacity style at 50s of the third iteration');
237 }, 'iteration composition of opacity animation');
238
239 test(t => {
240   const div = createDiv(t);
241   const anim =
242     div.animate({ boxShadow: ['rgb(0, 0, 0) 0px 0px 0px 0px',
243                               'rgb(120, 120, 120) 10px 10px 10px 0px'] },
244                 { duration: 100 * MS_PER_SEC,
245                   easing: 'linear',
246                   iterations: 10,
247                   iterationComposite: 'accumulate' });
248   anim.pause();
249
250   anim.currentTime = anim.effect.timing.duration / 2;
251   assert_equals(getComputedStyle(div).boxShadow,
252     'rgb(60, 60, 60) 5px 5px 5px 0px',
253     'Animated box-shadow style at 50s of the first iteration');
254   anim.currentTime = anim.effect.timing.duration * 2;
255   assert_equals(getComputedStyle(div).boxShadow,
256     'rgb(240, 240, 240) 20px 20px 20px 0px',
257     'Animated box-shadow style at 0s of the third iteration');
258   anim.currentTime += anim.effect.timing.duration / 2;
259   assert_equals(getComputedStyle(div).boxShadow,
260     'rgb(255, 255, 255) 25px 25px 25px 0px',
261     'Animated box-shadow style at 50s of the third iteration');
262 }, 'iteration composition of box-shadow animation');
263
264 test(t => {
265   const div = createDiv(t);
266   const anim =
267     div.animate({ filter: ['blur(0px)', 'blur(10px)'] },
268                 { duration: 100 * MS_PER_SEC,
269                   easing: 'linear',
270                   iterations: 10,
271                   iterationComposite: 'accumulate' });
272   anim.pause();
273
274   anim.currentTime = anim.effect.timing.duration / 2;
275   assert_equals(getComputedStyle(div).filter, 'blur(5px)',
276     'Animated filter blur style at 50s of the first iteration');
277   anim.currentTime = anim.effect.timing.duration * 2;
278   assert_equals(getComputedStyle(div).filter, 'blur(20px)',
279     'Animated filter blur style at 0s of the third iteration');
280   anim.currentTime += anim.effect.timing.duration / 2;
281   assert_equals(getComputedStyle(div).filter, 'blur(25px)',
282     'Animated filter blur style at 50s of the third iteration');
283 }, 'iteration composition of filter blur animation');
284
285 test(t => {
286   const div = createDiv(t);
287   const anim =
288     div.animate({ filter: ['brightness(1)',
289                            'brightness(180%)'] },
290                 { duration: 100 * MS_PER_SEC,
291                   easing: 'linear',
292                   iterations: 10,
293                   iterationComposite: 'accumulate' });
294   anim.pause();
295
296   anim.currentTime = anim.effect.timing.duration / 2;
297   assert_equals(getComputedStyle(div).filter,
298     'brightness(1.4)',
299     'Animated filter brightness style at 50s of the first iteration');
300   anim.currentTime = anim.effect.timing.duration * 2;
301   assert_equals(getComputedStyle(div).filter,
302     'brightness(2.6)', // brightness(1) + brightness(0.8) + brightness(0.8)
303     'Animated filter brightness style at 0s of the third iteration');
304   anim.currentTime += anim.effect.timing.duration / 2;
305   assert_equals(getComputedStyle(div).filter,
306     'brightness(3)', // (brightness(2.6) + brightness(3.4)) * 0.5
307     'Animated filter brightness style at 50s of the third iteration');
308 }, 'iteration composition of filter brightness for different unit animation');
309
310 test(t => {
311   const div = createDiv(t);
312   const anim =
313     div.animate({ filter: ['brightness(0)',
314                            'brightness(1)'] },
315                 { duration: 100 * MS_PER_SEC,
316                   easing: 'linear',
317                   iterations: 10,
318                   iterationComposite: 'accumulate' });
319   anim.pause();
320
321   anim.currentTime = anim.effect.timing.duration / 2;
322   assert_equals(getComputedStyle(div).filter,
323     'brightness(0.5)',
324     'Animated filter brightness style at 50s of the first iteration');
325   anim.currentTime = anim.effect.timing.duration * 2;
326   assert_equals(getComputedStyle(div).filter,
327     'brightness(0)', // brightness(1) is an identity element, not accumulated.
328     'Animated filter brightness style at 0s of the third iteration');
329   anim.currentTime += anim.effect.timing.duration / 2;
330   assert_equals(getComputedStyle(div).filter,
331     'brightness(0.5)', // brightness(1) is an identity element, not accumulated.
332     'Animated filter brightness style at 50s of the third iteration');
333 }, 'iteration composition of filter brightness animation');
334
335 test(t => {
336   const div = createDiv(t);
337   const anim =
338     div.animate({ filter: ['drop-shadow(rgb(0, 0, 0) 0px 0px 0px)',
339                            'drop-shadow(rgb(120, 120, 120) 10px 10px 10px)'] },
340                 { duration: 100 * MS_PER_SEC,
341                   easing: 'linear',
342                   iterations: 10,
343                   iterationComposite: 'accumulate' });
344   anim.pause();
345
346   anim.currentTime = anim.effect.timing.duration / 2;
347   assert_equals(getComputedStyle(div).filter,
348     'drop-shadow(rgb(60, 60, 60) 5px 5px 5px)',
349     'Animated filter drop-shadow style at 50s of the first iteration');
350   anim.currentTime = anim.effect.timing.duration * 2;
351   assert_equals(getComputedStyle(div).filter,
352     'drop-shadow(rgb(240, 240, 240) 20px 20px 20px)',
353     'Animated filter drop-shadow style at 0s of the third iteration');
354   anim.currentTime += anim.effect.timing.duration / 2;
355   assert_equals(getComputedStyle(div).filter,
356     'drop-shadow(rgb(255, 255, 255) 25px 25px 25px)',
357     'Animated filter drop-shadow style at 50s of the third iteration');
358 }, 'iteration composition of filter drop-shadow animation');
359
360 test(t => {
361   const div = createDiv(t);
362   const anim =
363     div.animate({ filter: ['brightness(1) contrast(1)',
364                            'brightness(2) contrast(2)'] },
365                 { duration: 100 * MS_PER_SEC,
366                   easing: 'linear',
367                   iterations: 10,
368                   iterationComposite: 'accumulate' });
369   anim.pause();
370
371   anim.currentTime = anim.effect.timing.duration / 2;
372   assert_equals(getComputedStyle(div).filter,
373     'brightness(1.5) contrast(1.5)',
374     'Animated filter list at 50s of the first iteration');
375   anim.currentTime = anim.effect.timing.duration * 2;
376   assert_equals(getComputedStyle(div).filter,
377     'brightness(3) contrast(3)',
378     'Animated filter list at 0s of the third iteration');
379   anim.currentTime += anim.effect.timing.duration / 2;
380   assert_equals(getComputedStyle(div).filter,
381     'brightness(3.5) contrast(3.5)',
382     'Animated filter list at 50s of the third iteration');
383 }, 'iteration composition of same filter list animation');
384
385 test(t => {
386   const div = createDiv(t);
387   const anim =
388     div.animate({ filter: ['brightness(1) contrast(1)',
389                            'contrast(2) brightness(2)'] },
390                 { duration: 100 * MS_PER_SEC,
391                   easing: 'linear',
392                   iterations: 10,
393                   iterationComposite: 'accumulate' });
394   anim.pause();
395
396   anim.currentTime = anim.effect.timing.duration / 2;
397   assert_equals(getComputedStyle(div).filter,
398     'contrast(2) brightness(2)', // discrete
399     'Animated filter list at 50s of the first iteration');
400   anim.currentTime = anim.effect.timing.duration * 2;
401   assert_equals(getComputedStyle(div).filter,
402     // We can't accumulate 'contrast(2) brightness(2)' onto
403     // the first list 'brightness(1) contrast(1)' because of
404     // mismatch of the order.
405     'brightness(1) contrast(1)',
406     'Animated filter list at 0s of the third iteration');
407   anim.currentTime += anim.effect.timing.duration / 2;
408   assert_equals(getComputedStyle(div).filter,
409     // We *can* accumulate 'contrast(2) brightness(2)' onto
410     // the same list 'contrast(2) brightness(2)' here.
411     'contrast(4) brightness(4)', // discrete
412     'Animated filter list at 50s of the third iteration');
413 }, 'iteration composition of discrete filter list because of mismatch ' +
414    'of the order');
415
416    test(t => {
417   const div = createDiv(t);
418   const anim =
419     div.animate({ filter: ['sepia(0)',
420                            'sepia(1) contrast(2)'] },
421                 { duration: 100 * MS_PER_SEC,
422                   easing: 'linear',
423                   iterations: 10,
424                   iterationComposite: 'accumulate' });
425   anim.pause();
426
427   anim.currentTime = anim.effect.timing.duration / 2;
428   assert_equals(getComputedStyle(div).filter,
429     'sepia(0.5) contrast(1.5)',
430     'Animated filter list at 50s of the first iteration');
431   anim.currentTime = anim.effect.timing.duration * 2;
432   assert_equals(getComputedStyle(div).filter,
433     'sepia(2) contrast(3)',
434     'Animated filter list at 0s of the third iteration');
435   anim.currentTime += anim.effect.timing.duration / 2;
436   assert_equals(getComputedStyle(div).filter,
437     'sepia(2.5) contrast(3.5)',
438     'Animated filter list at 50s of the third iteration');
439 }, 'iteration composition of different length filter list animation');
440
441 test(t => {
442   const div = createDiv(t);
443   const anim =
444     div.animate({ transform: ['rotate(0deg)', 'rotate(180deg)'] },
445                 { duration: 100 * MS_PER_SEC,
446                   easing: 'linear',
447                   iterations: 10,
448                   iterationComposite: 'accumulate' });
449   anim.pause();
450
451   anim.currentTime = anim.effect.timing.duration / 2;
452   assert_matrix_equals(getComputedStyle(div).transform,
453     'matrix(0, 1, -1, 0, 0, 0)', // rotate(90deg)
454     'Animated transform(rotate) style at 50s of the first iteration');
455   anim.currentTime = anim.effect.timing.duration * 2;
456   assert_matrix_equals(getComputedStyle(div).transform,
457     'matrix(1, 0, 0, 1, 0, 0)', // rotate(360deg)
458     'Animated transform(rotate) style at 0s of the third iteration');
459   anim.currentTime += anim.effect.timing.duration / 2;
460   assert_matrix_equals(getComputedStyle(div).transform,
461     'matrix(0, 1, -1, 0, 0, 0)', // rotate(450deg)
462     'Animated transform(rotate) style at 50s of the third iteration');
463 }, 'iteration composition of transform(rotate) animation');
464
465 test(t => {
466   const div = createDiv(t);
467   const anim =
468     div.animate({ transform: ['scale(0)', 'scale(1)'] },
469                 { duration: 100 * MS_PER_SEC,
470                   easing: 'linear',
471                   iterations: 10,
472                   iterationComposite: 'accumulate' });
473   anim.pause();
474
475   anim.currentTime = anim.effect.timing.duration / 2;
476   assert_matrix_equals(getComputedStyle(div).transform,
477     'matrix(0.5, 0, 0, 0.5, 0, 0)', // scale(0.5)
478     'Animated transform(scale) style at 50s of the first iteration');
479   anim.currentTime = anim.effect.timing.duration * 2;
480   assert_matrix_equals(getComputedStyle(div).transform,
481     'matrix(0, 0, 0, 0, 0, 0)', // scale(0); scale(1) is an identity element,
482                                 // not accumulated.
483     'Animated transform(scale) style at 0s of the third iteration');
484   anim.currentTime += anim.effect.timing.duration / 2;
485   assert_matrix_equals(getComputedStyle(div).transform,
486     'matrix(0.5, 0, 0, 0.5, 0, 0)', // scale(0.5); scale(1) an identity
487                                     // element, not accumulated.
488     'Animated transform(scale) style at 50s of the third iteration');
489 }, 'iteration composition of transform: [ scale(0), scale(1) ] animation');
490
491 test(t => {
492   const div = createDiv(t);
493   const anim =
494     div.animate({ transform: ['scale(1)', 'scale(2)'] },
495                 { duration: 100 * MS_PER_SEC,
496                   easing: 'linear',
497                   iterations: 10,
498                   iterationComposite: 'accumulate' });
499   anim.pause();
500
501   anim.currentTime = anim.effect.timing.duration / 2;
502   assert_matrix_equals(getComputedStyle(div).transform,
503     'matrix(1.5, 0, 0, 1.5, 0, 0)', // scale(1.5)
504     'Animated transform(scale) style at 50s of the first iteration');
505   anim.currentTime = anim.effect.timing.duration * 2;
506   assert_matrix_equals(getComputedStyle(div).transform,
507     'matrix(3, 0, 0, 3, 0, 0)', // scale(1 + (2 -1) + (2 -1))
508     'Animated transform(scale) style at 0s of the third iteration');
509   anim.currentTime += anim.effect.timing.duration / 2;
510   assert_matrix_equals(getComputedStyle(div).transform,
511     'matrix(3.5, 0, 0, 3.5, 0, 0)', // (scale(3) + scale(4)) * 0.5
512     'Animated transform(scale) style at 50s of the third iteration');
513 }, 'iteration composition of transform: [ scale(1), scale(2) ] animation');
514
515 test(t => {
516   const div = createDiv(t);
517   const anim =
518     div.animate({ transform: ['scale(0)', 'scale(2)'] },
519                 { duration: 100 * MS_PER_SEC,
520                   easing: 'linear',
521                   iterations: 10,
522                   iterationComposite: 'accumulate' });
523   anim.pause();
524
525   anim.currentTime = anim.effect.timing.duration / 2;
526   assert_matrix_equals(getComputedStyle(div).transform,
527     'matrix(1, 0, 0, 1, 0, 0)', // scale(1)
528     'Animated transform(scale) style at 50s of the first iteration');
529   anim.currentTime = anim.effect.timing.duration * 2;
530   assert_matrix_equals(getComputedStyle(div).transform,
531     'matrix(2, 0, 0, 2, 0, 0)', // (scale(0) + scale(2-1)*2)
532     'Animated transform(scale) style at 0s of the third iteration');
533   anim.currentTime += anim.effect.timing.duration / 2;
534   assert_matrix_equals(getComputedStyle(div).transform,
535     'matrix(3, 0, 0, 3, 0, 0)', // (scale(2) + scale(4)) * 0.5
536     'Animated transform(scale) style at 50s of the third iteration');
537 }, 'iteration composition of transform: scale(2) animation');
538
539 test(t => {
540   const div = createDiv(t);
541   const anim =
542     div.animate({ transform: ['rotate(0deg) translateX(0px)',
543                               'rotate(180deg) translateX(10px)'] },
544                 { duration: 100 * MS_PER_SEC,
545                   easing: 'linear',
546                   iterations: 10,
547                   iterationComposite: 'accumulate' });
548   anim.pause();
549
550   anim.currentTime = anim.effect.timing.duration / 2;
551   assert_matrix_equals(getComputedStyle(div).transform,
552     'matrix(0, 1, -1, 0, 0, 5)', // rotate(90deg) translateX(5px)
553     'Animated transform list at 50s of the first iteration');
554   anim.currentTime = anim.effect.timing.duration * 2;
555   assert_matrix_equals(getComputedStyle(div).transform,
556     'matrix(1, 0, 0, 1, 20, 0)', // rotate(360deg) translateX(20px)
557     'Animated transform list at 0s of the third iteration');
558   anim.currentTime += anim.effect.timing.duration / 2;
559   assert_matrix_equals(getComputedStyle(div).transform,
560     'matrix(0, 1, -1, 0, 0, 25)', // rotate(450deg) translateX(25px)
561     'Animated transform list at 50s of the third iteration');
562 }, 'iteration composition of transform list animation');
563
564 test(t => {
565   const div = createDiv(t);
566   const anim =
567     div.animate({ transform: ['matrix(2, 0, 0, 2, 0, 0)',
568                               'matrix(3, 0, 0, 3, 30, 0)'] },
569                 { duration: 100 * MS_PER_SEC,
570                   easing: 'linear',
571                   iterations: 10,
572                   iterationComposite: 'accumulate' });
573   anim.pause();
574
575   anim.currentTime = anim.effect.timing.duration / 2;
576   assert_matrix_equals(getComputedStyle(div).transform,
577     'matrix(2.5, 0, 0, 2.5, 15, 0)',
578     'Animated transform of matrix function at 50s of the first iteration');
579   anim.currentTime = anim.effect.timing.duration * 2;
580   assert_matrix_equals(getComputedStyle(div).transform,
581     // scale(2) + (scale(3-1)*2) + translateX(30px)*2
582     'matrix(6, 0, 0, 6, 60, 0)',
583     'Animated transform of matrix function at 0s of the third iteration');
584   anim.currentTime += anim.effect.timing.duration / 2;
585   assert_matrix_equals(getComputedStyle(div).transform,
586     // from: matrix(6, 0, 0, 6, 60, 0)
587     // to:   matrix(7, 0, 0, 7, 90, 0)
588     //         = scale(3) + (scale(3-1)*2) + translateX(30px)*3
589     'matrix(6.5, 0, 0, 6.5, 75, 0)',
590     'Animated transform of matrix function at 50s of the third iteration');
591 }, 'iteration composition of transform of matrix function');
592
593 test(t => {
594   const div = createDiv(t);
595   const anim =
596     div.animate({ transform: ['translateX(0px) scale(2)',
597                               'scale(3) translateX(10px)'] },
598                 { duration: 100 * MS_PER_SEC,
599                   easing: 'linear',
600                   iterations: 10,
601                   iterationComposite: 'accumulate' });
602   anim.pause();
603
604   anim.currentTime = anim.effect.timing.duration / 2;
605   assert_matrix_equals(getComputedStyle(div).transform,
606     // Interpolate between matrix(2, 0, 0, 2,  0, 0) = translateX(0px) scale(2)
607     //                 and matrix(3, 0, 0, 3, 30, 0) = scale(3) translateX(10px)
608     'matrix(2.5, 0, 0, 2.5, 15, 0)',
609     'Animated transform list at 50s of the first iteration');
610   anim.currentTime = anim.effect.timing.duration * 2;
611   assert_matrix_equals(getComputedStyle(div).transform,
612     // 'from' and 'to' value are mismatched, so accumulate
613     // matrix(2, 0, 0, 2, 0, 0) onto matrix(3, 0, 0, 3, 30, 0) * 2
614     //  = scale(2) + (scale(3-1)*2) + translateX(30px)*2
615     'matrix(6, 0, 0, 6, 60, 0)',
616     'Animated transform list at 0s of the third iteration');
617   anim.currentTime += anim.effect.timing.duration / 2;
618   assert_matrix_equals(getComputedStyle(div).transform,
619     // Interpolate between matrix(6, 0, 0, 6, 60, 0)
620     //                 and matrix(7, 0, 0, 7, 210, 0) = scale(7) translate(30px)
621     'matrix(6.5, 0, 0, 6.5, 135, 0)',
622     'Animated transform list at 50s of the third iteration');
623 }, 'iteration composition of transform list animation whose order is'
624    + ' mismatched');
625
626 test(t => {
627   const div = createDiv(t);
628   // Even if each transform list does not have functions which exist in
629   // other pair of the list, we don't fill any missing functions at all.
630   const anim =
631     div.animate({ transform: ['translateX(0px)',
632                               'scale(2) translateX(10px)'] },
633                 { duration: 100 * MS_PER_SEC,
634                   easing: 'linear',
635                   iterations: 10,
636                   iterationComposite: 'accumulate' });
637   anim.pause();
638
639   anim.currentTime = anim.effect.timing.duration / 2;
640   assert_matrix_equals(getComputedStyle(div).transform,
641     // Interpolate between matrix(1, 0, 0, 1,  0, 0) = translateX(0px)
642     //                 and matrix(2, 0, 0, 2, 20, 0) = scale(2) translateX(10px)
643     'matrix(1.5, 0, 0, 1.5, 10, 0)',
644     'Animated transform list at 50s of the first iteration');
645   anim.currentTime = anim.effect.timing.duration * 2;
646   assert_matrix_equals(getComputedStyle(div).transform,
647     // 'from' and 'to' value are mismatched, so accumulate
648     // matrix(1, 0, 0, 1, 0, 0) onto matrix(2, 0, 0, 2, 20, 0) * 2
649     //  = scale(1) + (scale(2-1)*2) + translateX(20px)*2
650     'matrix(3, 0, 0, 3, 40, 0)',
651     'Animated transform list at 0s of the third iteration');
652   anim.currentTime += anim.effect.timing.duration / 2;
653   assert_matrix_equals(getComputedStyle(div).transform,
654     // Interpolate between matrix(3, 0, 0, 3, 40, 0)
655     //                 and matrix(4, 0, 0, 4, 120, 0) =
656     //                       scale(2 + (2-1)*2) translate(10px * 3)
657     'matrix(3.5, 0, 0, 3.5, 80, 0)',
658     'Animated transform list at 50s of the third iteration');
659 }, 'iteration composition of transform list animation whose order is'
660    + ' mismatched because of missing functions');
661
662    test(t => {
663   const div = createDiv(t);
664   const anim =
665     div.animate({ transform: ['none',
666                               'translateX(10px)'] },
667                 { duration: 100 * MS_PER_SEC,
668                   easing: 'linear',
669                   iterations: 10,
670                   iterationComposite: 'accumulate' });
671   anim.pause();
672
673   anim.currentTime = anim.effect.timing.duration / 2;
674   assert_matrix_equals(getComputedStyle(div).transform,
675     // translateX(none) -> translateX(10px) @ 50%
676     'matrix(1, 0, 0, 1, 5, 0)',
677     'Animated transform list at 50s of the first iteration');
678   anim.currentTime = anim.effect.timing.duration * 2;
679   assert_matrix_equals(getComputedStyle(div).transform,
680     // translateX(10px * 2 + none) -> translateX(10px * 2 + 10px) @ 0%
681     'matrix(1, 0, 0, 1, 20, 0)',
682     'Animated transform list at 0s of the third iteration');
683   anim.currentTime += anim.effect.timing.duration / 2;
684   assert_matrix_equals(getComputedStyle(div).transform,
685     // translateX(10px * 2 + none) -> translateX(10px * 2 + 10px) @ 50%
686     'matrix(1, 0, 0, 1, 25, 0)',
687     'Animated transform list at 50s of the third iteration');
688 }, 'iteration composition of transform from none to translate');
689
690 test(t => {
691   const div = createDiv(t);
692   const anim =
693     div.animate({ transform: ['matrix3d(1, 0,  0, 0, ' +
694                                        '0, 1,  0, 0, ' +
695                                        '0, 0,  1, 0, ' +
696                                        '0, 0, 30, 1)',
697                               'matrix3d(1, 0,  0, 0, ' +
698                                        '0, 1,  0, 0, ' +
699                                        '0, 0,  1, 0, ' +
700                                        '0, 0, 50, 1)'] },
701                 { duration: 100 * MS_PER_SEC,
702                   easing: 'linear',
703                   iterations: 10,
704                   iterationComposite: 'accumulate' });
705   anim.pause();
706
707   anim.currentTime = anim.effect.timing.duration / 2;
708   assert_matrix_equals(getComputedStyle(div).transform,
709     'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 40, 1)',
710     'Animated transform of matrix3d function at 50s of the first iteration');
711   anim.currentTime = anim.effect.timing.duration * 2;
712   assert_matrix_equals(getComputedStyle(div).transform,
713     // translateZ(30px) + (translateZ(50px)*2)
714     'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 130, 1)',
715     'Animated transform of matrix3d function at 0s of the third iteration');
716   anim.currentTime += anim.effect.timing.duration / 2;
717   assert_matrix_equals(getComputedStyle(div).transform,
718     // from: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 130, 1)
719     // to:   matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 150, 1)
720     'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 140, 1)',
721     'Animated transform of matrix3d function at 50s of the third iteration');
722 }, 'iteration composition of transform of matrix3d function');
723
724 test(t => {
725   const div = createDiv(t);
726   const anim =
727     div.animate({ transform: ['rotate3d(1, 1, 0, 0deg)',
728                               'rotate3d(1, 1, 0, 90deg)'] },
729                 { duration: 100 * MS_PER_SEC,
730                   easing: 'linear',
731                   iterations: 10,
732                   iterationComposite: 'accumulate' });
733   anim.pause();
734
735   anim.currentTime = 0;
736   assert_matrix_equals(getComputedStyle(div).transform,
737     'matrix(1, 0, 0, 1, 0, 0)', // Actually not rotated at all.
738     'Animated transform of rotate3d function at 50s of the first iteration');
739   anim.currentTime = anim.effect.timing.duration * 2;
740   assert_matrix_equals(getComputedStyle(div).transform,
741     rotate3dToMatrix3d(1, 1, 0, Math.PI), // 180deg
742     'Animated transform of rotate3d function at 0s of the third iteration');
743   anim.currentTime += anim.effect.timing.duration / 2;
744   assert_matrix_equals(getComputedStyle(div).transform,
745     rotate3dToMatrix3d(1, 1, 0, 225 * Math.PI / 180), //((270 + 180) * 0.5)deg
746     'Animated transform of rotate3d function at 50s of the third iteration');
747 }, 'iteration composition of transform of rotate3d function');
748
749 test(t => {
750   const div = createDiv(t);
751   const anim =
752     div.animate({ marginLeft: ['10px', '20px'] },
753                 { duration: 100 * MS_PER_SEC,
754                   easing: 'linear',
755                   iterations: 10,
756                   iterationComposite: 'accumulate' });
757   anim.pause();
758
759   anim.currentTime = anim.effect.timing.duration / 2;
760   assert_equals(getComputedStyle(div).marginLeft, '15px',
761     'Animated margin-left style at 50s of the first iteration');
762   anim.currentTime = anim.effect.timing.duration * 2;
763   assert_equals(getComputedStyle(div).marginLeft, '50px', // 10px + 20px + 20px
764     'Animated margin-left style at 0s of the third iteration');
765   anim.currentTime += anim.effect.timing.duration / 2;
766   assert_equals(getComputedStyle(div).marginLeft, '55px', // (50px + 60px) * 0.5
767     'Animated margin-left style at 50s of the third iteration');
768 }, 'iteration composition starts with non-zero value animation');
769
770 test(t => {
771   const div = createDiv(t);
772   const anim =
773     div.animate({ marginLeft: ['10px', '-10px'] },
774                 { duration: 100 * MS_PER_SEC,
775                   easing: 'linear',
776                   iterations: 10,
777                   iterationComposite: 'accumulate' });
778   anim.pause();
779
780   anim.currentTime = anim.effect.timing.duration / 2;
781   assert_equals(getComputedStyle(div).marginLeft,
782     '0px',
783     'Animated margin-left style at 50s of the first iteration');
784   anim.currentTime = anim.effect.timing.duration * 2;
785   assert_equals(getComputedStyle(div).marginLeft,
786     '-10px', // 10px + -10px + -10px
787     'Animated margin-left style at 0s of the third iteration');
788   anim.currentTime += anim.effect.timing.duration / 2;
789   assert_equals(getComputedStyle(div).marginLeft,
790     '-20px', // (-10px + -30px) * 0.5
791     'Animated margin-left style at 50s of the third iteration');
792 }, 'iteration composition with negative final value animation');
793
794 test(t => {
795   const div = createDiv(t);
796   const anim = div.animate({ marginLeft: ['0px', '10px'] },
797                            { duration: 100 * MS_PER_SEC,
798                              easing: 'linear',
799                              iterations: 10,
800                              iterationComposite: 'accumulate' });
801   anim.pause();
802
803   anim.currentTime =
804     anim.effect.timing.duration * 2 + anim.effect.timing.duration / 2;
805   assert_equals(getComputedStyle(div).marginLeft, '25px',
806     'Animated style at 50s of the third iteration');
807
808   // double its duration.
809   anim.effect.timing.duration = anim.effect.timing.duration * 2;
810   assert_equals(getComputedStyle(div).marginLeft, '12.5px',
811     'Animated style at 25s of the first iteration');
812
813   // half of original.
814   anim.effect.timing.duration = anim.effect.timing.duration / 4;
815   assert_equals(getComputedStyle(div).marginLeft, '50px',
816       'Animated style at 50s of the fourth iteration');
817 }, 'duration changes with an iteration composition operation of accumulate');
818
819 </script>