Test for scrollend for mandatory snap point after load

Bug: 1400689
Change-Id: Ie56ff2a95e79d95e4742460732a1e016973d5db9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4178531
Reviewed-by: Kevin Ellis <kevers@chromium.org>
Commit-Queue: Mehdi Kazemi <mehdika@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1094085}
diff --git a/dom/events/scrolling/scroll_support.js b/dom/events/scrolling/scroll_support.js
index 169393e..847a989 100644
--- a/dom/events/scrolling/scroll_support.js
+++ b/dom/events/scrolling/scroll_support.js
@@ -10,6 +10,20 @@
   });
 }
 
+async function verifyScrollStopped(test, target_div) {
+  const unscaled_pause_time_in_ms = 100;
+  const x = target_div.scrollLeft;
+  const y = target_div.scrollTop;
+  return new Promise(resolve => {
+    test.step_timeout(() => {
+      assert_equals(x, target_div.scrollLeft);
+      assert_equals(y, target_div.scrollTop);
+      resolve();
+    }, unscaled_pause_time_in_ms);
+  });
+}
+
+
 const MAX_FRAME = 700;
 const MAX_UNCHANGED_FRAMES = 20;
 
@@ -44,6 +58,19 @@
     });
   });
 }
+function waitForNextFrame() {
+  const startTime = performance.now();
+  return new Promise(resolve => {
+    window.requestAnimationFrame((frameTime) => {
+      if (frameTime < startTime) {
+        window.requestAnimationFrame(resolve);
+      } else {
+        resolve();
+      }
+    });
+  });
+}
+
 
 // TODO(crbug.com/1400399): Deprecate as frame rates may vary greatly in
 // different test environments.
diff --git a/dom/events/scrolling/scrollend-event-fired-for-mandatory-snap-point-after-load.html b/dom/events/scrolling/scrollend-event-fired-for-mandatory-snap-point-after-load.html
new file mode 100644
index 0000000..a51069b
--- /dev/null
+++ b/dom/events/scrolling/scrollend-event-fired-for-mandatory-snap-point-after-load.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <meta name="viewport" content="width=device-width">
+  <script src="/resources/testharness.js"></script>
+  <script src="/resources/testharnessreport.js"></script>
+  <script src="/resources/testdriver.js"></script>
+  <script src="/resources/testdriver-actions.js"></script>
+  <script src="/resources/testdriver-vendor.js"></script>
+  <script src="scroll_support.js"></script>
+  <title>scrollend + mandatory scroll snap test</title>
+
+  <style>
+    #root {
+      width: 400px;
+      height: 400px;
+      overflow: auto;
+      scroll-snap-type: y mandatory;
+      border: 1px solid black;
+      --page-height: 400px;
+    }
+
+    #scroller {
+      height: 200px;
+      width: 200px;
+      overflow: auto;
+      border: 1px solid black;
+      --page-height: 200px;
+    }
+
+    .page {
+      height: var(--page-height);
+      scroll-snap-align: start;
+    }
+
+    .hidden {
+      display: none;
+    }
+  </style>
+</head>
+
+<body onload="runTests()">
+<div id="root" class="hidden">
+  <h1>scrollend + mandatory scroll snap test</h1>
+  <div id="scroller">
+    <div class="page">
+      <p>Page 1</p>
+    </div>
+    <div class="page">
+      <p>Page 2</p>
+    </div>
+    <div class="page">
+      <p>Page 3</p>
+    </div>
+  </div>
+
+  <div class="page">
+    <p>Page A</p>
+  </div>
+  <div class="page">
+    <p>Page B</p>
+  </div>
+  <div class="page">
+    <p>Page C</p>
+  </div>
+</div>
+
+<script>
+  function runTests() {
+    const root_div = document.getElementById("root");
+
+    async function createScrollendPromise(test) {
+      return waitForScrollendEvent(test, root_div).then(evt => {
+        assert_false(evt.cancelable, 'Event is not cancelable');
+        assert_false(evt.bubbles, 'Event targeting element does not bubble');
+      });
+    }
+
+    promise_test(async (t) => {
+      const targetScrollendPromise = createScrollendPromise(t);
+
+      await waitForNextFrame();
+      root_div.classList.remove("hidden");
+      await waitForNextFrame();
+
+      await targetScrollendPromise;
+      await verifyScrollStopped(t, root_div);
+    }, "scrollend event fired after load for mandatory snap point");
+  }
+</script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/dom/events/scrolling/scrollend-event-for-user-scroll.html b/dom/events/scrolling/scrollend-event-for-user-scroll.html
index 5146c5f..e9be7c9 100644
--- a/dom/events/scrolling/scrollend-event-for-user-scroll.html
+++ b/dom/events/scrolling/scrollend-event-for-user-scroll.html
@@ -39,19 +39,6 @@
   }
 }
 
-async function verifyScrollStopped(test) {
-  const unscaled_pause_time_in_ms = 100;
-  const x = target_div.scrollLeft;
-  const y = target_div.scrollTop;
-  return new Promise(resolve => {
-    test.step_timeout(() => {
-      assert_equals(x, target_div.scrollLeft);
-      assert_equals(y, target_div.scrollTop);
-      resolve();
-    }, unscaled_pause_time_in_ms);
-  });
-}
-
 async function verifyNoScrollendOnDocument(test) {
   const callback =
       test.unreached_func("window got unexpected scrollend event.");
@@ -94,7 +81,7 @@
     await targetScrollendPromise;
 
     assert_true(target_div.scrollTop > 0);
-    await verifyScrollStopped(t);
+    await verifyScrollStopped(t, target_div);
   }, 'Tests that the target_div gets scrollend event when touch dragging.');
 
   promise_test(async (t) => {
@@ -123,7 +110,7 @@
 
     await targetScrollendPromise;
     assert_true(target_div.scrollTop > 0);
-    await verifyScrollStopped(t);
+    await verifyScrollStopped(t, target_div);
   }, 'Tests that the target_div gets scrollend event when clicking ' +
      'scrollbar.');
 
@@ -154,7 +141,7 @@
 
     await targetScrollendPromise;
     assert_true(target_div.scrollTop > 0);
-    await verifyScrollStopped(t);
+    await verifyScrollStopped(t, target_div);
   }, 'Tests that the target_div gets scrollend event when dragging the ' +
       'scrollbar thumb.');
 
@@ -174,7 +161,7 @@
 
     await targetScrollendPromise;
     assert_true(target_div.scrollTop > 0);
-    await verifyScrollStopped(t);
+    await verifyScrollStopped(t, target_div);
   }, 'Tests that the target_div gets scrollend event when mouse wheel ' +
      'scrolling.');
 
@@ -190,7 +177,7 @@
 
     await targetScrollendPromise;
     assert_true(target_div.scrollTop > 0);
-    await verifyScrollStopped(t);
+    await verifyScrollStopped(t, target_div);
   }, 'Tests that the target_div gets scrollend event when sending DOWN key ' +
      'to the target.');
 }