keyboard-scroll.html (3420B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <title>Keyboard scrolling targets the last clicked element</title> 4 <link rel="help" href=""> 5 <link rel="author" href="flackr@chromium.org"> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 <script src="/resources/testdriver.js"></script> 9 <script src="/resources/testdriver-vendor.js"></script> 10 <script src="/resources/testdriver-actions.js"></script> 11 <script src="/css/css-scroll-snap/support/common.js"></script> 12 <script src="/dom/events/scrolling/scroll_support.js"></script> 13 <style> 14 .scroller { 15 overflow: auto; 16 height: 200px; 17 border: 1px solid black; 18 } 19 .spacer { 20 height: 200vh; 21 } 22 </style> 23 <body id="body"> 24 <div class="scroller" id="outer"> 25 <div class="scroller" id="inner"> 26 <div id="target"><span>This is the targeted node</span></div> 27 <div class="spacer"></div> 28 </div> 29 <div class="spacer"></div> 30 </div> 31 <div class="spacer"></div> 32 </body> 33 <script> 34 35 const target = document.getElementById("target"); 36 const outer = document.getElementById("outer"); 37 const inner = document.getElementById("inner"); 38 const scrollTargets = [document, outer, inner]; 39 40 function raf() { 41 return new Promise((resolve) => { 42 requestAnimationFrame(resolve); 43 }); 44 } 45 46 async function getKeyboardScrollingElement(test, clickTarget, onclick) { 47 const click_promise = waitForEvent("click", test, clickTarget); 48 await test_driver.click(clickTarget); 49 await click_promise; 50 await onclick(); 51 await raf(); 52 const scrollEndPromise = waitForScrollEndFallbackToDelayWithoutScrollEvent(scrollTargets); 53 await keyPress(document.body, "ArrowDown"); 54 return scrollEndPromise; 55 } 56 57 function friendlyName(node) { 58 if (node == document) return "document"; 59 if (node.id) return `#${node.id}`; 60 return `<${node.tagName}>`; 61 } 62 63 async function resetScroll() { 64 for (const scrollTarget of scrollTargets) { 65 const scroller = scrollTarget.scrollingElement || scrollTarget; 66 scroller.scrollTo(0, 0); 67 } 68 return raf(); 69 } 70 71 promise_test(async (test) => { 72 test.add_cleanup(resetScroll); 73 const scrolled = await getKeyboardScrollingElement(test, target, async () => { 74 target.remove(); 75 test.add_cleanup(() => { 76 inner.insertBefore(target, inner.firstChild); 77 }); 78 }); 79 assert_equals(friendlyName(scrolled), "#inner"); 80 }, "Keyboard scrolling scrolls the scroller when clicked target is removed"); 81 82 // Notably removing all children is a different code path than removing 83 // a single child. This is a regression test for https://crbug.com/40941145. 84 promise_test(async (test) => { 85 test.add_cleanup(resetScroll); 86 const scrolled = await getKeyboardScrollingElement(test, target.firstElementChild, async () => { 87 const previous = target.innerHTML; 88 target.innerHTML = ""; 89 test.add_cleanup(() => { 90 target.innerHTML = previous; 91 }); 92 }); 93 assert_equals(friendlyName(scrolled), "#inner"); 94 }, "Keyboard scrolling scrolls the scroller when clicked children are removed"); 95 96 promise_test(async (test) => { 97 test.add_cleanup(resetScroll); 98 const scrolled = await getKeyboardScrollingElement(test, target, async () => { 99 inner.remove(); 100 test.add_cleanup(() => { 101 outer.insertBefore(inner, outer.firstChild); 102 }); 103 }); 104 assert_equals(friendlyName(scrolled), "#outer"); 105 }, "Keyboard scrolling scrolls the next nearest scroller if the clicked scroller is removed"); 106 107 </script>