| function checkSnapEventSupport(event_type) { |
| if (event_type == "snapchanged") { |
| assert_true(window.onsnapchanged !== undefined, "snapchanged not supported"); |
| } else if (event_type == "snapchanging") { |
| assert_true(window.onsnapchanging !== undefined, "snapchanging not supported"); |
| } else { |
| assert_unreached(`Unknown snap event type selected: ${event_type}`); |
| } |
| } |
| |
| function assertSnapEvent(evt, expected_ids) { |
| assert_equals(evt.bubbles, false, "snap events don't bubble"); |
| assert_false(evt.cancelable, "snap events are not cancelable."); |
| assert_equals(evt.snapTargetBlock, expected_ids.block, |
| "snap event supplied expected target in block axis"); |
| assert_equals(evt.snapTargetInline, expected_ids.inline, |
| "snap event supplied expected target in inline axis"); |
| } |
| |
| async function snap_test_setup(test, scroller, event_type) { |
| checkSnapEventSupport(event_type); |
| await waitForScrollReset(test, scroller); |
| await waitForCompositorCommit(); |
| test.add_cleanup(async () => { |
| await waitForScrollReset(test, scroller); |
| }); |
| } |
| |
| async function test_snap_event(test, test_data, event_type, |
| use_onsnap_member = false) { |
| await snap_test_setup(test, test_data.scroller, event_type); |
| |
| let listener = test_data.scroller == |
| document.scrollingElement ? document : test_data.scroller; |
| |
| const event_promise = waitForSnapEvent(listener, event_type, true, |
| use_onsnap_member); |
| await test_data.scrolling_function(); |
| let evt = await event_promise; |
| |
| assertSnapEvent(evt, test_data.expected_snap_targets); |
| assert_approx_equals(test_data.scroller.scrollTop, |
| test_data.expected_scroll_offsets.y, 1, |
| "vertical scroll offset mismatch."); |
| assert_approx_equals(test_data.scroller.scrollLeft, |
| test_data.expected_scroll_offsets.x, 1, |
| "horizontal scroll offset mismatch."); |
| } |
| |
| async function test_snapchanged(test, test_data, use_onsnap_member = false) { |
| await test_snap_event(test, test_data, "snapchanged", use_onsnap_member); |
| } |
| |
| function waitForEventUntil(event_target, event_type, wait_until, |
| use_onsnap_member = false) { |
| return new Promise(resolve => { |
| let result = null; |
| const listener = (evt) => { |
| result = evt; |
| }; |
| if (use_onsnap_member) { |
| if (event_type === "snapchanging") { |
| event_target.onsnapchanging = listener; |
| } else { |
| event_target.onsnapchanged = listener; |
| } |
| } else { |
| event_target.addEventListener(event_type, listener); |
| } |
| wait_until.then(() => { |
| if (use_onsnap_member) { |
| if (event_type === "snapchanging") { |
| event_target.onsnapchanging = null; |
| } else { |
| event_target.onsnapchanged = null; |
| } |
| } else { |
| event_target.removeEventListener(event_type, listener); |
| } |
| resolve(result); |
| }); |
| }); |
| } |
| |
| function waitForEventsUntil(event_target, event_type, wait_until) { |
| return new Promise(resolve => { |
| let result = []; |
| const listener = (evt) => { |
| result.push(evt); |
| }; |
| event_target.addEventListener(event_type, listener); |
| wait_until.then(() => { |
| event_target.removeEventListener(event_type, listener); |
| resolve(result); |
| }); |
| }); |
| } |
| |
| // Proxy a wait for a snap event. We want to avoid having a test |
| // timeout in the event of an expected snap event not firing in a particular |
| // test case as that would cause the entire file to fail. |
| // Snap events should fire before scrollend, so if a scroll should happen, wait |
| // for a scrollend event. Otherwise, just do a rAF-based wait. |
| function waitForSnapEvent(event_target, event_type, scroll_happens = true, |
| use_onsnap_member = false) { |
| return scroll_happens ? waitForEventUntil(event_target, event_type, |
| waitForScrollendEventNoTimeout(event_target), |
| use_onsnap_member) |
| : waitForEventUntil(event_target, event_type, |
| waitForAnimationFrames(2), |
| use_onsnap_member); |
| } |
| |
| function waitForSnapChangedEvent(event_target, scroll_happens = true) { |
| return waitForSnapEvent(event_target, "snapchanged", scroll_happens); |
| } |
| |
| function getScrollbarToScrollerRatio(scroller) { |
| // Ideally we'd subtract the length of the scrollbar thumb from |
| // the dividend but there isn't currently a way to get the |
| // scrollbar thumb length. |
| return scroller.clientHeight / |
| (scroller.scrollHeight - scroller.clientHeight); |
| } |