test_page_scroll_overlap.html (7144B)
1 <!DOCTYPE html> 2 <head> 3 <title>Test for configurable scrolling overlap when scrolling by pages</title> 4 <script src="/tests/SimpleTest/SimpleTest.js"></script> 5 <script src="/tests/SimpleTest/EventUtils.js"></script> 6 <script type="text/javascript" src="/tests/gfx/layers/apz/test/mochitest/apz_test_utils.js"></script> 7 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"> 8 <style> 9 #myIframe { 10 width: 400px; 11 height: 300px; 12 } 13 </style> 14 </head> 15 <body> 16 <iframe id="myIframe"></iframe> 17 <script type="text/javascript"> 18 // This mochitest tests the behavior of two about:config prefs: 19 // toolkit.scrollbox.pagescroll.maxOverlapPercent 20 // toolkit.scrollbox.pagescroll.maxOverlapLines 21 // These prefs (added in bug 1783183) determine the amount of overlap between 22 // the old and new content in the scrollport when scrolling by pages, e.g. when 23 // a user presses PageDown or PageUp, or when we handle a call to 24 // window.scrollByPages(). 25 26 // Kick off the main test function when we've loaded: 27 SimpleTest.waitForExplicitFinish(); 28 addLoadEvent(() => { 29 doTests(); 30 }); 31 32 // constants: 33 const IFRAME_HEIGHT_IN_PX = 300; // Needs to match the style for #myIframe 34 const LINE_HEIGHT_IN_PX = 50; // Needs to match our chosen Ahem font-size below 35 const EPSILON_PER_LINE = 5; // see documentation 36 const IFRAME_SRCDOC = 37 "<!doctype html>\ 38 <meta charset='utf-8'>\ 39 <style>\ 40 :root{overflow:hidden;scroll-behavior:auto;\ 41 </style><div style='height:5000px;width:5000px'>"; 42 43 // This function sets the relevant about:config prefs to `pctVal` and 44 // `linesVal` and then checks that paging down (and later up) results in a 45 // scrollport that overlaps the previous scrollport by `expectedOverlapInPx`. 46 // 47 // Callers that are testing a line-count-based amount of overlap should pass 48 // `true` for useEpsilon, which then makes us expand the allowable overlap 49 // to `expectedOverlapInPx +/- (linesVal * EPSILON_PER_LINE)`. 50 async function testPrefVals(pctVal, linesVal, expectedOverlapInPx, useEpsilon) { 51 const win = myIframe.contentWindow; 52 const docElem = myIframe.contentDocument.documentElement; 53 54 // Define a convenience "is()" function that uses either is or isfuzzy 55 // depending on whether we're using an epsilon: 56 let myIs = function(actual, expected, message) { 57 if (useEpsilon) { 58 let epsilon = linesVal * EPSILON_PER_LINE; 59 isfuzzy(actual, expected, epsilon, message); 60 } else { 61 is(actual, expected, message); 62 } 63 }; 64 65 // Set the pref values: 66 let prefVals = []; 67 if (pctVal != null) { 68 prefVals.push(["toolkit.scrollbox.pagescroll.maxOverlapPercent", pctVal]); 69 } 70 if (linesVal != null) { 71 prefVals.push(["toolkit.scrollbox.pagescroll.maxOverlapLines", linesVal]); 72 } 73 await SpecialPowers.pushPrefEnv({"set": prefVals}); 74 75 // Scroll down by 1 page, and check that the overlap is what we expect: 76 let initialScrollY = docElem.scrollTop; 77 win.scrollByPages(1); 78 let deltaY = docElem.scrollTop - initialScrollY; 79 let overlapY = IFRAME_HEIGHT_IN_PX - deltaY; 80 myIs(overlapY, expectedOverlapInPx, 81 `Should get expected overlap, when paging down ` + 82 `with pref vals ${pctVal}% and ${linesVal}`); 83 84 // Now scroll up by 1 page (from the maximum scroll position), 85 // and check that the overlap is what we expect: 86 docElem.scrollTop = docElem.scrollTopMax; 87 initialScrollY = docElem.scrollTop; 88 win.scrollByPages(-1); 89 deltaY = initialScrollY - docElem.scrollTop; 90 overlapY = IFRAME_HEIGHT_IN_PX - deltaY; 91 myIs(overlapY, expectedOverlapInPx, 92 `Should get expected overlap, when paging up ` + 93 `with pref vals ${pctVal}% and ${linesVal}`); 94 95 // Undo our pref modifications: 96 await SpecialPowers.popPrefEnv(); 97 98 // Restore the initial scroll position to clean up after ourselves: 99 docElem.scrollTop = 0; 100 } 101 102 async function doTests() { 103 // Toggle a pref to avoid uninteresting off-by-1 test-failures on Android: 104 await SpecialPowers.pushPrefEnv({ 105 "set": [["layout.disable-pixel-alignment", true]] 106 }); 107 108 // Load a tall scrollable document in an iframe: 109 let iframeLoad = new Promise(resolve => { 110 myIframe.addEventListener("load", resolve, { once: true }); 111 }); 112 myIframe.srcdoc = IFRAME_SRCDOC; 113 await iframeLoad; 114 115 // Test pref-combinations that result in no overlap (0) between the old and 116 // new scroll positions. If either pref is 0 [or less than 0, which we clamp 117 // internally when using the pref value], then there should be no overlap. 118 await testPrefVals(0, 0, 0); 119 await testPrefVals(10, 0, 0); 120 await testPrefVals(100, 0, 0); 121 await testPrefVals(0, 10, 0); 122 await testPrefVals(-5, -5, 0); 123 await testPrefVals(-5, 9999, 0); 124 await testPrefVals(200, -5, 0); 125 126 // Test various percent values (with extremely high line-count values which 127 // makes the line count irrelevant, since we use whichever pref produces a 128 // smaller amount of overlap). Note that the iframe scrollport is 300px 129 // tall, so that's what the percent resolves against. 130 await testPrefVals(1, 9999, 3); // 1% of 300px is 3px 131 await testPrefVals(10, 9999, 30); // 10% of 300px is 30px 132 await testPrefVals(50, 9999, 150); // 50% of 300px is 150px 133 await testPrefVals(80, 9999, 240); // 80% of 300px is 240px 134 await testPrefVals(99, 9999, 240); // Values above 80% get clamped to 80%. 135 await testPrefVals(100, 9999, 240); // Values above 80% get clamped to 80%. 136 await testPrefVals(200, 9999, 240); // Values above 80% get clamped to 80%. 137 138 // Test various line-count pref values (with extremely high percent values, 139 // which makes the percent pref irrelevant, since we use whichever pref 140 // produces a smaller amount of overlap). Note that the "lines" here are 141 // sized using the font metrics of the iframe's root scroll frame, which uses 142 // the initial values for all of the CSS font properties. So our lines here 143 // have whatever line-height gets used for the default font at the default 144 // 16px font-size. (Unfortunately we can't force a more predictable font 145 // like Ahem here; even if we set that set on the root node, it doesn't 146 // affect the styles on the root scroll frame.) 147 // So: we set our expectations here by assuming that the lines are a little 148 // bit taller than the default font-size (16px), with a few pixels of epsilon 149 // (per line-height) to allow for platform differences. 150 await testPrefVals(200, 1, 18, true); // 1 line is roughly 18px tall 151 await testPrefVals(200, 2, 36, true); // 2 lines are roughly 36px tall 152 await testPrefVals(200, 10, 180, true); // 10 lines are roughly 180px tall 153 154 // Test some combinations where both prefs have intermediate values, where 155 // one or the other will "win" (with the lower pixel-value winning and 156 // establishing the expected amount of overlap): 157 // 10% of 300px is 30px, which is less than 5 lines (roughly 5*18 = 90px) 158 await testPrefVals(10, 5, 30); 159 // 20% of 300px is 60px, which is more than 2 lines (roughly 2*18 = 36px) 160 await testPrefVals(20, 2, 36, true); 161 // 50% of 300px is 150px, which is more than 5 lines (roughly 5*18 = 90px) 162 await testPrefVals(50, 5, 90, true); 163 164 SimpleTest.finish(); 165 } 166 </script>