Import WPT tests for scrollend and overscroll events
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 30 Oct 2019 07:58:26 +0000 (07:58 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 30 Oct 2019 07:58:26 +0000 (07:58 +0000)
https://bugs.webkit.org/show_bug.cgi?id=203500

Patch by Frederic Wang <fwang@igalia.com> on 2019-10-30
Reviewed by Simon Fraser.

LayoutTests/imported/w3c:

* web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-document-expected.txt: Added.
* web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-element-with-overscroll-behavior-expected.txt: Added.
* web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-scrolled-element-expected.txt: Added.
* web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-window-expected.txt: Added.
* web-platform-tests/dom/events/scrolling/scrollend-event-fired-after-snap-expected.txt: Added.
* web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-document-expected.txt: Added.
* web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-element-with-overscroll-behavior-expected.txt: Added.
* web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-scrolled-element-expected.txt: Added.
* web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-window-expected.txt: Added.

LayoutTests:

* TestExpectations: Skip the tests on most platforms, since
sendEventStream is not supported.
* platform/ios/TestExpectations: Enable the tests on iOS.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@251770 268f45cc-cd09-0410-ab3c-d52691b4dbfc

25 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/resources/import-expectations.json
LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-document-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-document.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-element-with-overscroll-behavior-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-element-with-overscroll-behavior.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-scrolled-element-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-scrolled-element.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-window-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-window.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scroll_support.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-after-snap-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-after-snap.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-document-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-document.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-element-with-overscroll-behavior-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-element-with-overscroll-behavior.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-scrolled-element-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-scrolled-element.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-window-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-window.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/w3c-import.log [new file with mode: 0644]
LayoutTests/platform/ios/TestExpectations

index 25dc6e5..9e8ff51 100644 (file)
@@ -1,3 +1,14 @@
+2019-10-30  Frederic Wang  <fwang@igalia.com>
+
+        Import WPT tests for scrollend and overscroll events
+        https://bugs.webkit.org/show_bug.cgi?id=203500
+
+        Reviewed by Simon Fraser.
+
+        * TestExpectations: Skip the tests on most platforms, since
+        sendEventStream is not supported.
+        * platform/ios/TestExpectations: Enable the tests on iOS.
+
 2019-10-29  Said Abou-Hallawa  <sabouhallawa@apple.com>
 
         [SVG2] SVGSymbolElement should inherits SVGGraphicsElement
index cd85406..4a02fb9 100644 (file)
@@ -152,6 +152,9 @@ fast/forms/call-text-did-change-in-text-field-when-typing.html [ Skip ]
 # Only Mac and iOS have an implementation of UIScriptController::doAsyncTask().
 fast/harness/uiscriptcontroller [ Skip ]
 
+# Only iOS has an implementation of UIScriptController::sendEventStream().
+imported/w3c/web-platform-tests/dom/events/scrolling [ Skip ]
+
 # This test only makes sense on Mac
 fast/attachment/attachment-subtitle-resize.html [ Skip ]
 
index 0ebcf57..5b328c5 100644 (file)
@@ -1,3 +1,20 @@
+2019-10-30  Frederic Wang  <fwang@igalia.com>
+
+        Import WPT tests for scrollend and overscroll events
+        https://bugs.webkit.org/show_bug.cgi?id=203500
+
+        Reviewed by Simon Fraser.
+
+        * web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-document-expected.txt: Added.
+        * web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-element-with-overscroll-behavior-expected.txt: Added.
+        * web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-scrolled-element-expected.txt: Added.
+        * web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-window-expected.txt: Added.
+        * web-platform-tests/dom/events/scrolling/scrollend-event-fired-after-snap-expected.txt: Added.
+        * web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-document-expected.txt: Added.
+        * web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-element-with-overscroll-behavior-expected.txt: Added.
+        * web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-scrolled-element-expected.txt: Added.
+        * web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-window-expected.txt: Added.
+
 2019-10-29  Said Abou-Hallawa  <sabouhallawa@apple.com>
 
         [SVG2] SVGSymbolElement should inherits SVGGraphicsElement
index 510fa1d..a210a77 100644 (file)
     "web-platform-tests/custom-elements/v0": "skip", 
     "web-platform-tests/dom": "import", 
     "web-platform-tests/dom/events": "import", 
-    "web-platform-tests/dom/events/scrolling": "skip", 
+    "web-platform-tests/dom/events/scrolling": "import", 
     "web-platform-tests/dom/nodes/Document-createElement-namespace-tests/empty.html": "skip", 
     "web-platform-tests/dom/nodes/Document-createElement-namespace-tests/empty.svg": "skip", 
     "web-platform-tests/dom/nodes/Document-createElement-namespace-tests/empty.xhtml": "skip", 
diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-document-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-document-expected.txt
new file mode 100644 (file)
index 0000000..d7c1b3e
--- /dev/null
@@ -0,0 +1,3 @@
+
+FAIL Tests that the document gets overscroll event when no element scrolls after touch scrolling. promise_test: Unhandled rejection with value: "Document did not receive overscroll event after scroll up on target."
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-document.html b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-document.html
new file mode 100644 (file)
index 0000000..c054ffc
--- /dev/null
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML>
+<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>
+<style>
+#targetDiv {
+  width: 200px;
+  height: 200px;
+  overflow: scroll;
+}
+
+#innerDiv {
+  width: 400px;
+  height: 400px;
+}
+</style>
+
+<body style="margin:0" onload=runTest()>
+<div id="targetDiv">
+  <div id="innerDiv">
+  </div>
+</div>
+</body>
+
+<script>
+var target_div = document.getElementById('targetDiv');
+var overscrolled_x_delta = 0;
+var overscrolled_y_delta = 0;
+function onOverscroll(event) {
+  assert_false(event.cancelable);
+  // overscroll events are bubbled when the target node is document.
+  assert_true(event.bubbles);
+  overscrolled_x_delta = event.deltaX;
+  overscrolled_y_delta = event.deltaY;
+}
+document.addEventListener("overscroll", onOverscroll);
+
+function runTest() {
+  promise_test (async (t) => {
+    // Make sure that no overscroll event is sent to target_div.
+    target_div.addEventListener("overscroll",
+        t.unreached_func("target_div got unexpected overscroll event."));
+    await waitForCompositorCommit();
+
+    // Scroll up on target div and wait for the doc to get overscroll event.
+    await touchScrollInTarget(300, target_div, 'up');
+    await waitFor(() => { return overscrolled_y_delta < 0; },
+        'Document did not receive overscroll event after scroll up on target.');
+    assert_equals(target_div.scrollTop, 0);
+
+    // Scroll left on target div and wait for the doc to get overscroll event.
+    await touchScrollInTarget(300, target_div, 'left');
+    await waitFor(() => { return overscrolled_x_delta < 0; },
+        'Document did not receive overscroll event after scroll left on target.');
+    assert_equals(target_div.scrollLeft, 0);
+  }, 'Tests that the document gets overscroll event when no element scrolls ' +
+      'after touch scrolling.');
+}
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-element-with-overscroll-behavior-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-element-with-overscroll-behavior-expected.txt
new file mode 100644 (file)
index 0000000..9647601
--- /dev/null
@@ -0,0 +1,3 @@
+
+FAIL Tests that the last element in the cut scroll chain gets overscroll event when no element scrolls by touch. promise_test: Unhandled rejection with value: "Expected element did not receive overscroll event after scroll up on target."
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-element-with-overscroll-behavior.html b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-element-with-overscroll-behavior.html
new file mode 100644 (file)
index 0000000..750080e
--- /dev/null
@@ -0,0 +1,92 @@
+<!DOCTYPE HTML>
+<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>
+<style>
+#overscrollXDiv {
+  width: 600px;
+  height: 600px;
+  overflow: scroll;
+  overscroll-behavior-x: contain;
+}
+#overscrollYDiv {
+  width: 500px;
+  height: 500px;
+  overflow: scroll;
+  overscroll-behavior-y: none;
+}
+#targetDiv {
+  width: 400px;
+  height: 400px;
+  overflow: scroll;
+}
+.content {
+  width:800px;
+  height:800px;
+}
+</style>
+
+<body style="margin:0" onload=runTest()>
+<div id="overscrollXDiv">
+  <div class=content>
+    <div id="overscrollYDiv">
+      <div class=content>
+        <div id="targetDiv">
+          <div class="content">
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+</body>
+
+<script>
+var target_div = document.getElementById('targetDiv');
+var overscrolled_x_delta = 0;
+var overscrolled_y_delta = 0;
+function onOverscrollX(event) {
+  assert_false(event.cancelable);
+  assert_false(event.bubbles);
+  overscrolled_x_delta = event.deltaX;
+}
+function onOverscrollY(event) {
+  assert_false(event.cancelable);
+  assert_false(event.bubbles);
+  overscrolled_y_delta = event.deltaY;
+}
+// Test that both "onoverscroll" and addEventListener("overscroll"... work.
+document.getElementById('overscrollXDiv').onoverscroll = onOverscrollX;
+document.getElementById('overscrollYDiv').
+    addEventListener("overscroll", onOverscrollY);
+
+function runTest() {
+  promise_test (async (t) => {
+    // Make sure that no overscroll event is sent to document or target_div.
+    document.addEventListener("overscroll",
+        t.unreached_func("Document got unexpected overscroll event."));
+    target_div.addEventListener("overscroll",
+        t.unreached_func("target_div got unexpected overscroll event."));
+    await waitForCompositorCommit();
+    // Scroll up on target div and wait for the element with overscroll-y to get
+    // overscroll event.
+    await touchScrollInTarget(300, target_div, 'up');
+    await waitFor(() => { return overscrolled_y_delta < 0; },
+        'Expected element did not receive overscroll event after scroll up on ' +
+        'target.');
+    assert_equals(target_div.scrollTop, 0);
+
+    // Scroll left on target div and wait for the element with overscroll-x to
+    // get overscroll event.
+    await touchScrollInTarget(300, target_div, 'left');
+    await waitFor(() => { return overscrolled_x_delta < 0; },
+        'Expected element did not receive overscroll event after scroll left ' +
+        'on target.');
+    assert_equals(target_div.scrollLeft, 0);
+  }, 'Tests that the last element in the cut scroll chain gets overscroll ' +
+     'event when no element scrolls by touch.');
+}
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-scrolled-element-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-scrolled-element-expected.txt
new file mode 100644 (file)
index 0000000..0015178
--- /dev/null
@@ -0,0 +1,3 @@
+
+FAIL Tests that the scrolled element gets overscroll event after fully scrolling by touch. promise_test: Unhandled rejection with value: "Scroller did not receive overscroll event after horizontal scroll."
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-scrolled-element.html b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-scrolled-element.html
new file mode 100644 (file)
index 0000000..cfc782a
--- /dev/null
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML>
+<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>
+<style>
+#scrollableDiv {
+  width: 200px;
+  height: 200px;
+  overflow: scroll;
+}
+
+#innerDiv {
+  width: 400px;
+  height: 400px;
+}
+</style>
+
+<body style="margin:0" onload=runTest()>
+<div id="scrollableDiv">
+  <div id="innerDiv">
+  </div>
+</div>
+</body>
+
+<script>
+var scrolling_div = document.getElementById('scrollableDiv');
+var overscrolled_x_delta = 0;
+var overscrolled_y_delta = 0;
+function onOverscroll(event) {
+  assert_false(event.cancelable);
+  assert_false(event.bubbles);
+  overscrolled_x_delta = event.deltaX;
+  overscrolled_y_delta = event.deltaY;
+}
+scrolling_div.addEventListener("overscroll", onOverscroll);
+
+function runTest() {
+  promise_test (async (t) => {
+    // Make sure that no overscroll event is sent to document.
+    document.addEventListener("overscroll",
+        t.unreached_func("Document got unexpected overscroll event."));
+    await waitForCompositorCommit();
+
+    // Do a horizontal scroll and wait for overscroll event.
+    await touchScrollInTarget(300, scrolling_div , 'right');
+    await waitFor(() => { return overscrolled_x_delta > 0; },
+        'Scroller did not receive overscroll event after horizontal scroll.');
+    assert_equals(scrolling_div.scrollWidth - scrolling_div.scrollLeft,
+                scrolling_div.clientWidth);
+
+    overscrolled_x_delta = 0;
+    overscrolled_y_delta = 0;
+
+    // Do a vertical scroll and wait for overscroll event.
+    await touchScrollInTarget(300, scrolling_div, 'down');
+    await waitFor(() => { return overscrolled_y_delta > 0; },
+        'Scroller did not receive overscroll event after vertical scroll.');
+    assert_equals(scrolling_div.scrollHeight - scrolling_div.scrollTop,
+                scrolling_div.clientHeight);
+  }, 'Tests that the scrolled element gets overscroll event after fully scrolling by touch.');
+}
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-window-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-window-expected.txt
new file mode 100644 (file)
index 0000000..70cf065
--- /dev/null
@@ -0,0 +1,3 @@
+
+FAIL Tests that the window gets overscroll event when no element scrollsafter touch scrolling. promise_test: Unhandled rejection with value: "Window did not receive overscroll event after scroll up on target."
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-window.html b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-window.html
new file mode 100644 (file)
index 0000000..ef5ae3d
--- /dev/null
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<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>
+<style>
+#targetDiv {
+  width: 200px;
+  height: 200px;
+  overflow: scroll;
+}
+
+#innerDiv {
+  width: 400px;
+  height: 400px;
+}
+</style>
+
+<body style="margin:0" onload=runTest()>
+<div id="targetDiv">
+  <div id="innerDiv">
+  </div>
+</div>
+</body>
+
+<script>
+var target_div = document.getElementById('targetDiv');
+var window_received_overscroll = false;
+
+function onOverscroll(event) {
+  assert_false(event.cancelable);
+  // overscroll events targetting document are bubbled to the window.
+  assert_true(event.bubbles);
+  window_received_overscroll = true;
+}
+window.addEventListener("overscroll", onOverscroll);
+
+function runTest() {
+  promise_test (async (t) => {
+    // Make sure that no overscroll event is sent to target_div.
+    target_div.addEventListener("overscroll",
+        t.unreached_func("target_div got unexpected overscroll event."));
+    // Scroll up on target div and wait for the window to get overscroll event.
+    await touchScrollInTarget(300, target_div, 'up');
+    await waitFor(() => { return window_received_overscroll; },
+        'Window did not receive overscroll event after scroll up on target.');
+  }, 'Tests that the window gets overscroll event when no element scrolls' +
+     'after touch scrolling.');
+}
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scroll_support.js b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scroll_support.js
new file mode 100644 (file)
index 0000000..6fd1b32
--- /dev/null
@@ -0,0 +1,85 @@
+const MAX_FRAME = 700;
+const MAX_UNCHANGED_FRAMES = 20;
+
+// Returns a promise that resolves when the given condition is met or rejects
+// after MAX_FRAME animation frames.
+function waitFor(condition, error_message = 'Reaches the maximum frames.') {
+  return new Promise((resolve, reject) => {
+    function tick(frames) {
+      // We requestAnimationFrame either for MAX_FRAM frames or until condition
+      // is met.
+      if (frames >= MAX_FRAME)
+        reject(error_message);
+      else if (condition())
+        resolve();
+      else
+        requestAnimationFrame(tick.bind(this, frames + 1));
+    }
+    tick(0);
+  });
+}
+
+function waitForCompositorCommit() {
+  return new Promise((resolve) => {
+    // rAF twice.
+    window.requestAnimationFrame(() => {
+      window.requestAnimationFrame(resolve);
+    });
+  });
+}
+
+function waitForAnimationEnd(getValue) {
+  var last_changed_frame = 0;
+  var last_position = getValue();
+  return new Promise((resolve, reject) => {
+    function tick(frames) {
+    // We requestAnimationFrame either for MAX_FRAME or until
+    // MAX_UNCHANGED_FRAMES with no change have been observed.
+      if (frames >= MAX_FRAME || frames - last_changed_frame > MAX_UNCHANGED_FRAMES) {
+        resolve();
+      } else {
+        current_value = getValue();
+        if (last_position != current_value) {
+          last_changed_frame = frames;
+          last_position = current_value;
+        }
+        requestAnimationFrame(tick.bind(this, frames + 1));
+      }
+    }
+    tick(0);
+  })
+}
+
+function touchScrollInTarget(pixels_to_scroll, target, direction, pause_time_in_ms = 100) {
+  var x_delta = 0;
+  var y_delta = 0;
+  const num_movs = 5;
+  if (direction == "down") {
+    y_delta = -1 * pixels_to_scroll / num_movs;
+  } else if (direction == "up") {
+    y_delta = pixels_to_scroll / num_movs;
+  } else if (direction == "right") {
+    x_delta = -1 * pixels_to_scroll / num_movs;
+  } else if (direction == "left") {
+    x_delta = pixels_to_scroll / num_movs;;
+  } else {
+    throw("scroll direction '" + direction + "' is not expected, direction should be 'down', 'up', 'left' or 'right'");
+  }
+  return new test_driver.Actions()
+      .addPointer("pointer1", "touch")
+      .pointerMove(0, 0, {origin: target})
+      .pointerDown()
+      .pointerMove(x_delta, y_delta, {origin: target})
+      .pointerMove(2 * x_delta, 2 * y_delta, {origin: target})
+      .pointerMove(3 * x_delta, 3 * y_delta, {origin: target})
+      .pointerMove(4 * x_delta, 4 * y_delta, {origin: target})
+      .pointerMove(5 * x_delta, 5 * y_delta, {origin: target})
+      .pause(pause_time_in_ms)
+      .pointerUp()
+      .send();
+}
+
+// Trigger fling by doing pointerUp right after pointerMoves.
+function touchFlingInTarget(pixels_to_scroll, target, direction) {
+  touchScrollInTarget(pixels_to_scroll, target, direction, 0 /* pause_time */);
+}
diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-after-snap-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-after-snap-expected.txt
new file mode 100644 (file)
index 0000000..f736bc1
--- /dev/null
@@ -0,0 +1,4 @@
+
+FAIL Tests that scrollend is fired after scroll snap animation completion. promise_test: Unhandled rejection with value: "Reaches the maximum frames."
+FAIL Tests that scrollend is fired after fling snap animation completion. promise_test: Unhandled rejection with value: "Reaches the maximum frames."
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-after-snap.html b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-after-snap.html
new file mode 100644 (file)
index 0000000..ef1b495
--- /dev/null
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<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>
+<style>
+div {
+  position: absolute;
+}
+#scroller {
+  width: 500px;
+  height: 500px;
+  overflow: scroll;
+  scroll-snap-type: both mandatory;
+  border: solid black 5px;
+}
+#space {
+  width: 2000px;
+  height: 2000px;
+}
+.target {
+  width: 200px;
+  height: 200px;
+  scroll-snap-align: start;
+  background-color: blue;
+}
+</style>
+
+<body style="margin:0" onload=runTests()>
+  <div id="scroller">
+    <div id="space"></div>
+    <div class="target" style="left: 0px; top: 0px;"></div>
+    <div class="target" style="left: 80px; top: 80px;"></div>
+    <div class="target" style="left: 200px; top: 200px;"></div>
+  </div>
+</body>
+
+<script>
+var scroller = document.getElementById("scroller");
+var space = document.getElementById("space");
+const MAX_FRAME_COUNT = 700;
+const MAX_UNCHANGED_FRAME = 20;
+
+function scrollTop() {
+  return scroller.scrollTop;
+}
+
+var scroll_arrived_after_scroll_end = false;
+var scroll_end_arrived = false;
+scroller.addEventListener("scroll", () => {
+  if (scroll_end_arrived)
+    scroll_arrived_after_scroll_end = true;
+});
+scroller.addEventListener("scrollend", () => {
+  scroll_end_arrived = true;
+});
+
+function runTests() {
+  promise_test (async () => {
+    await waitForCompositorCommit();
+    await touchScrollInTarget(100, scroller, 'down');
+    // Wait for the scroll snap animation to finish.
+    await waitForAnimationEnd(scrollTop);
+    await waitFor(() => { return scroll_end_arrived; });
+    // Verify that scroll snap animation has finished before firing scrollend event.
+    assert_false(scroll_arrived_after_scroll_end);
+  }, "Tests that scrollend is fired after scroll snap animation completion.");
+
+  promise_test (async () => {
+    // Reset scroll state.
+    scroller.scrollTo(0, 0);
+    await waitForCompositorCommit();
+    scroll_end_arrived = false;
+    scroll_arrived_after_scroll_end = false;
+
+    await touchFlingInTarget(50, scroller, 'down');
+    // Wait for the scroll snap animation to finish.
+    await waitForAnimationEnd(scrollTop);
+    await waitFor(() => { return scroll_end_arrived; });
+    // Verify that scroll snap animation has finished before firing scrollend event.
+    assert_false(scroll_arrived_after_scroll_end);
+  }, "Tests that scrollend is fired after fling snap animation completion.");
+}
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-document-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-document-expected.txt
new file mode 100644 (file)
index 0000000..5017b91
--- /dev/null
@@ -0,0 +1,3 @@
+
+FAIL Tests that the document gets scrollend event when no element scrolls by touch. promise_test: Unhandled rejection with value: "Document did not receive scrollend event after scroll left on target."
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-document.html b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-document.html
new file mode 100644 (file)
index 0000000..a35508e
--- /dev/null
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML>
+<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>
+<style>
+#targetDiv {
+  width: 200px;
+  height: 200px;
+  overflow: scroll;
+}
+
+#innerDiv {
+  width: 400px;
+  height: 400px;
+}
+</style>
+
+<body style="margin:0" onload=runTest()>
+<div id="targetDiv">
+  <div id="innerDiv">
+  </div>
+</div>
+</body>
+
+<script>
+var target_div = document.getElementById('targetDiv');
+var horizontal_scrollend_arrived = false;
+var vertical_scrollend_arrived = false;
+function onHorizontalScrollEnd(event) {
+  assert_false(event.cancelable);
+  // scrollend events are bubbled when the target node is document.
+  assert_true(event.bubbles);
+  horizontal_scrollend_arrived = true;
+}
+function onVerticalScrollEnd(event) {
+  assert_false(event.cancelable);
+  // scrollend events are bubbled when the target node is document.
+  assert_true(event.bubbles);
+  vertical_scrollend_arrived = true;
+}
+document.addEventListener("scrollend", onHorizontalScrollEnd);
+document.addEventListener("scrollend", onVerticalScrollEnd);
+
+function runTest() {
+  promise_test (async (t) => {
+    // Make sure that no scrollend event is sent to target_div.
+    target_div.addEventListener("scrollend",
+        t.unreached_func("target_div got unexpected scrollend event."));
+    await waitForCompositorCommit();
+    // Scroll left on target div and wait for the doc to get scrollend event.
+    await touchScrollInTarget(300, target_div, 'left');
+    await waitFor(() => { return horizontal_scrollend_arrived; },
+        'Document did not receive scrollend event after scroll left on target.');
+    assert_equals(target_div.scrollLeft, 0);
+
+    // Scroll up on target div and wait for the doc to get scrollend event.
+    await touchScrollInTarget(300, target_div, 'up');
+    await waitFor(() => { return vertical_scrollend_arrived; },
+        'Document did not receive scrollend event after scroll up on target.');
+    assert_equals(target_div.scrollTop, 0);
+  }, 'Tests that the document gets scrollend event when no element scrolls by ' +
+     'touch.');
+}
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-element-with-overscroll-behavior-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-element-with-overscroll-behavior-expected.txt
new file mode 100644 (file)
index 0000000..2d64fae
--- /dev/null
@@ -0,0 +1,3 @@
+
+FAIL Tests that the last element in the cut scroll chain gets scrollend event when no element scrolls by touch. promise_test: Unhandled rejection with value: "Expected element did not receive scrollend event after scroll left on target."
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-element-with-overscroll-behavior.html b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-element-with-overscroll-behavior.html
new file mode 100644 (file)
index 0000000..0269c66
--- /dev/null
@@ -0,0 +1,93 @@
+<!DOCTYPE HTML>
+<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>
+<style>
+#overscrollXDiv {
+  width: 600px;
+  height: 600px;
+  overflow: scroll;
+  overscroll-behavior-x: contain;
+}
+#overscrollYDiv {
+  width: 500px;
+  height: 500px;
+  overflow: scroll;
+  overscroll-behavior-y: none;
+}
+#targetDiv {
+  width: 400px;
+  height: 400px;
+  overflow: scroll;
+}
+.content {
+  width:800px;
+  height:800px;
+}
+</style>
+
+<body style="margin:0" onload=runTest()>
+<div id="overscrollXDiv">
+  <div class=content>
+    <div id="overscrollYDiv">
+      <div class=content>
+        <div id="targetDiv">
+          <div class="content">
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+</body>
+
+<script>
+var target_div = document.getElementById('targetDiv');
+var horizontal_scrollend_arrived = false;
+var vertical_scrollend_arrived = false;
+function onHorizontalScrollEnd(event) {
+  assert_false(event.cancelable);
+  assert_false(event.bubbles);
+  horizontal_scrollend_arrived = true;
+}
+function onVerticalScrollEnd(event) {
+  assert_false(event.cancelable);
+  assert_false(event.bubbles);
+  vertical_scrollend_arrived = true;
+}
+// Test that both "onscrollend" and addEventListener("scrollend"... work.
+document.getElementById('overscrollXDiv').onscrollend = onHorizontalScrollEnd;
+document.getElementById('overscrollYDiv').
+    addEventListener("scrollend", onVerticalScrollEnd);
+
+function runTest() {
+  promise_test (async (t) => {
+    // Make sure that no scrollend event is sent to document or target_div.
+    document.addEventListener("scrollend",
+        t.unreached_func("Document got unexpected scrollend event."));
+    target_div.addEventListener("scrollend",
+        t.unreached_func("target_div got unexpected scrollend event."));
+    await waitForCompositorCommit();
+
+    // Scroll left on target div and wait for the element with overscroll-x to
+    // get scrollend event.
+    await touchScrollInTarget(300, target_div, 'left');
+    await waitFor(() => { return horizontal_scrollend_arrived; },
+        'Expected element did not receive scrollend event after scroll left ' +
+        'on target.');
+    assert_equals(target_div.scrollLeft, 0);
+
+    // Scroll up on target div and wait for the element with overscroll-y to get
+    // scrollend event.
+    await touchScrollInTarget(300, target_div, 'up');
+    await waitFor(() => { return vertical_scrollend_arrived; },
+        'Expected element did not receive scrollend event after scroll up on ' +
+        'target.');
+    assert_equals(target_div.scrollTop, 0);
+  }, 'Tests that the last element in the cut scroll chain gets scrollend ' +
+     'event when no element scrolls by touch.');
+}
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-scrolled-element-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-scrolled-element-expected.txt
new file mode 100644 (file)
index 0000000..9fd4bf6
--- /dev/null
@@ -0,0 +1,3 @@
+
+FAIL Tests that the scrolled element gets scrollend event at the end of touch scrolling. promise_test: Unhandled rejection with value: "Scroller did not receive scrollend event after horizontal scroll."
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-scrolled-element.html b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-scrolled-element.html
new file mode 100644 (file)
index 0000000..87cad79
--- /dev/null
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML>
+<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>
+<style>
+#scrollableDiv {
+  width: 200px;
+  height: 200px;
+  overflow: scroll;
+}
+
+#innerDiv {
+  width: 400px;
+  height: 400px;
+}
+</style>
+
+<body style="margin:0" onload=runTest()>
+<div id="scrollableDiv">
+  <div id="innerDiv">
+  </div>
+</div>
+</body>
+
+<script>
+var scrolling_div = document.getElementById('scrollableDiv');
+var horizontal_scrollend_arrived = false;
+var vertical_scrollend_arrived = false;
+function onHorizontalScrollEnd(event) {
+  assert_false(event.cancelable);
+  assert_false(event.bubbles);
+  horizontal_scrollend_arrived = true;
+}
+function onVerticalScrollEnd(event) {
+  assert_false(event.cancelable);
+  assert_false(event.bubbles);
+  vertical_scrollend_arrived = true;
+}
+scrolling_div.addEventListener("scrollend", onHorizontalScrollEnd);
+scrolling_div.addEventListener("scrollend", onVerticalScrollEnd);
+
+function runTest() {
+  promise_test (async (t) => {
+    // Make sure that no scrollend event is sent to document.
+    document.addEventListener("scrollend",
+        t.unreached_func("Document got unexpected scrollend event."));
+    await waitForCompositorCommit();
+
+    // Do a horizontal scroll and wait for scrollend event.
+    await touchScrollInTarget(300, scrolling_div, 'right');
+    await waitFor(() => { return horizontal_scrollend_arrived; },
+        'Scroller did not receive scrollend event after horizontal scroll.');
+    assert_equals(scrolling_div.scrollWidth - scrolling_div.scrollLeft,
+                scrolling_div.clientWidth);
+
+    // Do a vertical scroll and wait for scrollend event.
+    await touchScrollInTarget(300, scrolling_div, 'down');
+    await waitFor(() => { return vertical_scrollend_arrived; },
+        'Scroller did not receive scrollend event after vertical scroll.');
+    assert_equals(scrolling_div.scrollHeight - scrolling_div.scrollTop,
+                scrolling_div.clientHeight);
+  }, 'Tests that the scrolled element gets scrollend event at the end of touch scrolling.');
+}
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-window-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-window-expected.txt
new file mode 100644 (file)
index 0000000..d095280
--- /dev/null
@@ -0,0 +1,3 @@
+
+FAIL Tests that the window gets scrollend event when no element scrolls after touch scrolling. promise_test: Unhandled rejection with value: "Window did not receive scrollend event after scroll up on target."
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-window.html b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-window.html
new file mode 100644 (file)
index 0000000..f9510e6
--- /dev/null
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<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>
+<style>
+#targetDiv {
+  width: 200px;
+  height: 200px;
+  overflow: scroll;
+}
+
+#innerDiv {
+  width: 400px;
+  height: 400px;
+}
+</style>
+
+<body style="margin:0" onload=runTest()>
+<div id="targetDiv">
+  <div id="innerDiv">
+  </div>
+</div>
+</body>
+
+<script>
+var target_div = document.getElementById('targetDiv');
+var scrollend_arrived = false;
+function onScrollEnd(event) {
+  assert_false(event.cancelable);
+  // scrollend events targetting document are bubbled to the window.
+  assert_true(event.bubbles);
+  scrollend_arrived = true;
+}
+window.addEventListener("scrollend", onScrollEnd);
+
+function runTest() {
+  promise_test (async (t) => {
+    // Make sure that no scrollend event is sent to target_div.
+    target_div.addEventListener("scrollend",
+        t.unreached_func("target_div got unexpected scrollend event."));
+    await waitForCompositorCommit();
+
+    // Scroll up on target div and wait for the doc to get scrollend event.
+    await touchScrollInTarget(300, target_div, 'up');
+    await waitFor(() => { return scrollend_arrived; },
+        'Window did not receive scrollend event after scroll up on target.');
+    assert_equals(target_div.scrollTop, 0);
+  }, 'Tests that the window gets scrollend event when no element scrolls ' +
+     'after touch scrolling.');
+}
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/w3c-import.log b/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/w3c-import.log
new file mode 100644 (file)
index 0000000..3be9105
--- /dev/null
@@ -0,0 +1,26 @@
+The tests in this directory were imported from the W3C repository.
+Do NOT modify these tests directly in WebKit.
+Instead, create a pull request on the WPT github:
+       https://github.com/web-platform-tests/wpt
+
+Then run the Tools/Scripts/import-w3c-tests in WebKit to reimport
+
+Do NOT modify or remove this file.
+
+------------------------------------------------------------------------
+Properties requiring vendor prefixes:
+None
+Property values requiring vendor prefixes:
+None
+------------------------------------------------------------------------
+List of files:
+/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-document.html
+/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-element-with-overscroll-behavior.html
+/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-scrolled-element.html
+/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/overscroll-event-fired-to-window.html
+/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scroll_support.js
+/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-after-snap.html
+/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-document.html
+/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-element-with-overscroll-behavior.html
+/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-scrolled-element.html
+/LayoutTests/imported/w3c/web-platform-tests/dom/events/scrolling/scrollend-event-fired-to-window.html
index f974f27..263e0db 100644 (file)
@@ -2560,6 +2560,8 @@ media/W3C/audio/canPlayType/canPlayType_supported_but_no_codecs_parameter_1.html
 
 media/video-seek-to-current-time.html [ Failure ]
 
+imported/w3c/web-platform-tests/dom/events/scrolling [ Pass ]
+
 fast/attachment/attachment-wrapping-action.html [ Pass ]
 fast/attachment/attachment-borderless.html [ Pass ]
 fast/images/pdf-as-image-dest-rect-change.html [ Pass ]