diff --git a/test/fixtures/wpt/README.md b/test/fixtures/wpt/README.md index 836e238bc4bcef..3e60ab39f00971 100644 --- a/test/fixtures/wpt/README.md +++ b/test/fixtures/wpt/README.md @@ -14,7 +14,7 @@ Last update: - compression: https://github.com/web-platform-tests/wpt/tree/5aa50dd415/compression - console: https://github.com/web-platform-tests/wpt/tree/767ae35464/console - dom/abort: https://github.com/web-platform-tests/wpt/tree/d1f1ecbd52/dom/abort -- dom/events: https://github.com/web-platform-tests/wpt/tree/ab8999891c/dom/events +- dom/events: https://github.com/web-platform-tests/wpt/tree/0a811c5161/dom/events - encoding: https://github.com/web-platform-tests/wpt/tree/5aa50dd415/encoding - fetch/data-urls/resources: https://github.com/web-platform-tests/wpt/tree/7c79d998ff/fetch/data-urls/resources - FileAPI: https://github.com/web-platform-tests/wpt/tree/cceaf3628d/FileAPI diff --git a/test/fixtures/wpt/dom/events/Event-dispatch-click.html b/test/fixtures/wpt/dom/events/Event-dispatch-click.html index 010305775df7e9..ab4a24a5ad5096 100644 --- a/test/fixtures/wpt/dom/events/Event-dispatch-click.html +++ b/test/fixtures/wpt/dom/events/Event-dispatch-click.html @@ -87,6 +87,22 @@ child.dispatchEvent(new MouseEvent("click", {bubbles:true})) }, "pick the first with activation behavior ") +async_test(function(t) { + var input = document.createElement("input") + input.type = "radio" + dump.appendChild(input) + input.onclick = t.step_func(function() { + assert_false(input.checked, "input pre-click must not be triggered") + }) + var child = input.appendChild(document.createElement("input")) + child.type = "radio" + child.onclick = t.step_func(function() { + assert_true(child.checked, "child pre-click must be triggered") + }) + child.dispatchEvent(new MouseEvent("click", {bubbles:true})) + t.done() +}, "pick the first with activation behavior ") + async_test(function(t) { var input = document.createElement("input") input.type = "checkbox" @@ -173,6 +189,46 @@ t.done() }, "disabled checkbox still has activation behavior, part 2") +async_test(function(t) { + var state = "start" + + var form = document.createElement("form") + form.onsubmit = t.step_func(() => { + if(state == "start" || state == "radio") { + state = "failure" + } else if(state == "form") { + state = "done" + } + return false + }) + dump.appendChild(form) + var button = form.appendChild(document.createElement("button")) + button.type = "submit" + var radio = button.appendChild(document.createElement("input")) + radio.type = "radio" + radio.onclick = t.step_func(() => { + if(state == "start") { + assert_unreached() + } else if(state == "radio") { + assert_true(radio.checked) + } + }) + radio.disabled = true + radio.click() + assert_equals(state, "start") + + state = "radio" + radio.disabled = false + radio.click() + assert_equals(state, "radio") + + state = "form" + button.click() + assert_equals(state, "done") + + t.done() +}, "disabled radio still has activation behavior") + async_test(function(t) { var input = document.createElement("input") input.type = "checkbox" diff --git a/test/fixtures/wpt/dom/events/Event-dispatch-on-disabled-elements.html b/test/fixtures/wpt/dom/events/Event-dispatch-on-disabled-elements.html index 361006a7240496..e7d6b455bbcaab 100644 --- a/test/fixtures/wpt/dom/events/Event-dispatch-on-disabled-elements.html +++ b/test/fixtures/wpt/dom/events/Event-dispatch-on-disabled-elements.html @@ -19,7 +19,7 @@ + +
+ +
+ + + + + diff --git a/test/fixtures/wpt/dom/events/Event-dispatch-throwing-multiple-globals.html b/test/fixtures/wpt/dom/events/Event-dispatch-throwing-multiple-globals.html new file mode 100644 index 00000000000000..a56fdf6af86581 --- /dev/null +++ b/test/fixtures/wpt/dom/events/Event-dispatch-throwing-multiple-globals.html @@ -0,0 +1,69 @@ + + + + + + diff --git a/test/fixtures/wpt/dom/events/EventTarget-constructible.any.js b/test/fixtures/wpt/dom/events/EventTarget-constructible.any.js index b0e7614e625b3d..4125d23f0c9650 100644 --- a/test/fixtures/wpt/dom/events/EventTarget-constructible.any.js +++ b/test/fixtures/wpt/dom/events/EventTarget-constructible.any.js @@ -23,6 +23,23 @@ test(() => { assert_equals(callCount, 2); }, "A constructed EventTarget can be used as expected"); +test(() => { + const target = new EventTarget(); + const event = new Event("foo"); + + function listener(e) { + assert_equals(e, event); + assert_equals(e.target, target); + assert_equals(e.currentTarget, target); + assert_array_equals(e.composedPath(), [target]); + } + target.addEventListener("foo", listener, { once: true }); + target.dispatchEvent(event); + assert_equals(event.target, target); + assert_equals(event.currentTarget, null); + assert_array_equals(event.composedPath(), []); +}, "A constructed EventTarget implements dispatch correctly"); + test(() => { class NicerEventTarget extends EventTarget { on(...args) { diff --git a/test/fixtures/wpt/dom/events/event-global.html b/test/fixtures/wpt/dom/events/event-global.html index 3e8d25ecb5dd9d..f70606fb65496a 100644 --- a/test/fixtures/wpt/dom/events/event-global.html +++ b/test/fixtures/wpt/dom/events/event-global.html @@ -114,4 +114,14 @@ target.dispatchEvent(new Event("click")); }, "window.event is set to the current event, which is the event passed to dispatch"); + +async_test(t => { + let target = new XMLHttpRequest(); + + target.onload = t.step_func_done(e => { + assert_equals(e, window.event); + }); + + target.dispatchEvent(new Event("load")); +}, "window.event is set to the current event, which is the event passed to dispatch (2)"); diff --git a/test/fixtures/wpt/dom/events/pointer-event-document-move.html b/test/fixtures/wpt/dom/events/pointer-event-document-move.html new file mode 100644 index 00000000000000..91e7c36860572a --- /dev/null +++ b/test/fixtures/wpt/dom/events/pointer-event-document-move.html @@ -0,0 +1,29 @@ + + + + + + + + + + + + diff --git a/test/fixtures/wpt/dom/events/preventDefault-during-activation-behavior.html b/test/fixtures/wpt/dom/events/preventDefault-during-activation-behavior.html new file mode 100644 index 00000000000000..92874031347165 --- /dev/null +++ b/test/fixtures/wpt/dom/events/preventDefault-during-activation-behavior.html @@ -0,0 +1,53 @@ + +preventDefault during activation behavior + + + + + + + + + +
+ +
+ + diff --git a/test/fixtures/wpt/dom/events/remove-all-listeners.html b/test/fixtures/wpt/dom/events/remove-all-listeners.html new file mode 100644 index 00000000000000..3a2a751a146bca --- /dev/null +++ b/test/fixtures/wpt/dom/events/remove-all-listeners.html @@ -0,0 +1,95 @@ + +Various edge cases where listeners are removed during iteration + + +
+ diff --git a/test/fixtures/wpt/dom/events/scrolling/WEB_FEATURES.yml b/test/fixtures/wpt/dom/events/scrolling/WEB_FEATURES.yml new file mode 100644 index 00000000000000..e4fba841b62ac9 --- /dev/null +++ b/test/fixtures/wpt/dom/events/scrolling/WEB_FEATURES.yml @@ -0,0 +1,4 @@ +features: +- name: scrollend + files: + - scrollend-* diff --git a/test/fixtures/wpt/dom/events/scrolling/overscroll-deltas.html b/test/fixtures/wpt/dom/events/scrolling/overscroll-deltas.html index 6f0b77f22eda2a..e13e9f1cce5949 100644 --- a/test/fixtures/wpt/dom/events/scrolling/overscroll-deltas.html +++ b/test/fixtures/wpt/dom/events/scrolling/overscroll-deltas.html @@ -6,80 +6,152 @@ - -
-
+ +
+
+
+
+
diff --git a/test/fixtures/wpt/dom/events/scrolling/overscroll-event-fired-to-scrolled-element.html b/test/fixtures/wpt/dom/events/scrolling/overscroll-event-fired-to-scrolled-element.html index cfc782a809a7e7..be4176df59d6a1 100644 --- a/test/fixtures/wpt/dom/events/scrolling/overscroll-event-fired-to-scrolled-element.html +++ b/test/fixtures/wpt/dom/events/scrolling/overscroll-event-fired-to-scrolled-element.html @@ -10,11 +10,14 @@ width: 200px; height: 200px; overflow: scroll; + position: absolute; + left: 150px; + top: 150px; } #innerDiv { - width: 400px; - height: 400px; + width: 250px; + height: 250px; } @@ -45,7 +48,7 @@ await waitForCompositorCommit(); // Do a horizontal scroll and wait for overscroll event. - await touchScrollInTarget(300, scrolling_div , 'right'); + await touchScrollInTarget(100, 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, @@ -55,7 +58,7 @@ overscrolled_y_delta = 0; // Do a vertical scroll and wait for overscroll event. - await touchScrollInTarget(300, scrolling_div, 'down'); + await touchScrollInTarget(100, 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, diff --git a/test/fixtures/wpt/dom/events/scrolling/scroll_support.js b/test/fixtures/wpt/dom/events/scrolling/scroll_support.js index 169393e4c3e419..a708364df07cad 100644 --- a/test/fixtures/wpt/dom/events/scrolling/scroll_support.js +++ b/test/fixtures/wpt/dom/events/scrolling/scroll_support.js @@ -1,15 +1,83 @@ -async function waitForScrollendEvent(test, target, timeoutMs = 500) { +async function waitForEvent(eventName, test, target, timeoutMs = 500) { return new Promise((resolve, reject) => { const timeoutCallback = test.step_timeout(() => { - reject(`No Scrollend event received for target ${target}`); + reject(`No ${eventName} event received for target ${target}`); }, timeoutMs); - target.addEventListener('scrollend', (evt) => { + target.addEventListener(eventName, (evt) => { clearTimeout(timeoutCallback); resolve(evt); }, { once: true }); }); } +async function waitForScrollendEvent(test, target, timeoutMs = 500) { + return waitForEvent("scrollend", test, target, timeoutMs); +} + +async function waitForScrollendEventNoTimeout(target) { + return new Promise((resolve) => { + target.addEventListener("scrollend", resolve); + }); +} + +async function waitForPointercancelEvent(test, target, timeoutMs = 500) { + return waitForEvent("pointercancel", test, target, timeoutMs); +} + +// Resets the scroll position to (0,0). If a scroll is required, then the +// promise is not resolved until the scrollend event is received. +async function waitForScrollReset(test, scroller, x = 0, y = 0) { + return new Promise(resolve => { + if (scroller.scrollTop == x && scroller.scrollLeft == y) { + resolve(); + } else { + const eventTarget = + scroller == document.scrollingElement ? document : scroller; + scroller.scrollTo(x, y); + waitForScrollendEventNoTimeout(eventTarget).then(resolve); + } + }); +} + +async function createScrollendPromiseForTarget(test, + target_div, + timeoutMs = 500) { + return waitForScrollendEvent(test, target_div, timeoutMs).then(evt => { + assert_false(evt.cancelable, 'Event is not cancelable'); + assert_false(evt.bubbles, 'Event targeting element does not bubble'); + }); +} + +function verifyNoScrollendOnDocument(test) { + const callback = + test.unreached_func("window got unexpected scrollend event."); + window.addEventListener('scrollend', callback); + test.add_cleanup(() => { + window.removeEventListener('scrollend', callback); + }); +} + +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(target_div.scrollLeft, x); + assert_equals(target_div.scrollTop, y); + resolve(); + }, unscaled_pause_time_in_ms); + }); +} + +async function resetTargetScrollState(test, target_div) { + if (target_div.scrollTop != 0 || target_div.scrollLeft != 0) { + target_div.scrollTop = 0; + target_div.scrollLeft = 0; + return waitForScrollendEvent(test, target_div); + } +} + const MAX_FRAME = 700; const MAX_UNCHANGED_FRAMES = 20; @@ -45,6 +113,29 @@ function waitForCompositorCommit() { }); } +// Please don't remove this. This is necessary for chromium-based browsers. It +// can be a no-op on user-agents that do not have a separate compositor thread. +// TODO(crbug.com/1509054): This shouldn't be necessary if the test harness +// deferred running the tests until after paint holding. +async function waitForCompositorReady() { + const animation = + document.body.animate({ opacity: [ 0, 1 ] }, {duration: 1 }); + return animation.finished; +} + +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. function waitForAnimationEnd(getValue) { @@ -70,6 +161,10 @@ function waitForAnimationEnd(getValue) { } // Scrolls in target according to move_path with pauses in between +// The move_path should contains coordinates that are within target boundaries. +// Keep in mind that 0,0 is the center of the target element and is also +// the pointerDown position. +// pointerUp() is fired after sequence of moves. function touchScrollInTargetSequentiallyWithPause(target, move_path, pause_time_in_ms = 100) { const test_driver_actions = new test_driver.Actions() .addPointer("pointer1", "touch") @@ -88,7 +183,7 @@ function touchScrollInTargetSequentiallyWithPause(target, move_path, pause_time_ y += step_y; test_driver_actions.pointerMove(x, y, {origin: target}); } - test_driver_actions.pause(pause_time_in_ms); + test_driver_actions.pause(pause_time_in_ms); // To prevent inertial scroll } return test_driver_actions.pointerUp().send(); @@ -125,7 +220,7 @@ function touchScrollInTarget(pixels_to_scroll, target, direction, pause_time_in_ // Trigger fling by doing pointerUp right after pointerMoves. function touchFlingInTarget(pixels_to_scroll, target, direction) { - touchScrollInTarget(pixels_to_scroll, target, direction, 0 /* pause_time */); + return touchScrollInTarget(pixels_to_scroll, target, direction, 0 /* pause_time */); } function mouseActionsInTarget(target, origin, delta, pause_time_in_ms = 100) { @@ -161,3 +256,23 @@ function conditionHolds(condition, error_message = 'Condition is not true anymor tick(0); }); } + +function scrollElementDown(element, scroll_amount) { + let x = 0; + let y = 0; + let delta_x = 0; + let delta_y = scroll_amount; + let actions = new test_driver.Actions() + .scroll(x, y, delta_x, delta_y, {origin: element}); + return actions.send(); +} + +function scrollElementLeft(element, scroll_amount) { + let x = 0; + let y = 0; + let delta_x = scroll_amount; + let delta_y = 0; + let actions = new test_driver.Actions() + .scroll(x, y, delta_x, delta_y, {origin: element}); + return actions.send(); +} diff --git a/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-after-sequence-of-scrolls.tentative.html b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-after-sequence-of-scrolls.tentative.html index 77bf029ced58c5..dab6dcc9bd8d67 100644 --- a/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-after-sequence-of-scrolls.tentative.html +++ b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-after-sequence-of-scrolls.tentative.html @@ -14,7 +14,7 @@ } #innerDiv { - width: 500px; + width: 4000px; height: 4000px; } @@ -28,36 +28,64 @@ diff --git a/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-for-mandatory-snap-point-after-load.html b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-for-mandatory-snap-point-after-load.html new file mode 100644 index 00000000000000..f3791134204497 --- /dev/null +++ b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-for-mandatory-snap-point-after-load.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + scrollend + mandatory scroll snap test + + + + + + + + + + + \ No newline at end of file diff --git a/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-for-programmatic-scroll.html b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-for-programmatic-scroll.html index c6569e0bebbd9f..449aea05351244 100644 --- a/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-for-programmatic-scroll.html +++ b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-for-programmatic-scroll.html @@ -1,11 +1,19 @@ - + + + + + + + + + + + +
+
+
+
+ + diff --git a/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView.html b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView.html index 8782b1dfee6237..40aa77f4764b6c 100644 --- a/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView.html +++ b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView.html @@ -108,10 +108,12 @@ document.body.appendChild(out_div); await waitForCompositorCommit(); - element_scrollend_arrived = false; - document_scrollend_arrived = false; inner_div.scrollIntoView({ inline: "end", block: "end", behavior: "auto" }); - await waitFor(() => { return element_scrollend_arrived || document_scrollend_arrived; }, "Nested scrollIntoView did not receive scrollend event."); + const scrollend_events = [ + waitForScrollendEventNoTimeout(out_div), + waitForScrollendEventNoTimeout(target_div) + ]; + await Promise.all(scrollend_events); assert_equals(root_element.scrollLeft, 0, "Nested scrollIntoView root_element scrollLeft"); assert_equals(root_element.scrollTop, 0, "Nested scrollIntoView root_element scrollTop"); assert_equals(out_div.scrollLeft, 100, "Nested scrollIntoView out_div scrollLeft"); diff --git a/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-to-document.html b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-to-document.html index 30904553883435..797c2eb53da0e3 100644 --- a/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-to-document.html +++ b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-to-document.html @@ -7,64 +7,100 @@ -
-
+
+
-
+
+
diff --git a/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-to-element-with-overscroll-behavior.html b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-to-element-with-overscroll-behavior.html index acad168e56c995..edda88e7cb2064 100644 --- a/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-to-element-with-overscroll-behavior.html +++ b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-to-element-with-overscroll-behavior.html @@ -7,96 +7,167 @@ -
-
-
-
-
-
-
-
+
+
+
+
-
+
+
+ +
+
+
+
+
+
diff --git a/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-to-scrolled-element.html b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-to-scrolled-element.html deleted file mode 100644 index 734339694220cc..00000000000000 --- a/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-to-scrolled-element.html +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - -
-
-
-
- - - diff --git a/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-to-window.html b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-to-window.html index ef72f56d2ba9d6..d2fd6f4d3158a5 100644 --- a/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-to-window.html +++ b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fired-to-window.html @@ -7,49 +7,63 @@ -
-
+
+
-
+
diff --git a/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fires-on-visual-viewport.html b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fires-on-visual-viewport.html new file mode 100644 index 00000000000000..99a281480ff11f --- /dev/null +++ b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fires-on-visual-viewport.html @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + +
+ + + diff --git a/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fires-to-iframe-inner-frame.html b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fires-to-iframe-inner-frame.html new file mode 100644 index 00000000000000..115e583c067ebd --- /dev/null +++ b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fires-to-iframe-inner-frame.html @@ -0,0 +1,30 @@ + + + + +
+
+
+
+ + diff --git a/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fires-to-iframe-window.html b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fires-to-iframe-window.html new file mode 100644 index 00000000000000..9cd3b421fe9036 --- /dev/null +++ b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-fires-to-iframe-window.html @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/fixtures/wpt/dom/events/scrolling/scrollend-event-for-user-scroll.html b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-for-user-scroll.html index 5146c5f719a1e4..a06843a35e7ec9 100644 --- a/test/fixtures/wpt/dom/events/scrolling/scrollend-event-for-user-scroll.html +++ b/test/fixtures/wpt/dom/events/scrolling/scrollend-event-for-user-scroll.html @@ -8,6 +8,7 @@ + + + +
+ + +
+
+ +
+ + + diff --git a/test/fixtures/wpt/dom/events/scrolling/scrollend-fires-to-text-input.html b/test/fixtures/wpt/dom/events/scrolling/scrollend-fires-to-text-input.html new file mode 100644 index 00000000000000..edc75d9121776e --- /dev/null +++ b/test/fixtures/wpt/dom/events/scrolling/scrollend-fires-to-text-input.html @@ -0,0 +1,32 @@ + + + + + + + + + + + + diff --git a/test/fixtures/wpt/dom/events/scrolling/scrollend-user-scroll-common.js b/test/fixtures/wpt/dom/events/scrolling/scrollend-user-scroll-common.js new file mode 100644 index 00000000000000..1b637233882843 --- /dev/null +++ b/test/fixtures/wpt/dom/events/scrolling/scrollend-user-scroll-common.js @@ -0,0 +1,150 @@ + +async function test_scrollend_on_touch_drag(t, target_div) { + // Skip the test on a Mac as they do not support touch screens. + const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0; + if (isMac) + return; + + await resetTargetScrollState(t, target_div); + await waitForCompositorReady(); + + const targetScrollendPromise = waitForScrollendEventNoTimeout(target_div); + verifyNoScrollendOnDocument(t); + + let scrollend_count = 0; + const scrollend_listener = () => { + scrollend_count += 1; + }; + target_div.addEventListener("scrollend", scrollend_listener); + t.add_cleanup(() => { + target_div.removeEventListener('scrollend', scrollend_listener); + }); + + // Perform a touch drag on target div and wait for target_div to get + // a scrollend event. + await new test_driver.Actions() + .addPointer('TestPointer', 'touch') + .pointerMove(0, 0, { origin: target_div }) // 0, 0 is center of element. + .pointerDown() + .addTick() + .pointerMove(0, -40, { origin: target_div }) // Drag up to move down. + .addTick() + .pause(200) // Prevent inertial scroll. + .pointerMove(0, -60, { origin: target_div }) + .addTick() + .pause(200) // Prevent inertial scroll. + .pointerUp() + .send(); + + await targetScrollendPromise; + + assert_true(target_div.scrollTop > 0); + await verifyScrollStopped(t, target_div); + assert_equals(scrollend_count, 1); +} + +async function test_scrollend_on_scrollbar_gutter_click(t, target_div) { + // Skip test on platforms that do not have a visible scrollbar (e.g. + // overlay scrollbar). + const scrollbar_width = target_div.offsetWidth - target_div.clientWidth; + if (scrollbar_width == 0) + return; + + await resetTargetScrollState(t, target_div); + await waitForCompositorReady(); + + const targetScrollendPromise = waitForScrollendEventNoTimeout(target_div); + verifyNoScrollendOnDocument(t); + + const bounds = target_div.getBoundingClientRect(); + // Some versions of webdriver have been known to frown at non-int arguments + // to pointerMove. + const x = Math.round(bounds.right - scrollbar_width / 2); + const y = Math.round(bounds.bottom - 20); + await new test_driver.Actions() + .addPointer('TestPointer', 'mouse') + .pointerMove(x, y, { origin: 'viewport' }) + .pointerDown() + .addTick() + .pointerUp() + .send(); + + await targetScrollendPromise; + assert_true(target_div.scrollTop > 0); + await verifyScrollStopped(t, target_div); +} + +// Same issue as previous test. +async function test_scrollend_on_scrollbar_thumb_drag(t, target_div) { + // Skip test on platforms that do not have a visible scrollbar (e.g. + // overlay scrollbar). + const scrollbar_width = target_div.offsetWidth - target_div.clientWidth; + if (scrollbar_width == 0) + return; + + await resetTargetScrollState(t, target_div); + await waitForCompositorReady(); + + const targetScrollendPromise = waitForScrollendEventNoTimeout(target_div); + verifyNoScrollendOnDocument(t); + + const bounds = target_div.getBoundingClientRect(); + // Some versions of webdriver have been known to frown at non-int arguments + // to pointerMove. + const x = Math.round(bounds.right - scrollbar_width / 2); + const y = Math.round(bounds.top + 30); + const dy = 30; + await new test_driver.Actions() + .addPointer('TestPointer', 'mouse') + .pointerMove(x, y, { origin: 'viewport' }) + .pointerDown() + .pointerMove(x, y + dy, { origin: 'viewport' }) + .addTick() + .pointerUp() + .send(); + + await targetScrollendPromise; + assert_true(target_div.scrollTop > 0); + await verifyScrollStopped(t, target_div); +} + +async function test_scrollend_on_mousewheel_scroll(t, target_div, frame) { + await resetTargetScrollState(t, target_div); + await waitForCompositorReady(); + + const targetScrollendPromise = waitForScrollendEventNoTimeout(target_div); + verifyNoScrollendOnDocument(t); + + let scroll_origin = target_div; + if (frame) { + // chromedriver doesn't support passing { origin: element } + // for an element within a subframe. Use the frame element itself. + scroll_origin = frame; + } + const x = 0; + const y = 0; + const dx = 0; + const dy = 40; + await new test_driver.Actions() + .scroll(x, y, dx, dy, { origin: scroll_origin }) + .send(); + + await targetScrollendPromise; + assert_true(target_div.scrollTop > 0); + await verifyScrollStopped(t, target_div); +} + +async function test_scrollend_on_keyboard_scroll(t, target_div) { + await resetTargetScrollState(t, target_div); + await waitForCompositorReady(); + + verifyNoScrollendOnDocument(t); + const targetScrollendPromise = waitForScrollendEventNoTimeout(target_div); + + target_div.focus(); + window.test_driver.send_keys(target_div, '\ue015'); + + await targetScrollendPromise; + assert_true(target_div.scrollTop > 0); + await verifyScrollStopped(t, target_div); +} diff --git a/test/fixtures/wpt/dom/events/scrolling/scrollend-with-snap-on-fractional-offset.html b/test/fixtures/wpt/dom/events/scrolling/scrollend-with-snap-on-fractional-offset.html new file mode 100644 index 00000000000000..d1f50304add2ac --- /dev/null +++ b/test/fixtures/wpt/dom/events/scrolling/scrollend-with-snap-on-fractional-offset.html @@ -0,0 +1,85 @@ + + + + + + + +
+
1
+
2
+
3
+
+ + + \ No newline at end of file diff --git a/test/fixtures/wpt/dom/events/scrolling/wheel-event-transactions-basic.html b/test/fixtures/wpt/dom/events/scrolling/wheel-event-transactions-basic.html new file mode 100644 index 00000000000000..1b9df69ec77f88 --- /dev/null +++ b/test/fixtures/wpt/dom/events/scrolling/wheel-event-transactions-basic.html @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + +
+
+
+
+
+
+
+
+
+
+ + + + diff --git a/test/fixtures/wpt/dom/events/scrolling/wheel-event-transactions-multiple-action-chains.html b/test/fixtures/wpt/dom/events/scrolling/wheel-event-transactions-multiple-action-chains.html new file mode 100644 index 00000000000000..3b46b2f99a9c99 --- /dev/null +++ b/test/fixtures/wpt/dom/events/scrolling/wheel-event-transactions-multiple-action-chains.html @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + +
+
+ + + + diff --git a/test/fixtures/wpt/dom/events/scrolling/wheel-event-transactions-target-display-change.html b/test/fixtures/wpt/dom/events/scrolling/wheel-event-transactions-target-display-change.html new file mode 100644 index 00000000000000..6ca3c78b74cefe --- /dev/null +++ b/test/fixtures/wpt/dom/events/scrolling/wheel-event-transactions-target-display-change.html @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + +
+
+
+ + + + diff --git a/test/fixtures/wpt/dom/events/scrolling/wheel-event-transactions-target-elements.html b/test/fixtures/wpt/dom/events/scrolling/wheel-event-transactions-target-elements.html new file mode 100644 index 00000000000000..0109b7b6b18b92 --- /dev/null +++ b/test/fixtures/wpt/dom/events/scrolling/wheel-event-transactions-target-elements.html @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + +
X
+
+ + + + diff --git a/test/fixtures/wpt/dom/events/scrolling/wheel-event-transactions-target-move.html b/test/fixtures/wpt/dom/events/scrolling/wheel-event-transactions-target-move.html new file mode 100644 index 00000000000000..a739d1cd5479ad --- /dev/null +++ b/test/fixtures/wpt/dom/events/scrolling/wheel-event-transactions-target-move.html @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + +
+
+
+ + + + diff --git a/test/fixtures/wpt/dom/events/scrolling/wheel-event-transactions-target-removal.html b/test/fixtures/wpt/dom/events/scrolling/wheel-event-transactions-target-removal.html new file mode 100644 index 00000000000000..f81efd22e22b92 --- /dev/null +++ b/test/fixtures/wpt/dom/events/scrolling/wheel-event-transactions-target-removal.html @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + +
+
+
+ + + + diff --git a/test/fixtures/wpt/dom/events/scrolling/wheel-event-transactions-target-resize.html b/test/fixtures/wpt/dom/events/scrolling/wheel-event-transactions-target-resize.html new file mode 100644 index 00000000000000..eb7431fca475db --- /dev/null +++ b/test/fixtures/wpt/dom/events/scrolling/wheel-event-transactions-target-resize.html @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + +
+
+
+ + + + diff --git a/test/fixtures/wpt/versions.json b/test/fixtures/wpt/versions.json index e55319b60334c7..3edb1453e7488e 100644 --- a/test/fixtures/wpt/versions.json +++ b/test/fixtures/wpt/versions.json @@ -16,7 +16,7 @@ "path": "dom/abort" }, "dom/events": { - "commit": "ab8999891c6225bef1741c2960033aad620481a8", + "commit": "0a811c51619b14f78fec60ba7dd1603795ca6a21", "path": "dom/events" }, "encoding": {