summaryrefslogtreecommitdiffstats
path: root/layout/base/tests/test_scroll_per_page.html
diff options
context:
space:
mode:
Diffstat (limited to 'layout/base/tests/test_scroll_per_page.html')
-rw-r--r--layout/base/tests/test_scroll_per_page.html247
1 files changed, 247 insertions, 0 deletions
diff --git a/layout/base/tests/test_scroll_per_page.html b/layout/base/tests/test_scroll_per_page.html
new file mode 100644
index 0000000000..dc8faef893
--- /dev/null
+++ b/layout/base/tests/test_scroll_per_page.html
@@ -0,0 +1,247 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Test for scroll per page</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="/tests/gfx/layers/apz/test/mochitest/apz_test_utils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(() => {
+ open("window_empty_document.html", "_blank", "width=500,height=500,scrollbars=yes");
+});
+
+async function doTests(aWindow) {
+ const IS_WIN = navigator.platform.includes("Win");
+ // On macOS and Linux, PageUp/PageDown requires native event to resolve
+ // default action of PageDown and PageUp. Although macOS widget has
+ // nsIWidget::AttachNativeKeyEvent(), we cannot use synthesizeKey() for the
+ // following tests. So, use nsISelectionController.pageMove() instead on
+ // non-Windows platforms.
+ const kUseKeyboardEvent = IS_WIN;
+ let selectionController;
+ if (!kUseKeyboardEvent) {
+ selectionController = SpecialPowers.wrap(aWindow)
+ .docShell
+ .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
+ .getInterface(SpecialPowers.Ci.nsISelectionDisplay)
+ .QueryInterface(SpecialPowers.Ci.nsISelectionController);
+ }
+
+ await SpecialPowers.pushPrefEnv({"set": [["general.smoothScroll", false]]});
+ await SimpleTest.promiseFocus(aWindow);
+
+ function getNodeDescription(aNode) {
+ function getElementDescription(aElement) {
+ if (aElement.getAttribute("id") !== null) {
+ return `${aElement.tagName.toLowerCase()}#${aElement.getAttribute("id")}`;
+ }
+ if (aElement.tagName === "BR") {
+ return `${getElementDescription(aElement.previousSibling)} + br`;
+ }
+ return aElement.tagName.toLowerCase();
+ }
+ switch (aNode.nodeType) {
+ case aNode.TEXT_NODE:
+ return `text node in ${getElementDescription(aNode.parentElement)}`;
+ case aNode.ELEMENT_NODE:
+ return getElementDescription(aNode);
+ default:
+ return "unknown node";
+ }
+ }
+
+ function waitForScrollEvent() {
+ return new Promise(resolve => {
+ aWindow.addEventListener("scroll", () => { SimpleTest.executeSoon(resolve); }, {once: true, capture: true});
+ });
+ }
+
+ async function doPageDown() {
+ let waitForScrolling = waitForScrollEvent();
+ if (kUseKeyboardEvent) {
+ synthesizeKey("KEY_PageDown", {}, aWindow);
+ } else {
+ selectionController.pageMove(true, false);
+ }
+ await waitForScrolling;
+ }
+
+ async function doPageUp() {
+ let waitForScrolling = waitForScrollEvent();
+ if (kUseKeyboardEvent) {
+ synthesizeKey("KEY_PageUp", {}, aWindow);
+ } else {
+ selectionController.pageMove(false, false);
+ }
+ await waitForScrolling;
+ }
+
+ let doc = aWindow.document;
+ let body = doc.body;
+ let selection = doc.getSelection();
+ let container;
+
+ body.innerHTML = '<div id="largeDiv" style="height: 1500px;">' +
+ "<p>previous line of the editor.</p>" +
+ '<div id="editor" contenteditable style="margin-top 500px; height: 5em; overflow: auto;">' +
+ "Here is first line<br>" +
+ "Here is second line" +
+ "</div>" +
+ "<p>next line of the editor.</p>" +
+ "</div>";
+ container = doc.documentElement;
+ let editor = doc.getElementById("editor");
+ editor.focus();
+ await waitToClearOutAnyPotentialScrolls(aWindow);
+
+ let description = "PageDown in non-scrollable editing host: ";
+ let previousScrollTop = container.scrollTop;
+ await doPageDown();
+ ok(container.scrollTop > previousScrollTop,
+ `${description}the document should be scrolled down even if user presses PageDown in the editing host got: ${container.scrollTop}, previous position: ${previousScrollTop}`);
+ let range = selection.getRangeAt(0);
+ is(range.startContainer, editor.firstChild.nextSibling.nextSibling,
+ `${description}selection start shouldn't be moved to outside of the editing host (got: ${getNodeDescription(range.startContainer)})`);
+ ok(range.collapsed, description + "selection should be collapsed");
+ is(doc.activeElement, editor,
+ description + "the editing host should keep having focus");
+
+ description = "PageUp in non-scrollable editing host: ";
+ previousScrollTop = container.scrollTop;
+ await doPageUp();
+ ok(container.scrollTop < previousScrollTop,
+ `${description}the document should be scrolled up even if user presses PageDown in the editing host got: ${container.scrollTop}, previous position: ${previousScrollTop}`);
+ range = selection.getRangeAt(0);
+ is(range.startContainer, editor.firstChild,
+ `${description}selection start shouldn't be moved to outside of the editing host (got: ${getNodeDescription(range.startContainer)})`);
+ ok(range.collapsed, description + "selection should be collapsed");
+ is(doc.activeElement, editor,
+ description + "the editing host should keep having focus");
+
+ body.innerHTML = '<div id="largeDiv" style="height: 1500px;">' +
+ "<p>previous line of the editor.</p>" +
+ '<div id="editor" contenteditable style="margin-top 500px; height: 5em; overflow: auto;">' +
+ '<div id="innerDiv" style="height: 10em;">' +
+ "Here is first line<br>" +
+ "Here is second line" +
+ "</div>" +
+ "</div>" +
+ "<p>next line of the editor.</p>" +
+ "</div>";
+ editor = doc.getElementById("editor");
+ container = editor;
+ editor.focus();
+ await waitToClearOutAnyPotentialScrolls(aWindow);
+
+ description = "PageDown in scrollable editing host: ";
+ previousScrollTop = container.scrollTop;
+ await doPageDown();
+ ok(container.scrollTop > previousScrollTop,
+ `${description}the editor should be scrolled down even if user presses PageDown in the editing host got: ${container.scrollTop}, previous position: ${previousScrollTop}`);
+ range = selection.getRangeAt(0);
+ is(range.startContainer, editor.firstChild.firstChild.nextSibling.nextSibling,
+ `${description}selection start shouldn't be moved to outside of the editing host (got: ${getNodeDescription(range.startContainer)})`);
+ ok(range.collapsed, description + "selection should be collapsed");
+ is(doc.activeElement, editor,
+ description + "the editing host should keep having focus");
+
+ description = "PageUp in scrollable editing host: ";
+ previousScrollTop = container.scrollTop;
+ await doPageUp();
+ ok(container.scrollTop < previousScrollTop,
+ `${description}the editor should be scrolled up even if user presses PageDown in the editing host got: ${container.scrollTop}, previous position: ${previousScrollTop}`);
+ range = selection.getRangeAt(0);
+ is(range.startContainer, editor.firstChild.firstChild,
+ `${description}selection start shouldn't be moved to outside of the editing host (got: ${getNodeDescription(range.startContainer)})`);
+ ok(range.collapsed, description + "selection should be collapsed");
+ is(doc.activeElement, editor,
+ description + "the editing host should keep having focus");
+
+ // Should scroll one page of the scrollable element
+ body.innerHTML = `<div id="editor" contenteditable style="height: 1500px;">${"abc<br>".repeat(100)}</div>`;
+ editor = doc.getElementById("editor");
+ container = doc.documentElement;
+ editor.focus();
+ await waitToClearOutAnyPotentialScrolls(aWindow);
+
+ description = "PageDown in too large editing host: ";
+ previousScrollTop = container.scrollTop;
+ await doPageDown();
+ ok(container.scrollTop > previousScrollTop,
+ `${description} The document should be scrolled down (got: ${container.scrollTop}, previous position: ${previousScrollTop})`);
+ ok(container.scrollTop <= previousScrollTop + container.clientHeight,
+ `${description} The document should not be scrolled down too much (got: ${container.scrollTop}, previous position: ${previousScrollTop}, scroll height: ${container.clientHeight})`);
+
+ selection.selectAllChildren(editor);
+ selection.collapseToEnd();
+ await waitToClearOutAnyPotentialScrolls(aWindow);
+
+ description = "PageUp in too large editing host: ";
+ container.scrollTop = container.scrollHeight;
+ previousScrollTop = container.scrollTop;
+ await doPageUp();
+ ok(container.scrollTop >= previousScrollTop - container.clientHeight,
+ `${description} The document should not be scrolled up too much (got: ${container.scrollTop}, previous position: ${previousScrollTop}, scroll height: ${container.clientHeight})`);
+
+ // Shouldn't scroll to caret position after pagedown scrolls editing host.
+ body.innerHTML = '<div id="editor" contenteditable style="height: 300px; overflow: auto;"><div style="height: 1500px;">abc<br>def<br></div></div>';
+ editor = doc.getElementById("editor");
+ container = editor;
+ editor.focus();
+ await waitToClearOutAnyPotentialScrolls(aWindow);
+
+ description = "PageDown in scrollable editing host";
+ previousScrollTop = container.scrollTop;
+ await doPageDown();
+ ok(container.scrollTop > previousScrollTop,
+ `${description} #1: Should be scrolled down (got: ${container.scrollTop}, previous position: ${previousScrollTop})`);
+ previousScrollTop = container.scrollTop;
+ await doPageDown();
+ ok(container.scrollTop > previousScrollTop,
+ `${description} #2: should be scrolled down (got:${container.scrollTop}, previous position: ${previousScrollTop})`);
+ previousScrollTop = container.scrollTop;
+ await doPageDown();
+ ok(container.scrollTop > previousScrollTop,
+ `${description} #3: should be scrolled down (got:${container.scrollTop}, previous position: ${previousScrollTop})`);
+ await doPageUp();
+ ok(container.scrollTop < 300,
+ `PageUp in scrollable editing host after scrolled down 3 pages: should be scrolled up to show caret (got:${container.scrollTop}`);
+
+ // Shouldn't scroll to caret position after pagedown scrolls outside of editing host.
+ // NOTE: We've set the window height is 500px above, but on Android, the viewport size depends on the screen size.
+ // Therefore, we need to compute enough height to test below with actual height of the window.
+ body.innerHTML = `<div id="editor" contenteditable style="height: ${aWindow.innerHeight * 3}px">abc<br>def<br></div>`;
+ editor = doc.getElementById("editor");
+ container = doc.documentElement;
+ editor.focus();
+ selection.collapse(editor.firstChild);
+ await waitToClearOutAnyPotentialScrolls(aWindow);
+
+ description = "PageDown in too high non-scrollable editing host";
+ previousScrollTop = container.scrollTop;
+ await doPageDown();
+ ok(container.scrollTop > previousScrollTop,
+ `${description} #1: Should be scrolled down (got: ${container.scrollTop}, previous position: ${previousScrollTop})`);
+ previousScrollTop = container.scrollTop;
+ await doPageDown();
+ ok(container.scrollTop > previousScrollTop,
+ `${description} #2: should be scrolled down (got:${container.scrollTop}, previous position: ${previousScrollTop})`);
+ previousScrollTop = container.scrollTop;
+ await doPageDown();
+ ok(container.scrollTop > previousScrollTop,
+ `${description} #3: should be scrolled down (got:${container.scrollTop}, previous position: ${previousScrollTop})`);
+ await doPageUp();
+ ok(container.scrollTop < 300,
+ `PageUp in too high non-scrollable editing host after scrolled down 3 pages: should be scrolled up to show caret (got:${container.scrollTop}`);
+
+ aWindow.close();
+ SimpleTest.finish();
+}
+</script>
+</html>