test_wheel_transactions.html (5393B)
1 <!DOCTYPE HTML> 2 <html> 3 <!-- 4 https://bugzilla.mozilla.org/show_bug.cgi?id=1175585 5 --> 6 <head> 7 <title>Test for Bug 1175585</title> 8 <script src="/tests/SimpleTest/SimpleTest.js"></script> 9 <script src="/tests/SimpleTest/EventUtils.js"></script> 10 <script src="/tests/SimpleTest/paint_listener.js"></script> 11 <script type="application/javascript" src="apz_test_native_event_utils.js"></script> 12 <script type="application/javascript" src="apz_test_utils.js"></script> 13 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> 14 <style> 15 #outer-frame { 16 height: 500px; 17 overflow: scroll; 18 background: repeating-linear-gradient(#CCC, #CCC 100px, #BBB 100px, #BBB 200px); 19 } 20 #inner-frame { 21 margin-top: 25%; 22 height: 200%; 23 width: 75%; 24 overflow: scroll; 25 } 26 #inner-content { 27 height: 200%; 28 width: 200%; 29 background: repeating-linear-gradient(#EEE, #EEE 100px, #DDD 100px, #DDD 200px); 30 } 31 </style> 32 </head> 33 <body> 34 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1175585">APZ wheel transactions test</a> 35 <p id="display"></p> 36 <div id="outer-frame"> 37 <div id="inner-frame"> 38 <div id="inner-content"></div> 39 </div> 40 </div> 41 <pre id="test"> 42 <script type="application/javascript"> 43 44 async function scrollWheelOver(element, deltaY) { 45 await promiseNativeWheelAndWaitForScrollEvent(element, 10, 10, 0, deltaY); 46 } 47 48 async function test() { 49 var outer = document.getElementById("outer-frame"); 50 var inner = document.getElementById("inner-frame"); 51 52 // Register a wheel event listener that records the target of 53 // the last wheel event, so that we can make assertions about it. 54 let lastWheelTarget; 55 let firstWheelTarget; 56 let wheelEventOccurred = false; 57 var wheelTargetRecorder = function(e) { 58 if (!wheelEventOccurred) { 59 firstWheelTarget = e.target; 60 wheelEventOccurred = true; 61 } 62 lastWheelTarget = e.target; 63 }; 64 window.addEventListener("wheel", wheelTargetRecorder); 65 66 // Scroll |outer| to the bottom. 67 while (outer.scrollTop < outer.scrollTopMax) { 68 await scrollWheelOver(outer, -10); 69 } 70 71 is(lastWheelTarget, firstWheelTarget, 72 "target " + lastWheelTarget.id + " should be " + lastWheelTarget.id); 73 window.removeEventListener("wheel", wheelTargetRecorder); 74 75 // Immediately after, scroll it back up a bit. 76 await scrollWheelOver(outer, 10); 77 78 // Check that it was |outer| that scrolled back, and |inner| didn't 79 // scroll at all, as all the above scrolls should be in the same 80 // transaction. 81 ok(outer.scrollTop < outer.scrollTopMax, "'outer' should have scrolled back a bit"); 82 is(inner.scrollTop, 0, "'inner' should not have scrolled"); 83 84 // The next part of the test is related to the transaction timeout. 85 // Turn it down a bit so waiting for the timeout to elapse doesn't 86 // slow down the test harness too much. 87 var timeout = 5; 88 await SpecialPowers.pushPrefEnv({"set": [["mousewheel.transaction.timeout", timeout]]}); 89 SimpleTest.requestFlakyTimeout("we are testing code that measures actual elapsed time between two events"); 90 91 // Scroll up a bit more. It's still |outer| scrolling because 92 // |inner| is still scrolled all the way to the top. 93 await scrollWheelOver(outer, 10); 94 95 // Wait for the transaction timeout to elapse. 96 // timeout * 5 is used to make it less likely that the timeout is less than 97 // the system timestamp resolution 98 await SpecialPowers.promiseTimeout(timeout * 5); 99 100 // Now scroll down. The transaction having timed out, the event 101 // should pick up a new target, and that should be |inner|. 102 await scrollWheelOver(outer, -10); 103 ok(inner.scrollTop > 0, "'inner' should have been scrolled"); 104 105 // Finally, test scroll handoff after a timeout. 106 107 // Continue scrolling |inner| down to the bottom. 108 var prevScrollTop = inner.scrollTop; 109 while (inner.scrollTop < inner.scrollTopMax) { 110 await scrollWheelOver(outer, -10); 111 // Avoid a failure getting us into an infinite loop. 112 ok(inner.scrollTop > prevScrollTop, "scrolling down should increase scrollTop"); 113 prevScrollTop = inner.scrollTop; 114 } 115 116 // Wait for the transaction timeout to elapse. 117 // timeout * 5 is used to make it less likely that the timeout is less than 118 // the system timestamp resolution 119 await SpecialPowers.promiseTimeout(timeout * 5); 120 121 // Continued downward scrolling should scroll |outer| to the bottom. 122 prevScrollTop = outer.scrollTop; 123 while (outer.scrollTop < outer.scrollTopMax) { 124 await scrollWheelOver(outer, -10); 125 // Avoid a failure getting us into an infinite loop. 126 ok(outer.scrollTop > prevScrollTop, "scrolling down should increase scrollTop"); 127 prevScrollTop = outer.scrollTop; 128 } 129 } 130 131 SimpleTest.waitForExplicitFinish(); 132 133 // Disable smooth scrolling because it makes the test flaky (we don't have a good 134 // way of detecting when the scrolling is finished). 135 // Also, on macOS, force the native events to be wheel inputs rather than pan 136 // inputs since this test is specifically testing things related to wheel 137 // transactions. 138 pushPrefs([["general.smoothScroll", false], 139 ["apz.test.mac.synth_wheel_input", true], 140 ["mousewheel.transaction.timeout", 1500], 141 ["dom.event.wheel-event-groups.enabled", true]]) 142 .then(waitUntilApzStable) 143 .then(test) 144 .then(SimpleTest.finish, SimpleTest.finishWithFailure); 145 146 </script> 147 </pre> 148 149 </body> 150 </html>