Bug 1623734 [wpt PR 22343] - [scroll-timeline] Implement element-based scroll offset, a=testonly
authorMajid Valipour <majidvp@chromium.org>
Tue, 28 Apr 2020 11:34:20 +0000
changeset 527534 97cead11ec4aa6376a4172464603d64919c95a40
parent 527533 3ab9340aa94c36fdb12152f4a5398a9ace1eb4d4
child 527535 73a40ddaf64e8f662e74cdcb1417c32e9d014218
push id37368
push userbtara@mozilla.com
push dateFri, 01 May 2020 21:45:51 +0000
treeherdermozilla-central@0f9c5a59e45d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstestonly
bugs1623734, 22343, 1023375, 2100887, 759266
milestone77.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1623734 [wpt PR 22343] - [scroll-timeline] Implement element-based scroll offset, a=testonly Automatic update from web-platform-tests [scroll-timeline] Implement element-based scroll offset Implement basic element-based offset calculation taking edge and threshold into account. Test: external/wpt/scroll-animations/element-based-offset.html Bug: 1023375 Change-Id: I38caf32e775e6827a9b7d8763bb7cf9c86fc29c3 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2100887 Reviewed-by: Majid Valipour <majidvp@chromium.org> Reviewed-by: Yi Gu <yigu@chromium.org> Commit-Queue: Majid Valipour <majidvp@chromium.org> Cr-Commit-Position: refs/heads/master@{#759266} -- wpt-commits: 63695b3eadcbbcb673a88e0150bea906d6dda39a wpt-pr: 22343
testing/web-platform/tests/scroll-animations/element-based-offset.html
testing/web-platform/tests/scroll-animations/testcommon.js
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/scroll-animations/element-based-offset.html
@@ -0,0 +1,212 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test element-based scroll offset for scroll timeline.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/web-animations/testcommon.js"></script>
+<script src="testcommon.js"></script>
+
+<style>
+  .scroller {
+    overflow: auto;
+    height: 500px;
+    width: 500px;
+  }
+
+  .contents {
+    height: 2000px;
+    width: 2000px;
+    position: relative;
+  }
+
+  .vertical #start, .vertical #end {
+    background: blue;
+    border-top: 5px solid pink;
+    box-sizing: border-box;
+    width: 100%;
+    height: 50px;
+  }
+
+  .vertical #start {
+    position: absolute;
+    top: 50px;
+  }
+
+  .vertical #end {
+    position: absolute;
+    top: 1050px;
+  }
+
+  .horizontal #start, .horizontal #end {
+    background: blue;
+    border-left:5px solid pink;
+    box-sizing: border-box;
+    height: 100%;
+    width: 50px;
+  }
+
+  .horizontal #start {
+    position: absolute;
+    left: 50px;
+  }
+
+  .horizontal #end {
+    position: absolute;
+    left: 1050px;
+  }
+</style>
+<div id="log"></div>
+<script>
+  'use strict';
+
+  function createScrollerWithStartAndEnd(test, orientationClass) {
+    var scroller = createDiv(test);
+    scroller.innerHTML =
+     `<div class='contents'>
+        <div id='start'></div>
+        <div id='end'></div>
+      </div>`;
+    scroller.classList.add('scroller');
+    scroller.classList.add(orientationClass);
+
+    return scroller;
+  }
+
+  async function createScrollAnimationTest(description, config) {
+    promise_test(async t => {
+      const scroller = createScrollerWithStartAndEnd(t, config.orientation);
+      t.add_cleanup(() => scroller.remove());
+
+      const start = scroller.querySelector("#start");
+      const end = scroller.querySelector("#end")
+
+      const timeline = createScrollTimeline(t, {
+        scrollSource: scroller,
+        orientation: config.orientation,
+        timeRange: 1000,
+        fill: 'both',
+        startScrollOffset: {target: start, ...config.start},
+        endScrollOffset: {target: end, ...config.end }
+      });
+
+      const animation = createScrollLinkedAnimation(t, timeline);
+      const scrollRange = end.offsetTop - start.offsetTop;
+      const timeRange = animation.timeline.timeRange;
+
+      // Verify initial start and current times in Idle state.
+      assert_equals(animation.currentTime, null,
+        "The current time is null in Idle state.");
+      assert_equals(animation.startTime, null,
+        "The start time is null in Idle state.");
+
+      animation.play();
+      // Verify initial start and current times in Pending state.
+      assert_times_equal(animation.currentTime, 0,
+        "The current time is a hold time in Pending state.");
+      assert_equals(animation.startTime, null,
+        "The start time is null in Pending state.");
+
+      await animation.ready;
+      // Verify initial start and current times in Playing state.
+      assert_times_equal(animation.currentTime, 0,
+        "The current time is zero in Playing state.");
+      assert_times_equal(animation.startTime, 0,
+        "The start time is zero in Playing state.");
+
+      // Now do some scrolling and make sure that the Animation current time is
+      // correct.
+      if (config.orientation == 'vertical') {
+        scroller.scrollTo({top: config.scrollTo});
+        assert_equals(scroller.scrollTop, config.scrollTo);
+      } else {
+        scroller.scrollTo({left: config.scrollTo});
+        assert_equals(scroller.scrollLeft, config.scrollTo);
+      }
+
+      await waitForNextFrame();
+      assert_times_equal(animation.timeline.currentTime, config.expectedCurrentTime,
+        "The timeline current time corresponds to the scroll position of the scroller.");
+      assert_times_equal(animation.currentTime, config.expectedCurrentTime,
+        "The animation current time corresponds to the scroll position of the scroller.");
+      assert_times_equal(
+        animation.effect.getComputedTiming().localTime,
+        config.expectedCurrentTime,
+        'Effect local time corresponds to the scroll position of the scroller.');
+    }, description);
+  }
+
+  // start is @   50px
+  // end is   @   1050px
+  // both have    50px heights
+  // scroller has 500px heights
+  // For each test the expected start/end is in the comment to help with the
+  // verification.
+  const tests = {
+    // offsets: [100, 1100]
+    "at start": {
+      scrollTo: 100,
+      expectedCurrentTime: 0,
+    },
+    // offsets: [100, 1100]
+    "after start": {
+      scrollTo: 200,
+      expectedCurrentTime: 100,
+    },
+    // offsets: [100, 1100]
+    "at middle" : {
+      scrollTo: 600,
+      expectedCurrentTime: 500,
+    },
+    // offsets: [100, 1100]
+    "at end" : {
+      scrollTo: 1099,
+      expectedCurrentTime: 999,
+    },
+    // offsets: [100, 1100]
+    "after end" : {
+      scrollTo: 1150,
+      expectedCurrentTime: 1000,
+    },
+    // offsets: [75, 1075]
+    "with threshold 0.5" : {
+      // give threshold to both start and end to keep scrollRange
+      // 1000 which simplifies the calculation.
+      start: {threshold: 0.5},
+      end: {threshold: 0.5},
+      scrollTo: 600 - 25,
+      expectedCurrentTime: 500,
+    },
+    // offsets: [50, 1050]
+    "with threshold 1.0": {
+      start: {threshold: 1.0},
+      end: {threshold: 1.0},
+      scrollTo: 600 - 50,
+      expectedCurrentTime: 500,
+    },
+    // offset: [100, 550]
+    "with end edge" : {
+      end: {edge: "end"},
+      scrollTo: 325,
+      expectedCurrentTime: 500,
+    },
+    // offset: [100, 600]
+     "with end edge and threshold 1.0": {
+      end: {
+        threshold: 1.0,
+        edge: "end"
+      },
+      scrollTo: 350,
+      expectedCurrentTime: 500,
+    },
+  };
+
+  for (let orientation of ['vertical', 'horizontal']) {
+    for (let testName in tests) {
+      const description = `Animation start and current times are correct given
+          element-based offsets for orienation ${orientation} and ${testName}.`;
+      const config = tests[testName];
+      config.orientation = orientation;
+      createScrollAnimationTest(description, config);
+    }
+  }
+</script>
\ No newline at end of file
--- a/testing/web-platform/tests/scroll-animations/testcommon.js
+++ b/testing/web-platform/tests/scroll-animations/testcommon.js
@@ -1,32 +1,33 @@
 function createScroller(test) {
   var scroller = createDiv(test);
   scroller.innerHTML = "<div class='contents'></div>";
   scroller.classList.add('scroller');
   return scroller;
 }
 
-function createScrollTimeline(test) {
-  return new ScrollTimeline({
+function createScrollTimeline(test, options) {
+  options = options || {
     scrollSource: createScroller(test),
     timeRange: 1000
-  });
+  }
+  return new ScrollTimeline(options);
 }
 
 function createScrollTimelineWithOffsets(test, startOffset, endOffset) {
-  return new ScrollTimeline({
+  return createScrollTimeline(test, {
     scrollSource: createScroller(test),
     orientation: "vertical",
     startScrollOffset: startOffset,
     endScrollOffset: endOffset,
     timeRange: 1000
   });
 }
 
 function createScrollLinkedAnimation(test, timeline) {
-  if(timeline === undefined)
+  if (timeline === undefined)
     timeline = createScrollTimeline(test);
   const DURATION = 1000; // ms
   const KEYFRAMES = { opacity: [1, 0] };
   return new Animation(
     new KeyframeEffect(createDiv(test), KEYFRAMES, DURATION), timeline);
 }