browser_animation_pseudo-element.js (9599B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 // Test for pseudo element. 7 8 const TEST_DATA = [ 9 { 10 expectedTargetLabel: "::before", 11 expectedAnimationNameLabel: "body", 12 expectedKeyframsGraphPathSegments: [ 13 { x: 0, y: 0 }, 14 { x: 1000, y: 100 }, 15 ], 16 }, 17 { 18 expectedTargetLabel: "::before", 19 expectedAnimationNameLabel: "div-before", 20 expectedKeyframsGraphPathSegments: [ 21 { x: 0, y: 100 }, 22 { x: 1000, y: 0 }, 23 ], 24 }, 25 { 26 expectedTargetLabel: "::after", 27 expectedAnimationNameLabel: "div-after", 28 }, 29 { 30 expectedTargetLabel: "::backdrop", 31 expectedAnimationNameLabel: "dialog-backdrop", 32 }, 33 { 34 expectedTargetLabel: "::marker", 35 expectedAnimationNameLabel: "div-marker", 36 }, 37 { 38 expectedTargetLabel: "::view-transition-group(root)", 39 expectedAnimationNameLabel: "-ua-view-transition-group-anim-root", 40 }, 41 { 42 expectedTargetLabel: "::view-transition-group(my-vt)", 43 expectedAnimationNameLabel: "my-vt-animation", 44 }, 45 { 46 expectedTargetLabel: "::view-transition-old(root)", 47 expectedAnimationNameLabel: "-ua-mix-blend-mode-plus-lighter", 48 }, 49 { 50 expectedTargetLabel: "::view-transition-old(root)", 51 expectedAnimationNameLabel: "-ua-view-transition-fade-out", 52 }, 53 { 54 expectedTargetLabel: "::view-transition-new(root)", 55 expectedAnimationNameLabel: "-ua-mix-blend-mode-plus-lighter", 56 }, 57 { 58 expectedTargetLabel: "::view-transition-new(root)", 59 expectedAnimationNameLabel: "-ua-view-transition-fade-in", 60 }, 61 { 62 expectedTargetLabel: "::view-transition-old(my-vt)", 63 expectedAnimationNameLabel: "-ua-mix-blend-mode-plus-lighter", 64 }, 65 { 66 expectedTargetLabel: "::view-transition-old(my-vt)", 67 expectedAnimationNameLabel: "-ua-view-transition-fade-out", 68 }, 69 { 70 expectedTargetLabel: "::view-transition-new(my-vt)", 71 expectedAnimationNameLabel: "-ua-mix-blend-mode-plus-lighter", 72 }, 73 { 74 expectedTargetLabel: "::view-transition-new(my-vt)", 75 expectedAnimationNameLabel: "-ua-view-transition-fade-in", 76 }, 77 ]; 78 79 add_task(async function () { 80 await addTab(URL_ROOT + "doc_pseudo.html"); 81 82 const { animationInspector, inspector, panel } = 83 await openAnimationInspector(); 84 85 // Select the html node so we can see ::view-transition animations 86 await selectNode("html", inspector); 87 88 await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async () => { 89 const document = content.document; 90 const transition = document.startViewTransition(() => { 91 document.querySelector(".div-view-transition").append("world"); 92 }); 93 await transition.ready; 94 await transition.updateCallbackDone; 95 }); 96 97 info("Waiting for expected animations to be displayed"); 98 try { 99 await waitFor( 100 () => 101 panel.querySelectorAll(".animation-list .animation-item").length === 102 TEST_DATA.length 103 ); 104 ok( 105 true, 106 `Got expectedCount of animation item should be ${TEST_DATA.length}` 107 ); 108 } catch (e) { 109 ok( 110 false, 111 `Didn't get expected number of animations. Got ${panel.querySelectorAll(".animation-list .animation-item").length} expected ${TEST_DATA.length}` 112 ); 113 } 114 115 info("Checking content of each animation item"); 116 for (let i = 0; i < TEST_DATA.length; i++) { 117 await checkAnimationItemAtIndex(panel, i, TEST_DATA[i]); 118 } 119 120 info( 121 "Checking whether node is selected correctly " + 122 "when click on the first inspector icon on Reps component" 123 ); 124 let onDetailRendered = animationInspector.once( 125 "animation-keyframes-rendered" 126 ); 127 await clickOnTargetNode(animationInspector, panel, 0); 128 await onDetailRendered; 129 assertAnimationCount(panel, 1); 130 assertAnimationNameLabel(panel, TEST_DATA[0].expectedAnimationNameLabel); 131 assertKeyframesGraphPathSegments( 132 panel, 133 TEST_DATA[0].expectedKeyframsGraphPathSegments 134 ); 135 136 // Select `body` only so we avoid having all the view transition items 137 info("Select <body> to reset the animation list"); 138 await selectNode("body", inspector); 139 140 info( 141 "Checking whether node is selected correctly " + 142 "when click on the second inspector icon on Reps component" 143 ); 144 onDetailRendered = animationInspector.once("animation-keyframes-rendered"); 145 await clickOnTargetNode(animationInspector, panel, 1); 146 await onDetailRendered; 147 assertAnimationCount(panel, 1); 148 assertAnimationNameLabel(panel, TEST_DATA[1].expectedAnimationNameLabel); 149 assertKeyframesGraphPathSegments( 150 panel, 151 TEST_DATA[1].expectedKeyframsGraphPathSegments 152 ); 153 154 info( 155 "Check that view-transition node can be selected from the animation panel" 156 ); 157 info("Select <html> to reset the animation list"); 158 await selectNode("html", inspector); 159 // wait for all the animations to be displayed again 160 await waitFor( 161 () => 162 panel.querySelectorAll(".animation-list .animation-item").length === 163 TEST_DATA.length 164 ); 165 166 onDetailRendered = animationInspector.once("animation-keyframes-rendered"); 167 await clickOnTargetNodeByTargetText( 168 animationInspector, 169 panel, 170 "::view-transition-group(my-vt)" 171 ); 172 173 // we get all the view transition animations, even those on elements who are not children 174 // of the currently selected node 175 const expectedTargets = [ 176 "::view-transition-group(my-vt)", 177 "::view-transition-group(root)", 178 "::view-transition-old(my-vt)", 179 "::view-transition-old(my-vt)", 180 "::view-transition-old(root)", 181 "::view-transition-old(root)", 182 "::view-transition-new(my-vt)", 183 "::view-transition-new(my-vt)", 184 "::view-transition-new(root)", 185 "::view-transition-new(root)", 186 ]; 187 await waitFor(() => 188 [ 189 ...panel.querySelectorAll( 190 ".animation-list .animation-item .animation-target .attrName" 191 ), 192 ] 193 .map(attrNameEl => attrNameEl.textContent) 194 .every((targetElText, index) => targetElText === expectedTargets[index]) 195 ); 196 197 is( 198 inspector.selection.nodeFront.displayName, 199 "::view-transition-group(my-vt)", 200 "Expected view transition pseudo element node was selected" 201 ); 202 203 info("Select <html> to reset the animation list"); 204 await selectNode("html", inspector); 205 // wait for all the animations to be displayed again 206 await waitFor( 207 () => 208 panel.querySelectorAll(".animation-list .animation-item").length === 209 TEST_DATA.length 210 ); 211 212 info( 213 "Stop the view transition and check that related animations are removed" 214 ); 215 const TEST_DATA_WITHOUT_VIEW_TRANSITION = TEST_DATA.filter( 216 ({ expectedTargetLabel }) => 217 !expectedTargetLabel.startsWith("::view-transition") 218 ); 219 220 await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async () => { 221 content.document.activeViewTransition.skipTransition(); 222 }); 223 224 await waitFor( 225 () => 226 panel.querySelectorAll(".animation-list .animation-item").length === 227 TEST_DATA_WITHOUT_VIEW_TRANSITION.length 228 ); 229 ok( 230 true, 231 `Got expectedCount of animation item after stopping the view transition` 232 ); 233 234 info("Reload the page"); 235 await reloadBrowser(); 236 237 info("Waiting for expected animations to be displayed"); 238 // No need to check for view transition this time, we want to assert that we do get 239 // animations for pseudo element after reloading (assert fix for Bug 2001126) 240 await waitFor( 241 () => 242 panel.querySelectorAll(".animation-list .animation-item").length === 243 TEST_DATA_WITHOUT_VIEW_TRANSITION.length 244 ); 245 ok( 246 true, 247 `Got expectedCount of animation item should be ${TEST_DATA_WITHOUT_VIEW_TRANSITION.length} after reloading` 248 ); 249 250 info("Checking content of each animation item after reload"); 251 for (let i = 0; i < TEST_DATA_WITHOUT_VIEW_TRANSITION.length; i++) { 252 await checkAnimationItemAtIndex( 253 panel, 254 i, 255 TEST_DATA_WITHOUT_VIEW_TRANSITION[i] 256 ); 257 } 258 }); 259 260 async function checkAnimationItemAtIndex(panel, index, testData) { 261 info(`Checking pseudo element for animation at index #${index}`); 262 const animationItemEl = await findAnimationItemByIndex(panel, index); 263 264 if (!animationItemEl) { 265 ok(false, `Didn't find an animation at index #${index}`); 266 return; 267 } 268 269 info("Checking text content of animation target"); 270 const animationTargetEl = animationItemEl.querySelector( 271 ".animation-list .animation-item .animation-target" 272 ); 273 is( 274 animationTargetEl.textContent, 275 testData.expectedTargetLabel, 276 `Got expected target for animation at index #${index}` 277 ); 278 279 info("Checking text content of animation name"); 280 const animationNameEl = animationItemEl.querySelector(".animation-name"); 281 is( 282 animationNameEl.textContent, 283 testData.expectedAnimationNameLabel, 284 `Got expected animation name for animation at index #${index}` 285 ); 286 } 287 288 function assertAnimationCount(panel, expectedCount) { 289 info("Checking count of animation item"); 290 is( 291 panel.querySelectorAll(".animation-list .animation-item").length, 292 expectedCount, 293 `Count of animation item should be ${expectedCount}` 294 ); 295 } 296 297 function assertAnimationNameLabel(panel, expectedAnimationNameLabel) { 298 info("Checking the animation name label"); 299 is( 300 panel.querySelector(".animation-list .animation-item .animation-name") 301 .textContent, 302 expectedAnimationNameLabel, 303 `The animation name should be ${expectedAnimationNameLabel}` 304 ); 305 } 306 307 function assertKeyframesGraphPathSegments(panel, expectedPathSegments) { 308 info("Checking the keyframes graph path segments"); 309 const pathEl = panel.querySelector(".keyframes-graph-path path"); 310 assertPathSegments(pathEl, true, expectedPathSegments); 311 }