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