tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }