tor-browser

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

support.js (4224B)


      1 // Assert that the user agent under test supports AnimationTrigger.
      2 // AnimationTrigger tests should do this sanity check before proceeding.
      3 function assertAnimationTriggerSupport() {
      4  assert_true(document.documentElement.style.animationTrigger !== undefined);
      5 }
      6 
      7 const setScrollTop = (scroller, y) => {
      8  const scrollend_promise =
      9    waitForScrollEndFallbackToDelayWithoutScrollEvent(scroller);
     10  scroller.scrollTop = y;
     11  return scrollend_promise;
     12 }
     13 
     14 function getRangeBoundariesForTest(trigger_start, trigger_end,
     15                                   exit_start, exit_end, scroller) {
     16  let rangeBoundaries = {
     17    scroller: scroller,
     18    offsetWithinTriggerRange: (trigger_start + trigger_end) / 2,
     19    offsetAboveTriggerRange: trigger_start - 10,
     20    offsetBelowTriggerRange: trigger_end + 10,
     21    offsetAboveExitRange: exit_start - 10,
     22    offsetBelowExitRange: exit_end + 10,
     23  };
     24 
     25  rangeBoundaries.enterTriggerRange = async () => {
     26    return setScrollTop(rangeBoundaries.scroller,
     27                        rangeBoundaries.offsetWithinTriggerRange);
     28  };
     29  rangeBoundaries.exitTriggerRangeAbove = async () => {
     30    return setScrollTop(rangeBoundaries.scroller,
     31                        rangeBoundaries.offsetAboveTriggerRange);
     32  };
     33  rangeBoundaries.exitTriggerRangeBelow = async () => {
     34    return setScrollTop(rangeBoundaries.scroller,
     35                        rangeBoundaries.offsetBelowTriggerRange);
     36  };
     37  rangeBoundaries.exitExitRangeAbove = async () => {
     38    return setScrollTop(rangeBoundaries.scroller,
     39                        rangeBoundaries.offsetAboveExitRange);
     40  };
     41  rangeBoundaries.exitExitRangeBelow = async () => {
     42    return setScrollTop(rangeBoundaries.scroller,
     43                        rangeBoundaries.offsetBelowExitRange);
     44  };
     45 
     46  return rangeBoundaries;
     47 }
     48 
     49 // Helper function for animation-trigger tests. Aims to perform a scroll and
     50 // observe the animation events indicated by |events_of_interest| and
     51 // |events_should_fire|
     52 async function testAnimationTrigger(test, scroll_fn, target,
     53                                    events_of_interest,  events_should_fire) {
     54  assertAnimationTriggerSupport();
     55 
     56  let evt_promises = [];
     57  for (let idx = 0; idx < events_of_interest.length; idx++) {
     58    const evt = events_of_interest[idx];
     59    const animationevent_promise = new Promise((resolve) => {
     60      const watcher_func = () => {
     61        if (!events_should_fire[idx]) {
     62          test.unreached_func(`received unexpected event: ${evt}.`)();
     63        }
     64        resolve();
     65      }
     66 
     67      target.addEventListener(evt, watcher_func,
     68        { once: true });
     69 
     70      // If we are not expecting the event, just wait for 3 frames before
     71      // continuing the test.
     72      if (!events_should_fire[idx]) {
     73        waitForAnimationFrames(3).then(() => {
     74          target.removeEventListener(evt, watcher_func);
     75          resolve();
     76        });
     77      }
     78    });
     79 
     80    evt_promises.push(animationevent_promise);
     81  }
     82 
     83  await scroll_fn();
     84  await Promise.all(evt_promises);
     85 }
     86 
     87 function computeContainOffset(scroller, subject, pct) {
     88  const contain_start = subject.offsetTop + subject.offsetHeight
     89    - scroller.offsetTop - scroller.clientHeight;
     90  const contain_end = subject.offsetTop - scroller.offsetTop;
     91 
     92  return contain_start + (pct / 100) * (contain_end - contain_start);
     93 }
     94 
     95 function setupAnimationAndTrigger(target, subject, duration) {
     96  const animation = new Animation(
     97    new KeyframeEffect(
     98      target,
     99      [
    100        { transform: "scale(1)", backgroundColor: "yellow" },
    101        { transform: "scale(2)", backgroundColor: "yellow" },
    102      ],
    103      { duration: duration, fill: "both" }
    104    ));
    105 
    106  let trigger = new TimelineTrigger({
    107    timeline: new ViewTimeline({ subject: subject, axis: "y" }),
    108    rangeStart: "contain 0%",
    109    rangeEnd: "contain 100%"
    110  });
    111 
    112  trigger.addAnimation(animation, "play-forwards", "play-backwards");
    113 }
    114 
    115 async function waitForAnimation(targetCurrentTime, animation) {
    116  return new Promise(resolve => {
    117    function waitForCurrentTime() {
    118      if ((targetCurrentTime - animation.currentTime) * animation.playbackRate <= 0) {
    119        resolve();
    120        return;
    121      }
    122 
    123      requestAnimationFrame(waitForCurrentTime);
    124    }
    125    waitForCurrentTime();
    126  });
    127 }