helper_scrollbar_snap_bug1501062.html (5064B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <meta name="viewport" content="width=device-width; initial-scale=1.0"> 6 <title>Exercising the slider.snapMultiplier code</title> 7 <script type="application/javascript" src="apz_test_native_event_utils.js"></script> 8 <script type="application/javascript" src="apz_test_utils.js"></script> 9 <script src="/tests/SimpleTest/paint_listener.js"></script> 10 </head> 11 <body> 12 <div id="scrollable" style="width: 300px; height: 300px; overflow: auto"> 13 <div id="filler" style="height: 2000px; background-image: linear-gradient(red,blue)"></div> 14 </div> 15 </body> 16 <script type="text/javascript"> 17 async function test() { 18 // Note that this pref is a read-once-on-startup pref so we can't change it 19 // and have the change take effect. Instead we just use the value to determine 20 // what the expected behaviour is. 21 var snapMultiplier = SpecialPowers.getIntPref("slider.snapMultiplier"); 22 23 // Much of the code below is "inlined" from promiseVerticalScrollbarDrag. Reusing 24 // that code was nontrivial given the modifications we needed to make, and 25 // would have increased the complexity of that helper function more than I'd 26 // like. However if any bugfixes are made to that function this code might 27 // need to be updated as well. 28 29 var scrollableDiv = document.getElementById("scrollable"); 30 var boundingClientRect = scrollableDiv.getBoundingClientRect(); 31 var verticalScrollbarWidth = boundingClientRect.width - scrollableDiv.clientWidth; 32 if (verticalScrollbarWidth == 0) { 33 ok(true, "No scrollbar, can't do this test"); 34 return; 35 } 36 37 // register a scroll listener for the initial drag 38 let scrollPromise = new Promise(resolve => { 39 scrollableDiv.addEventListener("scroll", resolve, {once: true}); 40 }); 41 42 var upArrowHeight = verticalScrollbarWidth; // assume square scrollbar buttons 43 var mouseX = scrollableDiv.clientWidth + (verticalScrollbarWidth / 2); 44 var mouseY = upArrowHeight + 5; // start dragging somewhere in the thumb 45 46 dump("Starting drag at " + mouseX + ", " + mouseY + " from top-left of #" + scrollableDiv.id + "\n"); 47 48 // Move the mouse to the scrollbar thumb and drag it down 49 await promiseNativeMouseEventWithAPZ({ 50 target: scrollableDiv, 51 offsetX: mouseX, 52 offsetY: mouseY, 53 type: "mousemove", 54 }); 55 await promiseNativeMouseEventWithAPZ({ 56 target: scrollableDiv, 57 offsetX: mouseX, 58 offsetY: mouseY, 59 type: "mousedown", 60 }); 61 // drag down by 100 pixels 62 mouseY += 100; 63 await promiseNativeMouseEventWithAPZ({ 64 target: scrollableDiv, 65 offsetX: mouseX, 66 offsetY: mouseY, 67 type: "mousemove", 68 }); 69 70 // wait here until the scroll event listener is triggered. 71 await scrollPromise; 72 var savedScrollPos = scrollableDiv.scrollTop; 73 ok(savedScrollPos > 0, "Scrolled to " + savedScrollPos); 74 75 // register a new scroll event listener. The next mousemove below will either 76 // trigger the snapback behaviour (if snapMultiplier > 0) or trigger a vertical 77 // scroll (if snapMultiplier == 0) because of the x- and y-coordinates we move 78 // the mouse to. This allows us to wait for a scroll event in either case. 79 // If we only triggered the snapback case then waiting for the scroll to 80 // "not happen" in the other case would be more error-prone. 81 scrollPromise = new Promise(resolve => { 82 scrollableDiv.addEventListener("scroll", resolve, {once: true}); 83 }); 84 // Add 2 to snapMultipler just to make sure we get far enough away from the scrollbar 85 var snapBackDistance = (snapMultiplier + 2) * verticalScrollbarWidth; 86 await promiseNativeMouseEventWithAPZ({ 87 target: scrollableDiv, 88 offsetX: mouseX + snapBackDistance, 89 offsetY: mouseY + 10, 90 type: "mousemove", 91 }); 92 93 // wait here until the scroll happens 94 await scrollPromise; 95 if (snapMultiplier > 0) { 96 ok(scrollableDiv.scrollTop == 0, "Scroll position snapped back to " + scrollableDiv.scrollTop); 97 } else { 98 ok(scrollableDiv.scrollTop > savedScrollPos, "Scroll position increased to " + scrollableDiv.scrollTop); 99 } 100 101 // Now we move the mouse back to the old position to ensure the scroll position 102 // gets restored properly 103 scrollPromise = new Promise(resolve => { 104 scrollableDiv.addEventListener("scroll", resolve, {once: true}); 105 }); 106 await promiseNativeMouseEventWithAPZ({ 107 target: scrollableDiv, 108 offsetX: mouseX, 109 offsetY: mouseY, 110 type: "mousemove", 111 }); 112 113 // wait here until the scroll happens 114 await scrollPromise; 115 ok(scrollableDiv.scrollTop == savedScrollPos, "Scroll position was restored to " + scrollableDiv.scrollTop); 116 117 // Release mouse and ensure the scroll position stuck 118 await promiseNativeMouseEventWithAPZ({ 119 target: scrollableDiv, 120 offsetX: mouseX, 121 offsetY: mouseY, 122 type: "mouseup", 123 }); 124 // Flush everything just to be safe 125 await promiseOnlyApzControllerFlushed(); 126 127 ok(scrollableDiv.scrollTop == savedScrollPos, "Final scroll position was " + scrollableDiv.scrollTop); 128 } 129 130 waitUntilApzStable() 131 .then(test) 132 .then(subtestDone, subtestFailed); 133 134 </script> 135 </html>