getAnimations.html (8366B)
1 <!DOCTYPE html> 2 <meta charset=utf-8> 3 <title>DocumentOrShadowRoot.getAnimations</title> 4 <link rel="help" href="https://drafts.csswg.org/web-animations-1/#dom-documentorshadowroot-getanimations"> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 <script src="../../testcommon.js"></script> 8 <body> 9 <div id="log"></div> 10 <div id="target"></div> 11 <script> 12 'use strict'; 13 14 const gKeyFrames = { 'marginLeft': ['100px', '200px'] }; 15 16 test(t => { 17 assert_equals(document.getAnimations().length, 0, 18 'getAnimations returns an empty sequence for a document ' + 19 'with no animations'); 20 }, 'Document.getAnimations() returns an empty sequence for non-animated' 21 + ' content'); 22 23 test(t => { 24 const div = createDiv(t); 25 const anim1 = div.animate(gKeyFrames, 100 * MS_PER_SEC); 26 const anim2 = div.animate(gKeyFrames, 100 * MS_PER_SEC); 27 assert_equals(document.getAnimations().length, 2, 28 'getAnimation returns running animations'); 29 30 anim1.finish(); 31 anim2.finish(); 32 assert_equals(document.getAnimations().length, 0, 33 'getAnimation only returns running animations'); 34 }, 'Document.getAnimations() returns script-generated animations') 35 36 test(t => { 37 const div = createDiv(t); 38 const anim1 = div.animate(gKeyFrames, 100 * MS_PER_SEC); 39 const anim2 = div.animate(gKeyFrames, 100 * MS_PER_SEC); 40 assert_array_equals(document.getAnimations(), 41 [ anim1, anim2 ], 42 'getAnimations() returns running animations'); 43 }, 'Document.getAnimations() returns script-generated animations in the order' 44 + ' they were created') 45 46 test(t => { 47 // This element exists but is not a descendent of any document, so isn't 48 // picked up by getAnimations. 49 const div = document.createElement('div'); 50 const anim = div.animate(gKeyFrames, 100 * MS_PER_SEC); 51 assert_equals(document.getAnimations().length, 0); 52 53 // Now connect the div; it should appear in the list of animations. 54 document.body.appendChild(div); 55 t.add_cleanup(() => { div.remove(); }); 56 assert_equals(document.getAnimations().length, 1); 57 }, 'Document.getAnimations() does not return a disconnected node'); 58 59 test(t => { 60 const effect = new KeyframeEffect(null, gKeyFrames, 100 * MS_PER_SEC); 61 const anim = new Animation(effect, document.timeline); 62 anim.play(); 63 64 assert_equals(document.getAnimations().length, 0, 65 'document.getAnimations() only returns animations targeting ' + 66 'elements in this document'); 67 }, 'Document.getAnimations() does not return an animation with a null target'); 68 69 promise_test(async t => { 70 const iframe = document.createElement('iframe'); 71 await insertFrameAndAwaitLoad(t, iframe, document) 72 73 const div = createDiv(t, iframe.contentDocument) 74 const effect = new KeyframeEffect(div, null, 100 * MS_PER_SEC); 75 const anim = new Animation(effect, document.timeline); 76 anim.play(); 77 78 // The animation's timeline is from the main document, but the effect's 79 // target element is part of the iframe document and that is what matters 80 // for getAnimations. 81 assert_equals(document.getAnimations().length, 0); 82 assert_equals(iframe.contentDocument.getAnimations().length, 1); 83 anim.finish(); 84 }, 'Document.getAnimations() returns animations on elements inside same-origin' 85 + ' iframes'); 86 87 promise_test(async t => { 88 const iframe1 = document.createElement('iframe'); 89 const iframe2 = document.createElement('iframe'); 90 91 await insertFrameAndAwaitLoad(t, iframe1, document); 92 await insertFrameAndAwaitLoad(t, iframe2, document); 93 94 const div_frame1 = createDiv(t, iframe1.contentDocument) 95 const div_main_frame = createDiv(t) 96 const effect1 = new KeyframeEffect(div_frame1, null, 100 * MS_PER_SEC); 97 const anim1 = new Animation(effect1, document.timeline); 98 anim1.play(); 99 // Animation of div_frame1 is in iframe with main timeline. 100 // The animation's timeline is from the iframe, but the effect's target 101 // element is part of the iframe's document. 102 assert_equals(document.getAnimations().length, 0); 103 assert_equals(iframe1.contentDocument.getAnimations().length, 1); 104 anim1.finish(); 105 106 // animation of div_frame1 in iframe1 with iframe timeline 107 const effect2 = new KeyframeEffect(div_frame1, null, 100 * MS_PER_SEC); 108 const anim2 = new Animation(effect2, iframe1.contentDocument.timeline); 109 anim2.play(); 110 assert_equals(document.getAnimations().length, 0); 111 assert_equals(iframe1.contentDocument.getAnimations().length, 1); 112 anim2.finish(); 113 114 //animation of div_main_frame in main frame with iframe timeline 115 const effect3 = new KeyframeEffect(div_main_frame, null, 100 * MS_PER_SEC); 116 const anim3 = new Animation(effect3, iframe1.contentDocument.timeline); 117 anim3.play(); 118 assert_equals(document.getAnimations().length, 1); 119 assert_equals(iframe1.contentDocument.getAnimations().length, 0); 120 anim3.finish(); 121 122 //animation of div_frame1 in iframe1 with another iframe's timeline 123 const effect4 = new KeyframeEffect(div_frame1, null, 100 * MS_PER_SEC); 124 const anim4 = new Animation(effect4, iframe2.contentDocument.timeline); 125 anim4.play(); 126 assert_equals(document.getAnimations().length, 0); 127 assert_equals(iframe1.contentDocument.getAnimations().length, 1); 128 assert_equals(iframe2.contentDocument.getAnimations().length, 0); 129 anim4.finish(); 130 }, 'iframe.contentDocument.getAnimations() returns animations on elements ' 131 + 'inside same-origin Document'); 132 133 test(t => { 134 const div = createDiv(t); 135 const shadow = div.attachShadow({ mode: 'open' }); 136 137 // Create a tree with the following structure 138 // 139 // div 140 // | 141 // (ShadowRoot) 142 // / \ 143 // childA childB 144 // (*anim2) | 145 // grandChild 146 // (*anim1) 147 // 148 // This lets us test that: 149 // 150 // a) All children of the ShadowRoot are included 151 // b) Descendants of the children are included 152 // c) The result is sorted by composite order (since we fire anim1 before 153 // anim2 despite childA appearing first in tree order) 154 155 const childA = createDiv(t); 156 shadow.append(childA); 157 158 const childB = createDiv(t); 159 shadow.append(childB); 160 161 const grandChild = createDiv(t); 162 childB.append(grandChild); 163 164 const anim1 = grandChild.animate(gKeyFrames, 100 * MS_PER_SEC) 165 const anim2 = childA.animate(gKeyFrames, 100 * MS_PER_SEC) 166 167 assert_array_equals( 168 div.shadowRoot.getAnimations(), 169 [ anim1, anim2 ], 170 'getAnimations() called on ShadowRoot returns expected animations' 171 ); 172 }, 'ShadowRoot.getAnimations() return all animations in the shadow tree'); 173 174 test(t => { 175 const div = createDiv(t); 176 const shadow = div.attachShadow({ mode: 'open' }); 177 178 const child = createDiv(t); 179 shadow.append(child); 180 181 child.animate(gKeyFrames, 100 * MS_PER_SEC) 182 183 assert_array_equals( 184 document.getAnimations(), 185 [], 186 'getAnimations() called on Document does not return animations from shadow' 187 + ' trees' 188 ); 189 }, 'Document.getAnimations() does NOT return animations in shadow trees'); 190 191 test(t => { 192 const div = createDiv(t); 193 const shadow = div.attachShadow({ mode: 'open' }); 194 195 div.animate(gKeyFrames, 100 * MS_PER_SEC) 196 197 assert_array_equals( 198 div.shadowRoot.getAnimations(), 199 [], 200 'getAnimations() called on ShadowRoot does not return animations from' 201 + ' Document' 202 ); 203 }, 'ShadowRoot.getAnimations() does NOT return animations in parent document'); 204 205 promise_test(async t => { 206 const div = createDiv(t); 207 const watcher = EventWatcher(t, div, 'transitionrun'); 208 209 // Create a covering animation to prevent transitions from firing after 210 // calling getAnimations(). 211 const coveringAnimation = new Animation( 212 new KeyframeEffect(div, { opacity: [0, 1] }, 100 * MS_PER_SEC) 213 ); 214 215 // Setup transition start point. 216 div.style.transition = 'opacity 100s'; 217 getComputedStyle(div).opacity; 218 219 // Update specified style but don't flush style. 220 div.style.opacity = '0.5'; 221 222 // Fetch animations 223 document.getAnimations(); 224 225 // Play the covering animation to ensure that only the call to 226 // getAnimations() has a chance to trigger transitions. 227 coveringAnimation.play(); 228 229 // If getAnimations() flushed style, we should get a transitionrun event. 230 await watcher.wait_for('transitionrun'); 231 }, 'Document.getAnimations() triggers a style change event'); 232 233 </script> 234 </body>