common.js (4729B)
1 function checkSnapEventSupport(event_type) { 2 if (event_type == "scrollsnapchange") { 3 assert_true(window.onscrollsnapchange !== undefined, "scrollsnapchange not supported"); 4 } else if (event_type == "scrollsnapchanging") { 5 assert_true(window.onscrollsnapchanging !== undefined, "scrollsnapchanging not supported"); 6 } else { 7 assert_unreached(`Unknown snap event type selected: ${event_type}`); 8 } 9 } 10 11 function assertSnapEvent(evt, expected_ids) { 12 assert_equals(evt.bubbles, evt.target == document, 13 "snap events don't bubble except when fired at the document"); 14 assert_false(evt.cancelable, "snap events are not cancelable."); 15 assert_equals(evt.snapTargetBlock, expected_ids.block, 16 "snap event supplied expected target in block axis"); 17 assert_equals(evt.snapTargetInline, expected_ids.inline, 18 "snap event supplied expected target in inline axis"); 19 } 20 21 async function snap_test_setup(test, scroller, event_type) { 22 checkSnapEventSupport(event_type); 23 await waitForScrollReset(test, scroller); 24 await waitForCompositorCommit(); 25 test.add_cleanup(async () => { 26 await waitForScrollReset(test, scroller); 27 }); 28 } 29 30 async function test_snap_event(test, test_data, event_type, 31 use_onsnap_member = false) { 32 await snap_test_setup(test, test_data.scroller, event_type); 33 34 let listener = test_data.scroller == 35 document.scrollingElement ? document : test_data.scroller; 36 37 const event_promise = waitForSnapEvent(listener, event_type, true, 38 use_onsnap_member); 39 await test_data.scrolling_function(); 40 let evt = await event_promise; 41 42 assertSnapEvent(evt, test_data.expected_snap_targets); 43 assert_approx_equals(test_data.scroller.scrollTop, 44 test_data.expected_scroll_offsets.y, 1, 45 "vertical scroll offset mismatch."); 46 assert_approx_equals(test_data.scroller.scrollLeft, 47 test_data.expected_scroll_offsets.x, 1, 48 "horizontal scroll offset mismatch."); 49 } 50 51 async function test_scrollsnapchange(test, test_data, use_onsnap_member = false) { 52 await test_snap_event(test, test_data, "scrollsnapchange", use_onsnap_member); 53 } 54 55 function waitForEventUntil(event_target, event_type, wait_until, 56 use_onsnap_member = false) { 57 return new Promise(resolve => { 58 let result = null; 59 const listener = (evt) => { 60 result = evt; 61 }; 62 if (use_onsnap_member) { 63 if (event_type === "scrollsnapchanging") { 64 event_target.onscrollsnapchanging = listener; 65 } else { 66 event_target.onscrollsnapchange = listener; 67 } 68 } else { 69 event_target.addEventListener(event_type, listener); 70 } 71 wait_until.then(() => { 72 if (use_onsnap_member) { 73 if (event_type === "scrollsnapchanging") { 74 event_target.onscrollsnapchanging = null; 75 } else { 76 event_target.onscrollsnapchange = null; 77 } 78 } else { 79 event_target.removeEventListener(event_type, listener); 80 } 81 resolve(result); 82 }); 83 }); 84 } 85 86 function waitForEventsUntil(event_target, event_type, wait_until) { 87 return new Promise(resolve => { 88 let result = []; 89 const listener = (evt) => { 90 result.push(evt); 91 }; 92 event_target.addEventListener(event_type, listener); 93 wait_until.then(() => { 94 event_target.removeEventListener(event_type, listener); 95 resolve(result); 96 }); 97 }); 98 } 99 100 // Proxy a wait for a snap event. We want to avoid having a test 101 // timeout in the event of an expected snap event not firing in a particular 102 // test case as that would cause the entire file to fail. 103 // Snap events should fire before scrollend, so if a scroll should happen, wait 104 // for a scrollend event. Otherwise, just do a rAF-based wait. 105 function waitForSnapEvent(event_target, event_type, scroll_happens = true, 106 use_onsnap_member = false) { 107 return scroll_happens ? waitForEventUntil(event_target, event_type, 108 waitForScrollendEventNoTimeout(event_target), 109 use_onsnap_member) 110 : waitForEventUntil(event_target, event_type, 111 waitForAnimationFrames(2), 112 use_onsnap_member); 113 } 114 115 function waitForScrollSnapChangeEvent(event_target, scroll_happens = true) { 116 return waitForSnapEvent(event_target, "scrollsnapchange", scroll_happens); 117 } 118 119 function getScrollbarToScrollerRatio(scroller) { 120 // Ideally we'd subtract the length of the scrollbar thumb from 121 // the dividend but there isn't currently a way to get the 122 // scrollbar thumb length. 123 return scroller.clientHeight / 124 (scroller.scrollHeight - scroller.clientHeight); 125 }