175acf8424688c29e2b433226c6c4af11d176eb3
[WebKit-https.git] / LayoutTests / imported / w3c / web-platform-tests / css / css-animations / Document-getAnimations.tentative.html
1 <!doctype html>
2 <meta charset=utf-8>
3 <title>Document.getAnimations() for CSS animations</title>
4 <link rel="help" href="https://drafts.csswg.org/css-animations-2/#animation-composite-order">
5 <script src="/resources/testharness.js"></script>
6 <script src="/resources/testharnessreport.js"></script>
7 <script src="support/testcommon.js"></script>
8 <style>
9 @keyframes animLeft {
10   to { left: 100px }
11 }
12 @keyframes animTop {
13   to { top: 100px }
14 }
15 @keyframes animBottom {
16   to { bottom: 100px }
17 }
18 @keyframes animRight {
19   to { right: 100px }
20 }
21 </style>
22 <div id="log"></div>
23 <script>
24 'use strict';
25
26 test(t => {
27   assert_equals(document.getAnimations().length, 0,
28     'getAnimations returns an empty sequence for a document'
29     + ' with no animations');
30 }, 'getAnimations for non-animated content');
31
32 test(t => {
33   const div = addDiv(t);
34
35   // Add an animation
36   div.style.animation = 'animLeft 100s';
37   assert_equals(document.getAnimations().length, 1,
38                 'getAnimations returns a running CSS Animation');
39
40   // Add another animation
41   div.style.animation = 'animLeft 100s, animTop 100s';
42   assert_equals(document.getAnimations().length, 2,
43                 'getAnimations returns two running CSS Animations');
44
45   // Remove both
46   div.style.animation = '';
47   assert_equals(document.getAnimations().length, 0,
48                 'getAnimations returns no running CSS Animations');
49 }, 'getAnimations for CSS Animations');
50
51 test(t => {
52   const div = addDiv(t);
53   div.style.animation = 'animLeft 100s, animTop 100s, animRight 100s, ' +
54                         'animBottom 100s';
55
56   const animations = document.getAnimations();
57   assert_equals(animations.length, 4,
58                 'getAnimations returns all running CSS Animations');
59   assert_equals(animations[0].animationName, 'animLeft',
60                 'Order of first animation returned');
61   assert_equals(animations[1].animationName, 'animTop',
62                 'Order of second animation returned');
63   assert_equals(animations[2].animationName, 'animRight',
64                 'Order of third animation returned');
65   assert_equals(animations[3].animationName, 'animBottom',
66                 'Order of fourth animation returned');
67 }, 'Order of CSS Animations - within an element');
68
69 test(t => {
70   const div1 = addDiv(t, { style: 'animation: animLeft 100s' });
71   const div2 = addDiv(t, { style: 'animation: animLeft 100s' });
72   const div3 = addDiv(t, { style: 'animation: animLeft 100s' });
73   const div4 = addDiv(t, { style: 'animation: animLeft 100s' });
74
75   let animations = document.getAnimations();
76   assert_equals(animations.length, 4,
77                 'getAnimations returns all running CSS Animations');
78   assert_equals(animations[0].effect.target, div1,
79                 'Order of first animation returned');
80   assert_equals(animations[1].effect.target, div2,
81                 'Order of second animation returned');
82   assert_equals(animations[2].effect.target, div3,
83                 'Order of third animation returned');
84   assert_equals(animations[3].effect.target, div4,
85                 'Order of fourth animation returned');
86
87   // Order should be depth-first pre-order so add some depth as follows:
88   //
89   //      <parent>
90   //       /  |
91   //      2   3
92   //    /  \
93   //   1   4
94   //
95   // Which should give: 2, 1, 4, 3
96   div2.appendChild(div1);
97   div2.appendChild(div4);
98   animations = document.getAnimations();
99   assert_equals(animations[0].effect.target, div2,
100                 'Order of first animation returned after tree surgery');
101   assert_equals(animations[1].effect.target, div1,
102                 'Order of second animation returned after tree surgery');
103   assert_equals(animations[2].effect.target, div4,
104                 'Order of third animation returned after tree surgery');
105   assert_equals(animations[3].effect.target, div3,
106                 'Order of fourth animation returned after tree surgery');
107
108 }, 'Order of CSS Animations - across elements');
109
110 test(t => {
111   const div1 = addDiv(t, { style: 'animation: animLeft 100s, animTop 100s' });
112   const div2 = addDiv(t, { style: 'animation: animBottom 100s' });
113
114   let expectedResults = [ [ div1, 'animLeft' ],
115                             [ div1, 'animTop' ],
116                             [ div2, 'animBottom' ] ];
117   let animations = document.getAnimations();
118   assert_equals(animations.length, expectedResults.length,
119                 'getAnimations returns all running CSS Animations');
120   animations.forEach((anim, i) => {
121     assert_equals(anim.effect.target, expectedResults[i][0],
122                   'Target of animation in position ' + i);
123     assert_equals(anim.animationName, expectedResults[i][1],
124                   'Name of animation in position ' + i);
125   });
126
127   // Modify tree structure and animation list
128   div2.appendChild(div1);
129   div1.style.animation = 'animLeft 100s, animRight 100s, animTop 100s';
130
131   expectedResults = [ [ div2, 'animBottom' ],
132                       [ div1, 'animLeft' ],
133                       [ div1, 'animRight' ],
134                       [ div1, 'animTop' ] ];
135   animations = document.getAnimations();
136   assert_equals(animations.length, expectedResults.length,
137                 'getAnimations returns all running CSS Animations after ' +
138                 'making changes');
139   animations.forEach((anim, i) => {
140     assert_equals(anim.effect.target, expectedResults[i][0],
141                   'Target of animation in position ' + i + ' after changes');
142     assert_equals(anim.animationName, expectedResults[i][1],
143                   'Name of animation in position ' + i + ' after changes');
144   });
145 }, 'Order of CSS Animations - across and within elements');
146
147 test(t => {
148   const div = addDiv(t, { style: 'animation: animLeft 100s, animTop 100s' });
149   const animLeft = document.getAnimations()[0];
150   assert_equals(animLeft.animationName, 'animLeft',
151                 'Originally, animLeft animation comes first');
152
153   // Disassociate animLeft from markup and restart
154   div.style.animation = 'animTop 100s';
155   animLeft.play();
156
157   const animations = document.getAnimations();
158   assert_equals(animations.length, 2,
159                 'getAnimations returns markup-bound and free animations');
160   assert_equals(animations[0].animationName, 'animTop',
161                 'Markup-bound animations come first');
162   assert_equals(animations[1], animLeft, 'Free animations come last');
163 }, 'Order of CSS Animations - markup-bound vs free animations');
164
165 test(t => {
166   const div = addDiv(t, { style: 'animation: animLeft 100s, animTop 100s' });
167   const animLeft = document.getAnimations()[0];
168   const animTop  = document.getAnimations()[1];
169
170   // Disassociate both animations from markup and restart in opposite order
171   div.style.animation = '';
172   animTop.play();
173   animLeft.play();
174
175   const animations = document.getAnimations();
176   assert_equals(animations.length, 2,
177                 'getAnimations returns free animations');
178   assert_equals(animations[0], animTop,
179                 'Free animations are returned in the order they are started');
180   assert_equals(animations[1], animLeft,
181                 'Animations started later are returned later');
182
183   // Restarting an animation should have no effect
184   animTop.cancel();
185   animTop.play();
186   assert_equals(document.getAnimations()[0], animTop,
187                 'After restarting, the ordering of free animations' +
188                 ' does not change');
189 }, 'Order of CSS Animations - free animations');
190
191 test(t => {
192   // Add an animation first
193   const div = addDiv(t, { style: 'animation: animLeft 100s' });
194   div.style.top = '0px';
195   div.style.transition = 'all 100s';
196   flushComputedStyle(div);
197
198   // *Then* add a transition
199   div.style.top = '100px';
200   flushComputedStyle(div);
201
202   // Although the transition was added later, it should come first in the list
203   const animations = document.getAnimations();
204   assert_equals(animations.length, 2,
205                 'Both CSS animations and transitions are returned');
206   assert_class_string(animations[0], 'CSSTransition', 'Transition comes first');
207   assert_class_string(animations[1], 'CSSAnimation', 'Animation comes second');
208 }, 'Order of CSS Animations and CSS Transitions');
209
210 test(t => {
211   const div = addDiv(t, { style: 'animation: animLeft 100s forwards' });
212   div.getAnimations()[0].finish();
213   assert_equals(document.getAnimations().length, 1,
214                 'Forwards-filling CSS animations are returned');
215 }, 'Finished but filling CSS Animations are returned');
216
217 test(t => {
218   const div = addDiv(t, { style: 'animation: animLeft 100s' });
219   div.getAnimations()[0].finish();
220   assert_equals(document.getAnimations().length, 0,
221                 'Non-filling finished CSS animations are not returned');
222 }, 'Finished but not filling CSS Animations are not returned');
223
224 test(t => {
225   const div = addDiv(t, { style: 'animation: animLeft 100s 100s' });
226   assert_equals(document.getAnimations().length, 1,
227                 'Yet-to-start CSS animations are returned');
228 }, 'Yet-to-start CSS Animations are returned');
229
230 test(t => {
231   const div = addDiv(t, { style: 'animation: animLeft 100s' });
232   div.getAnimations()[0].cancel();
233   assert_equals(document.getAnimations().length, 0,
234                 'CSS animations canceled by the API are not returned');
235 }, 'CSS Animations canceled via the API are not returned');
236
237 test(t => {
238   const div = addDiv(t, { style: 'animation: animLeft 100s' });
239   const anim = div.getAnimations()[0];
240   anim.cancel();
241   anim.play();
242   assert_equals(document.getAnimations().length, 1,
243                 'CSS animations canceled and restarted by the API are ' +
244                 'returned');
245 }, 'CSS Animations canceled and restarted via the API are returned');
246
247 test(t => {
248   // Create two divs with the following arrangement:
249   //
250   //       parent
251   //    (::marker,)
252   //     ::before,
253   //     ::after
254   //        |
255   //       child
256
257   addStyle(t, {
258     '#parent::after': "content: ''; animation: animLeft 100s;",
259     '#parent::before': "content: ''; animation: animRight 100s;",
260   });
261
262   const supportsMarkerPseudos = CSS.supports('selector(::marker)');
263   if (supportsMarkerPseudos) {
264     addStyle(t, {
265       '#parent': 'display: list-item;',
266       '#parent::marker': "content: ''; animation: animLeft 100s;",
267     });
268   }
269
270   const parent = addDiv(t, { id: 'parent' });
271   const child = addDiv(t);
272   parent.appendChild(child);
273   for (const div of [parent, child]) {
274     div.setAttribute('style', 'animation: animBottom 100s');
275   }
276
277   const expectedAnimations = [
278     [parent, undefined],
279     [parent, '::marker'],
280     [parent, '::before'],
281     [parent, '::after'],
282     [child, undefined],
283   ];
284   if (!supportsMarkerPseudos) {
285     expectedAnimations.splice(1, 1);
286   }
287
288   const animations = document.getAnimations();
289   assert_equals(
290     animations.length,
291     expectedAnimations.length,
292     'CSS animations on both pseudo-elements and elements are returned'
293   );
294
295   for (const [index, expected] of expectedAnimations.entries()) {
296     const [element, pseudo] = expected;
297     const actual = animations[index];
298
299     if (pseudo) {
300       assert_equals(
301         actual.effect.target.element,
302         element,
303         `Animation #${index + 1} has expected target`
304       );
305       assert_equals(
306         actual.effect.target.type,
307         pseudo,
308         `Animation #${index + 1} has expected pseudo type`
309       );
310     } else {
311       assert_equals(
312         actual.effect.target,
313         element,
314         `Animation #${index + 1} has expected target`
315       );
316     }
317   }
318 }, 'CSS Animations targetting (pseudo-)elements should have correct order '
319    + 'after sorting');
320
321 </script>