test_smooth_scroll_preference.html (5059B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Tests for smooth scroll preferences changes triggered by prefers-reduced-motion setting</title> 6 <script src="/tests/SimpleTest/SimpleTest.js"></script> 7 <script type="text/javascript" src="/tests/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js"></script> 8 <script type="text/javascript" src="/tests/gfx/layers/apz/test/mochitest/apz_test_utils.js"></script> 9 <link rel="stylesheet" href="/tests/SimpleTest/test.css"/> 10 <style> 11 .spacer { 12 height: 500vh; 13 } 14 </style> 15 </head> 16 <body> 17 <p id="display"></p> 18 <div id="content" style="display: none"></div> 19 <pre id="test"></pre> 20 <div class="spacer"></div> 21 <script> 22 async function changePrefersReducedMotion(aValue) { 23 const uiPrefChangedPromise = new Promise(resolve => { 24 SpecialPowers.addAsyncObserver(function LookAndFeelChanged() { 25 SpecialPowers.removeAsyncObserver(LookAndFeelChanged, "look-and-feel-changed"); 26 resolve(); 27 }, "look-and-feel-changed"); 28 }); 29 30 await SpecialPowers.pushPrefEnv({ 31 set: [["ui.prefersReducedMotion", aValue]], 32 }); 33 await uiPrefChangedPromise; 34 35 // NOTE: Changing "ui.prefersReducedMotion" takes some amount of time for 36 // some reasons, without this `promiseWaitForCondition` 37 // `SpecialPowers.getBoolPref("general.smoothScroll")` checks in this test 38 // intermittently fail specifically in verify runs. 39 await SimpleTest.promiseWaitForCondition(() => 40 SpecialPowers.getIntPref("ui.prefersReducedMotion") == aValue, ""); 41 // Give a chance to reflect the "ui.prefersReducedMotion" change to 42 // "general.smoothScroll". 43 await new Promise(resolve => requestAnimationFrame(resolve)); 44 } 45 46 add_setup(async () => { 47 if (SpecialPowers.Services.prefs.prefHasUserValue("general.smoothScroll")) { 48 const original = SpecialPowers.getBoolPref("general.smoothScroll"); 49 await SpecialPowers.clearUserPref("general.smoothScroll"); 50 // Restore the original value when this test finished. 51 SimpleTest.registerCleanupFunction(async () => { 52 await SpecialPowers.setBoolPref("general.smoothScroll", original); 53 }); 54 } 55 56 // Clear out `ui.prefersReducedMotion`. 57 await SpecialPowers.pushPrefEnv({ 58 clear: [["ui.prefersReducedMotion"]], 59 }); 60 61 SimpleTest.registerCleanupFunction(async () => { 62 await SpecialPowers.clearUserPref("ui.prefersReducedMotion"); 63 }); 64 65 await changePrefersReducedMotion(0); 66 }); 67 68 function promiseTwoScrollEvents(aTarget) { 69 return new Promise(resolve => { 70 let count = 0; 71 const listener = event => { 72 if (++count == 2) { 73 aTarget.removeEventListener("scroll", listener); 74 resolve(); 75 } 76 } 77 aTarget.addEventListener("scroll", listener); 78 }); 79 } 80 81 add_task(async () => { 82 // This test assumes that the default value of `general.smoothScroll` is 83 // true. 84 ok(SpecialPowers.getBoolPref("general.smoothScroll"), 85 "The default smoothScroll is true"); 86 87 // Do a smooth scroll operation. 88 let twoScrollEventsPromise = promiseTwoScrollEvents(window); 89 window.scrollBy({top: 500, behavior: "smooth"}); 90 await twoScrollEventsPromise; 91 92 // Clobber the smooth scrolling. 93 window.scrollTo({top: 0, behavior: "instant"}); 94 is(window.scrollY, 0); 95 96 // Set preferes-reduced-motion. 97 await changePrefersReducedMotion(1); 98 ok(!SpecialPowers.getBoolPref("general.smoothScroll"), 99 "The default smoothScroll is now false"); 100 101 // Do a smooth scroll operation, but it should be now instant. 102 let scrollEventPromise = promiseOneEvent(window, "scroll"); 103 window.scrollBy({top: 500, behavior: "smooth"}); 104 await scrollEventPromise; 105 // Allow 1px difference here since this test document gets loaded in an 106 // iframe and the top level content document doesn't have any meta viewport 107 // tag, thus this test document gets scaled down by < 1.0 value. 108 isfuzzy(window.scrollY, 500, 1); 109 110 // Reset the scroll position. 111 window.scrollTo({top: 0, behavior: "instant"}); 112 is(window.scrollY, 0); 113 114 // Disable preferes-reduced-motion. 115 await changePrefersReducedMotion(0); 116 ok(SpecialPowers.getBoolPref("general.smoothScroll"), 117 "The default smoothScroll is now true again"); 118 119 // Set `general.smoothScroll` to true. 120 await SpecialPowers.setBoolPref("general.smoothScroll", true); 121 await new Promise(resolve => requestAnimationFrame(resolve)); 122 123 // Do a smooth scroll operation. 124 twoScrollEventsPromise = promiseTwoScrollEvents(window); 125 window.scrollBy({top: 500, behavior: "smooth"}); 126 await twoScrollEventsPromise; 127 128 // Clobber the smooth scrolling. 129 window.scrollTo({top: 0, behavior: "instant"}); 130 is(window.scrollY, 0); 131 132 // Set preferes-reduced-motion again. 133 await changePrefersReducedMotion(1); 134 ok(SpecialPowers.getBoolPref("general.smoothScroll"), 135 "The default smoothScroll is no longer be able to be changed by prefers-reduced-motion"); 136 137 // Do a smooth scroll operation again, it should be smooth. 138 twoScrollEventsPromise = promiseTwoScrollEvents(window); 139 window.scrollBy({top: 500, behavior: "smooth"}); 140 await twoScrollEventsPromise; 141 }); 142 </script> 143 </body> 144 </html>