053c7becf34b4ea68349b7ad460c3f3440538ec2
[WebKit-https.git] / LayoutTests / imported / w3c / web-platform-tests / css / css-animations / KeyframeEffect-getKeyframes.tentative.html
1 <!doctype html>
2 <meta charset=utf-8>
3 <title>KeyframeEffect.getKeyframes() for CSS animations</title>
4 <!--  TODO: Add a more specific link for this once it is specified.  -->
5 <link rel="help" href="https://drafts.csswg.org/css-animations-2/">
6 <script src="/resources/testharness.js"></script>
7 <script src="/resources/testharnessreport.js"></script>
8 <script src="support/testcommon.js"></script>
9 <style>
10 @keyframes anim-empty { }
11
12 @keyframes anim-empty-frames {
13   from { }
14   to   { }
15 }
16
17 @keyframes anim-only-timing {
18   from { animation-timing-function: linear; }
19   to   { }
20 }
21
22 @keyframes anim-only-non-animatable {
23   from { animation-duration: 3s; }
24   to   { animation-duration: 5s; }
25 }
26
27 @keyframes anim-simple {
28   from { color: rgb(0, 0, 0); }
29   to   { color: rgb(255, 255, 255); }
30 }
31
32 @keyframes anim-simple-three {
33   from { color: rgb(0, 0, 0); }
34   50%  { color: rgb(0, 0, 255); }
35   to   { color: rgb(255, 255, 255); }
36 }
37
38 @keyframes anim-simple-timing {
39   from { color: rgb(0, 0, 0); animation-timing-function: linear; }
40   50%  { color: rgb(0, 0, 255);  animation-timing-function: ease-in-out; }
41   to   { color: rgb(255, 255, 255); animation-timing-function: step-end; }
42 }
43
44 @keyframes anim-simple-timing-some {
45   from { color: rgb(0, 0, 0); animation-timing-function: linear; }
46   50%  { color: rgb(0, 0, 255); }
47   to   { color: rgb(255, 255, 255); }
48 }
49
50 @keyframes anim-simple-shorthand {
51   from { margin: 8px; }
52   to   { margin: 16px; }
53 }
54
55 @keyframes anim-omit-to {
56   from { color: rgb(0, 0, 255); }
57 }
58
59 @keyframes anim-omit-from {
60   to   { color: rgb(0, 0, 255); }
61 }
62
63 @keyframes anim-omit-from-to {
64   50%  { color: rgb(0, 0, 255); }
65 }
66
67 @keyframes anim-partially-omit-to {
68   from { margin-top: 50px;
69          margin-bottom: 100px; }
70   to   { margin-top: 150px !important; /* ignored */
71          margin-bottom: 200px; }
72 }
73
74 @keyframes anim-different-props {
75   from { color: rgb(0, 0, 0); margin-top: 8px; }
76   25%  { color: rgb(0, 0, 255); }
77   75%  { margin-top: 12px; }
78   to   { color: rgb(255, 255, 255); margin-top: 16px }
79 }
80
81 @keyframes anim-different-props-and-easing {
82   from { color: rgb(0, 0, 0); margin-top: 8px; animation-timing-function: linear; }
83   25%  { color: rgb(0, 0, 255); animation-timing-function: step-end; }
84   75%  { margin-top: 12px; animation-timing-function: ease-in; }
85   to   { color: rgb(255, 255, 255); margin-top: 16px }
86 }
87
88 @keyframes anim-merge-offset {
89   from { color: rgb(0, 0, 0); }
90   to   { color: rgb(255, 255, 255); }
91   from { margin-top: 8px; }
92   to   { margin-top: 16px; }
93 }
94
95 @keyframes anim-merge-offset-and-easing {
96   from { color: rgb(0, 0, 0); animation-timing-function: step-end; }
97   to   { color: rgb(255, 255, 255); }
98   from { margin-top: 8px; animation-timing-function: linear; }
99   to   { margin-top: 16px; }
100   from { font-size: 16px; animation-timing-function: step-end; }
101   to   { font-size: 32px; }
102   from { padding-left: 2px; animation-timing-function: linear; }
103   to   { padding-left: 4px; }
104 }
105
106 @keyframes anim-no-merge-equiv-easing {
107   from { margin-top: 0px; animation-timing-function: steps(1, end); }
108   from { margin-right: 0px; animation-timing-function: step-end; }
109   from { margin-bottom: 0px; animation-timing-function: steps(1); }
110   50%  { margin-top: 10px; animation-timing-function: step-end; }
111   50%  { margin-right: 10px; animation-timing-function: step-end; }
112   50%  { margin-bottom: 10px; animation-timing-function: step-end; }
113   to   { margin-top: 20px; margin-right: 20px; margin-bottom: 20px; }
114 }
115
116 @keyframes anim-overriding {
117   from          { padding-top: 50px }
118   50%, from     { padding-top: 30px } /* wins: 0% */
119   75%, 85%, 50% { padding-top: 20px } /* wins: 75%, 50% */
120   100%, 85%     { padding-top: 70px } /* wins: 100% */
121   85.1%         { padding-top: 60px } /* wins: 85.1% */
122   85%           { padding-top: 30px } /* wins: 85% */
123 }
124
125 @keyframes anim-filter {
126   to { filter: blur(5px) sepia(60%) saturate(30%); }
127 }
128
129 @keyframes anim-filter-drop-shadow {
130   from { filter: drop-shadow(10px 10px 10px rgb(0, 255, 0)); }
131   to { filter: drop-shadow(50px 30px 10px rgb(255, 0, 0)); }
132 }
133
134 @keyframes anim-text-shadow {
135   to { text-shadow: none; }
136 }
137
138 @keyframes anim-background-size {
139   to { background-size: 50%, 6px, contain }
140 }
141
142 :root {
143   --var-100px: 100px;
144   --end-color: rgb(255, 0, 0);
145 }
146 @keyframes anim-variables {
147   to { transform: translate(var(--var-100px), 0) }
148 }
149 @keyframes anim-variables-shorthand {
150   to { margin: var(--var-100px) }
151 }
152 @keyframes anim-custom-property-in-keyframe {
153   to { --end-color: rgb(0, 255, 0); color: var(--end-color) }
154 }
155 @keyframes anim-only-custom-property-in-keyframe {
156   from { transform: translate(100px, 0) }
157   to { --not-used: 200px }
158 }
159 </style>
160 <body>
161 <div id="log"></div>
162 <script>
163 "use strict";
164
165 const getKeyframes = elem => elem.getAnimations()[0].effect.getKeyframes();
166
167 const assert_frames_equal = (a, b, name) => {
168   assert_equals(Object.keys(a).sort().toString(),
169                 Object.keys(b).sort().toString(),
170                 "properties on " + name);
171   for (const p in a) {
172     if (p === 'offset' || p === 'computedOffset') {
173       assert_approx_equals(a[p], b[p], 0.00001,
174                            "value for '" + p + "' on " + name);
175     } else {
176       assert_equals(a[p], b[p], "value for '" + p + "' on " + name);
177     }
178   }
179 };
180
181 // animation-timing-function values to test with, where the value
182 // is exactly the same as its serialization, sorted by the order
183 // getKeyframes() will group frames with the same easing function
184 // together (by nsTimingFunction::Compare).
185 const kTimingFunctionValues = [
186   "ease",
187   "linear",
188   "ease-in",
189   "ease-out",
190   "ease-in-out",
191   "steps(1, start)",
192   "steps(2, start)",
193   "steps(1)",
194   "steps(2)",
195   "cubic-bezier(0, 0, 1, 1)",
196   "cubic-bezier(0, 0.25, 0.75, 1)"
197 ];
198
199 test(t => {
200   const div = addDiv(t);
201
202   div.style.animation = 'anim-empty 100s';
203   assert_equals(getKeyframes(div).length, 0,
204                 "number of frames with empty @keyframes");
205
206   div.style.animation = 'anim-empty-frames 100s';
207   assert_equals(getKeyframes(div).length, 0,
208                 "number of frames when @keyframes has empty keyframes");
209
210   div.style.animation = 'anim-only-timing 100s';
211   assert_equals(getKeyframes(div).length, 0,
212                 "number of frames when @keyframes only has keyframes with " +
213                 "animation-timing-function");
214
215   div.style.animation = 'anim-only-non-animatable 100s';
216   assert_equals(getKeyframes(div).length, 0,
217                 "number of frames when @keyframes only has frames with " +
218                 "non-animatable properties");
219 }, 'KeyframeEffect.getKeyframes() returns no frames for various kinds'
220    + ' of empty enimations');
221
222 test(t => {
223   const div = addDiv(t);
224
225   div.style.animation = 'anim-simple 100s';
226   const frames = getKeyframes(div);
227
228   assert_equals(frames.length, 2, "number of frames");
229
230   const expected = [
231     { offset: 0, computedOffset: 0, easing: "ease",
232       color: "rgb(0, 0, 0)", composite: "auto" },
233     { offset: 1, computedOffset: 1, easing: "ease",
234       color: "rgb(255, 255, 255)", composite: "auto" },
235   ];
236
237   for (let i = 0; i < frames.length; i++) {
238     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
239   }
240 }, 'KeyframeEffect.getKeyframes() returns expected frames for a simple'
241    + ' animation');
242
243 test(t => {
244   for (const easing of kTimingFunctionValues) {
245     const div = addDiv(t);
246
247     div.style.animation = 'anim-simple-three 100s ' + easing;
248     const frames = getKeyframes(div);
249
250     assert_equals(frames.length, 3, "number of frames");
251
252     for (let i = 0; i < frames.length; i++) {
253       assert_equals(frames[i].easing, easing,
254                     "value for 'easing' on ComputedKeyframe #" + i);
255     }
256   }
257 }, 'KeyframeEffect.getKeyframes() returns frames with expected easing'
258    + ' values, when the easing comes from animation-timing-function on the'
259    + ' element');
260
261 test(t => {
262   const div = addDiv(t);
263
264   div.style.animation = 'anim-simple-timing 100s';
265   const frames = getKeyframes(div);
266
267   assert_equals(frames.length, 3, "number of frames");
268   assert_equals(frames[0].easing, "linear",
269                 "value of 'easing' on ComputedKeyframe #0");
270   assert_equals(frames[1].easing, "ease-in-out",
271                 "value of 'easing' on ComputedKeyframe #1");
272   assert_equals(frames[2].easing, "steps(1)",
273                 "value of 'easing' on ComputedKeyframe #2");
274 }, 'KeyframeEffect.getKeyframes() returns frames with expected easing'
275    + ' values, when the easing is specified on each keyframe');
276
277 test(t => {
278   const div = addDiv(t);
279
280   div.style.animation = 'anim-simple-timing-some 100s step-start';
281   const frames = getKeyframes(div);
282
283   assert_equals(frames.length, 3, "number of frames");
284   assert_equals(frames[0].easing, "linear",
285                 "value of 'easing' on ComputedKeyframe #0");
286   assert_equals(frames[1].easing, "steps(1, start)",
287                 "value of 'easing' on ComputedKeyframe #1");
288   assert_equals(frames[2].easing, "steps(1, start)",
289                 "value of 'easing' on ComputedKeyframe #2");
290 }, 'KeyframeEffect.getKeyframes() returns frames with expected easing'
291    + ' values, when the easing is specified on some keyframes');
292
293 test(t => {
294   const div = addDiv(t);
295
296   div.style.animation = 'anim-simple-shorthand 100s';
297   const frames = getKeyframes(div);
298
299   assert_equals(frames.length, 2, "number of frames");
300
301   const expected = [
302     { offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
303       marginBottom: "8px", marginLeft: "8px",
304       marginRight: "8px", marginTop: "8px" },
305     { offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
306       marginBottom: "16px", marginLeft: "16px",
307       marginRight: "16px", marginTop: "16px" },
308   ];
309
310   for (let i = 0; i < frames.length; i++) {
311     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
312   }
313 }, 'KeyframeEffect.getKeyframes() returns expected frames for a simple'
314    + ' animation that specifies a single shorthand property');
315
316 test(t => {
317   const div = addDiv(t);
318
319   div.style.animation = 'anim-omit-to 100s';
320   div.style.color = 'rgb(255, 255, 255)';
321   const frames = getKeyframes(div);
322
323   assert_equals(frames.length, 2, "number of frames");
324
325   const expected = [
326     { offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
327       color: "rgb(0, 0, 255)" },
328     { offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
329       color: "rgb(255, 255, 255)" },
330   ];
331
332   for (let i = 0; i < frames.length; i++) {
333     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
334   }
335 }, 'KeyframeEffect.getKeyframes() returns expected frames for an ' +
336    'animation with a 0% keyframe and no 100% keyframe');
337
338 test(t => {
339   const div = addDiv(t);
340
341   div.style.animation = 'anim-omit-from 100s';
342   div.style.color = 'rgb(255, 255, 255)';
343   const frames = getKeyframes(div);
344
345   assert_equals(frames.length, 2, "number of frames");
346
347   const expected = [
348     { offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
349       color: "rgb(255, 255, 255)" },
350     { offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
351       color: "rgb(0, 0, 255)" },
352   ];
353
354   for (let i = 0; i < frames.length; i++) {
355     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
356   }
357 }, 'KeyframeEffect.getKeyframes() returns expected frames for an ' +
358    'animation with a 100% keyframe and no 0% keyframe');
359
360 test(t => {
361   const div = addDiv(t);
362
363   div.style.animation = 'anim-omit-from-to 100s';
364   div.style.color = 'rgb(255, 255, 255)';
365   const frames = getKeyframes(div);
366
367   assert_equals(frames.length, 3, "number of frames");
368
369   const expected = [
370     { offset: 0,   computedOffset: 0,   easing: "ease", composite: "auto",
371       color: "rgb(255, 255, 255)" },
372     { offset: 0.5, computedOffset: 0.5, easing: "ease", composite: "auto",
373       color: "rgb(0, 0, 255)" },
374     { offset: 1,   computedOffset: 1,   easing: "ease", composite: "auto",
375       color: "rgb(255, 255, 255)" },
376   ];
377
378   for (let i = 0; i < frames.length; i++) {
379     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
380   }
381 }, 'KeyframeEffect.getKeyframes() returns expected frames for an ' +
382    'animation with no 0% or 100% keyframe but with a 50% keyframe');
383
384 test(t => {
385   const div = addDiv(t);
386
387   div.style.animation = 'anim-partially-omit-to 100s';
388   div.style.marginTop = '250px';
389   const frames = getKeyframes(div);
390
391   assert_equals(frames.length, 2, "number of frames");
392
393   const expected = [
394     { offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
395       marginTop: '50px', marginBottom: '100px' },
396     { offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
397       marginTop: '250px', marginBottom: '200px' },
398   ];
399
400   for (let i = 0; i < frames.length; i++) {
401     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
402   }
403 }, 'KeyframeEffect.getKeyframes() returns expected frames for an ' +
404    'animation with a partially complete 100% keyframe (because the ' +
405    '!important rule is ignored)');
406
407 test(t => {
408   const div = addDiv(t);
409
410   div.style.animation = 'anim-different-props 100s';
411   const frames = getKeyframes(div);
412
413   assert_equals(frames.length, 4, "number of frames");
414
415   const expected = [
416     { offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
417       color: "rgb(0, 0, 0)", marginTop: "8px" },
418     { offset: 0.25, computedOffset: 0.25, easing: "ease", composite: "auto",
419       color: "rgb(0, 0, 255)" },
420     { offset: 0.75, computedOffset: 0.75, easing: "ease", composite: "auto",
421       marginTop: "12px" },
422     { offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
423       color: "rgb(255, 255, 255)", marginTop: "16px" },
424   ];
425
426   for (let i = 0; i < frames.length; i++) {
427     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
428   }
429 }, 'KeyframeEffect.getKeyframes() returns expected frames for an ' +
430    'animation with different properties on different keyframes, all ' +
431    'with the same easing function');
432
433 test(t => {
434   const div = addDiv(t);
435
436   div.style.animation = 'anim-different-props-and-easing 100s';
437   const frames = getKeyframes(div);
438
439   assert_equals(frames.length, 4, "number of frames");
440
441   const expected = [
442     { offset: 0, computedOffset: 0, easing: "linear", composite: "auto",
443       color: "rgb(0, 0, 0)", marginTop: "8px" },
444     { offset: 0.25, computedOffset: 0.25, easing: "steps(1)", composite: "auto",
445       color: "rgb(0, 0, 255)" },
446     { offset: 0.75, computedOffset: 0.75, easing: "ease-in", composite: "auto",
447       marginTop: "12px" },
448     { offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
449       color: "rgb(255, 255, 255)", marginTop: "16px" },
450   ];
451
452   for (let i = 0; i < frames.length; i++) {
453     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
454   }
455 }, 'KeyframeEffect.getKeyframes() returns expected frames for an ' +
456    'animation with different properties on different keyframes, with ' +
457    'a different easing function on each');
458
459 test(t => {
460   const div = addDiv(t);
461
462   div.style.animation = 'anim-merge-offset 100s';
463   const frames = getKeyframes(div);
464
465   assert_equals(frames.length, 2, "number of frames");
466
467   const expected = [
468     { offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
469       color: "rgb(0, 0, 0)", marginTop: "8px" },
470     { offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
471       color: "rgb(255, 255, 255)", marginTop: "16px" },
472   ];
473
474   for (let i = 0; i < frames.length; i++) {
475     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
476   }
477 }, 'KeyframeEffect.getKeyframes() returns expected frames for an ' +
478    'animation with multiple keyframes for the same time, and all with ' +
479    'the same easing function');
480
481 test(t => {
482   const div = addDiv(t);
483
484   div.style.animation = 'anim-merge-offset-and-easing 100s';
485   const frames = getKeyframes(div);
486
487   assert_equals(frames.length, 3, "number of frames");
488
489   const expected = [
490     { offset: 0, computedOffset: 0, easing: "steps(1)", composite: "auto",
491       color: "rgb(0, 0, 0)", fontSize: "16px" },
492     { offset: 0, computedOffset: 0, easing: "linear", composite: "auto",
493       marginTop: "8px", paddingLeft: "2px" },
494     { offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
495       color: "rgb(255, 255, 255)", fontSize: "32px", marginTop: "16px",
496       paddingLeft: "4px" },
497   ];
498
499   for (let i = 0; i < frames.length; i++) {
500     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
501   }
502 }, 'KeyframeEffect.getKeyframes() returns expected frames for an ' +
503    'animation with multiple keyframes for the same time and with ' +
504    'different easing functions');
505
506 test(t => {
507   const div = addDiv(t);
508
509   div.style.animation = 'anim-no-merge-equiv-easing 100s';
510   const frames = getKeyframes(div);
511
512   assert_equals(frames.length, 3, "number of frames");
513
514   const expected = [
515     { offset: 0, computedOffset: 0, easing: "steps(1)", composite: "auto",
516       marginTop: "0px", marginRight: "0px", marginBottom: "0px" },
517     { offset: 0.5, computedOffset: 0.5, easing: "steps(1)", composite: "auto",
518       marginTop: "10px", marginRight: "10px", marginBottom: "10px" },
519     { offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
520       marginTop: "20px", marginRight: "20px", marginBottom: "20px" },
521   ];
522
523   for (let i = 0; i < frames.length; i++) {
524     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
525   }
526 }, 'KeyframeEffect.getKeyframes() returns expected frames for an ' +
527    'animation with multiple keyframes for the same time and with ' +
528    'different but equivalent easing functions');
529
530 test(t => {
531   const div = addDiv(t);
532
533   div.style.animation = 'anim-overriding 100s';
534   const frames = getKeyframes(div);
535
536   assert_equals(frames.length, 6, "number of frames");
537
538   const expected = [
539     { offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
540       paddingTop: "30px" },
541     { offset: 0.5, computedOffset: 0.5, easing: "ease", composite: "auto",
542       paddingTop: "20px" },
543     { offset: 0.75, computedOffset: 0.75, easing: "ease", composite: "auto",
544       paddingTop: "20px" },
545     { offset: 0.85, computedOffset: 0.85, easing: "ease", composite: "auto",
546       paddingTop: "30px" },
547     { offset: 0.851, computedOffset: 0.851, easing: "ease", composite: "auto",
548       paddingTop: "60px" },
549     { offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
550       paddingTop: "70px" },
551   ];
552
553   for (let i = 0; i < frames.length; i++) {
554     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
555   }
556 }, 'KeyframeEffect.getKeyframes() returns expected frames for ' +
557    'overlapping keyframes');
558
559 // Gecko-specific test case: We are specifically concerned here that the
560 // computed value for filter, "none", is correctly represented.
561
562 test(t => {
563   const div = addDiv(t);
564
565   div.style.animation = 'anim-filter 100s';
566   const frames = getKeyframes(div);
567
568   assert_equals(frames.length, 2, "number of frames");
569
570   const expected = [
571     { offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
572       filter: "none" },
573     { offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
574       filter: "blur(5px) sepia(60%) saturate(30%)" },
575   ];
576
577   for (let i = 0; i < frames.length; i++) {
578     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
579   }
580 }, 'KeyframeEffect.getKeyframes() returns expected values for ' +
581    'animations with filter properties and missing keyframes');
582
583 test(t => {
584   const div = addDiv(t);
585
586   div.style.animation = 'anim-filter-drop-shadow 100s';
587   const frames = getKeyframes(div);
588
589   assert_equals(frames.length, 2, "number of frames");
590
591   const expected = [
592     { offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
593       filter: "drop-shadow(rgb(0, 255, 0) 10px 10px 10px)" },
594     { offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
595       filter: "drop-shadow(rgb(255, 0, 0) 50px 30px 10px)" },
596   ];
597
598   for (let i = 0; i < frames.length; i++) {
599     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
600   }
601 }, 'KeyframeEffect.getKeyframes() returns expected values for ' +
602    'animation with drop-shadow of filter property');
603
604 // Gecko-specific test case: We are specifically concerned here that the
605 // computed value for text-shadow and a "none" specified on a keyframe
606 // are correctly represented.
607
608 test(t => {
609   const div = addDiv(t);
610
611   div.style.textShadow = '1px 1px 2px rgb(0, 0, 0), ' +
612                          '0 0 16px rgb(0, 0, 255), ' +
613                          '0 0 3.2px rgb(0, 0, 255)';
614   div.style.animation = 'anim-text-shadow 100s';
615   const frames = getKeyframes(div);
616
617   assert_equals(frames.length, 2, "number of frames");
618
619   const expected = [
620     { offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
621       textShadow: "rgb(0, 0, 0) 1px 1px 2px,"
622                   + " rgb(0, 0, 255) 0px 0px 16px,"
623                   + " rgb(0, 0, 255) 0px 0px 3.2px" },
624     { offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
625       textShadow: "none" },
626   ];
627
628   for (let i = 0; i < frames.length; i++) {
629     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
630   }
631 }, 'KeyframeEffect.getKeyframes() returns expected values for ' +
632    'animations with text-shadow properties and missing keyframes');
633
634 // Gecko-specific test case: We are specifically concerned here that the
635 // initial value for background-size and the specified list are correctly
636 // represented.
637
638 test(t => {
639   const div = addDiv(t);
640
641   div.style.animation = 'anim-background-size 100s';
642   let frames = getKeyframes(div);
643
644   assert_equals(frames.length, 2, "number of frames");
645
646   const expected = [
647     { offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
648       backgroundSize: "auto" },
649     { offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
650       backgroundSize: "50%, 6px, contain" },
651   ];
652
653   for (let i = 0; i < frames.length; i++) {
654     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
655   }
656
657   // Test inheriting a background-size value
658
659   expected[0].backgroundSize = div.style.backgroundSize =
660     "30px, 40%, auto";
661   frames = getKeyframes(div);
662
663   for (let i = 0; i < frames.length; i++) {
664     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i
665                         + " after updating current style");
666   }
667 }, 'KeyframeEffect.getKeyframes() returns expected values for ' +
668    'animations with background-size properties and missing keyframes');
669
670 test(t => {
671   const div = addDiv(t);
672   div.style.animation = 'anim-variables 100s';
673
674   const frames = getKeyframes(div);
675
676   assert_equals(frames.length, 2, "number of frames");
677
678   const expected = [
679     { offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
680       transform: "none" },
681     { offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
682       transform: "translate(100px)" },
683   ];
684   for (let i = 0; i < frames.length; i++) {
685     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
686   }
687 }, 'KeyframeEffect.getKeyframes() returns expected values for ' +
688    'animations with CSS variables as keyframe values');
689
690 test(t => {
691   const div = addDiv(t);
692   div.style.animation = 'anim-variables-shorthand 100s';
693
694   const frames = getKeyframes(div);
695
696   assert_equals(frames.length, 2, "number of frames");
697
698   const expected = [
699     { offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
700       marginBottom: "0px",
701       marginLeft: "0px",
702       marginRight: "0px",
703       marginTop: "0px" },
704     { offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
705       marginBottom: "100px",
706       marginLeft: "100px",
707       marginRight: "100px",
708       marginTop: "100px" },
709   ];
710   for (let i = 0; i < frames.length; i++) {
711     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
712   }
713 }, 'KeyframeEffect.getKeyframes() returns expected values for ' +
714    'animations with CSS variables as keyframe values in a shorthand property');
715
716 test(t => {
717   const div = addDiv(t);
718   div.style.animation = 'anim-custom-property-in-keyframe 100s';
719
720   const frames = getKeyframes(div);
721
722   assert_equals(frames.length, 2, "number of frames");
723
724   const expected = [
725     { offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
726       color: "rgb(0, 0, 0)" },
727     { offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
728       color: "rgb(0, 255, 0)" },
729   ];
730   for (let i = 0; i < frames.length; i++) {
731     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
732   }
733 }, 'KeyframeEffect.getKeyframes() returns expected values for ' +
734    'animations with a CSS variable which is overriden by the value in keyframe');
735
736 test(t => {
737   const div = addDiv(t);
738   div.style.animation = 'anim-only-custom-property-in-keyframe 100s';
739
740   const frames = getKeyframes(div);
741
742   assert_equals(frames.length, 2, "number of frames");
743
744   const expected = [
745     { offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
746       transform: "translate(100px)" },
747     { offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
748       transform: "none" },
749   ];
750   for (let i = 0; i < frames.length; i++) {
751     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
752   }
753 }, 'KeyframeEffect.getKeyframes() returns expected values for ' +
754    'animations with only custom property in a keyframe');
755
756 </script>
757 </body>