summaryrefslogtreecommitdiffstats
path: root/dom/events/test/test_scroll_per_page.html
diff options
context:
space:
mode:
Diffstat (limited to 'dom/events/test/test_scroll_per_page.html')
-rw-r--r--dom/events/test/test_scroll_per_page.html259
1 files changed, 259 insertions, 0 deletions
diff --git a/dom/events/test/test_scroll_per_page.html b/dom/events/test/test_scroll_per_page.html
new file mode 100644
index 0000000000..8d464b1a43
--- /dev/null
+++ b/dom/events/test/test_scroll_per_page.html
@@ -0,0 +1,259 @@
+<!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) {
+ 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);
+ case aNode.DOCUMENT_NODE:
+ return `document node`;
+ default:
+ return "unknown node";
+ }
+ }
+
+ function getScrollPositionStr(aNode) {
+ return `{ scrollTop: ${aNode.scrollTop}, scrollHeight: ${
+ aNode.scrollHeight
+ }, scrollLeft: ${aNode.scrollLeft}, scrollWidth: ${aNode.scrollWidth} }`;
+ }
+
+ async function doPageDownOrUp(aKey, aFocusedElement, aScrollTargetElement) {
+ let scrollEventTarget =
+ aScrollTargetElement === doc.documentElement
+ ? doc
+ : aScrollTargetElement;
+ let scrollEventFired = false;
+ function onScroll(aEvent) {
+ scrollEventFired |= aEvent.target === scrollEventTarget;
+ }
+ scrollEventTarget.addEventListener("scroll", onScroll);
+ if (!navigator.platform.includes("Mac")) {
+ synthesizeKey(`KEY_${aKey}`, {}, aWindow);
+ } else {
+ synthesizeKey(`KEY_${aKey}`, { altKey: true }, aWindow);
+ }
+ let retry = 3;
+ while (retry--) {
+ await waitToClearOutAnyPotentialScrolls(aWindow);
+ if (scrollEventFired) {
+ break;
+ }
+ }
+ ok(scrollEventFired,
+ `Scroll event should've been fired on ${getNodeDescription(scrollEventTarget)}`);
+ scrollEventTarget.removeEventListener("scroll", onScroll);
+ }
+
+ async function doPageDown(aFocusedElement, aScrollTargetElement) {
+ await doPageDownOrUp("PageDown", aFocusedElement, aScrollTargetElement);
+ }
+
+ async function doPageUp(aFocusedElement, aScrollTargetElement) {
+ await doPageDownOrUp("PageUp", aFocusedElement, aScrollTargetElement);
+ }
+
+ // Let's put log of scroll events for making debug this test easier.
+ aWindow.addEventListener("scroll", (aEvent) => {
+ let scrollElement =
+ aEvent.target === doc
+ ? doc.documentElement
+ : aEvent.target;
+ info(`"scroll" event fired on ${getNodeDescription(aEvent.target)}: ${
+ getScrollPositionStr(scrollElement)
+ }`);
+ }, { capture: true });
+
+ 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(editor, container);
+ 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(editor, container);
+ 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(editor, container);
+ 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(editor, container);
+ 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(editor, container);
+ 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(editor, container);
+ 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(editor, container);
+ ok(container.scrollTop > previousScrollTop,
+ `${description} #1: Should be scrolled down (got: ${container.scrollTop}, previous position: ${previousScrollTop})`);
+ previousScrollTop = container.scrollTop;
+ await doPageDown(editor, container);
+ ok(container.scrollTop > previousScrollTop,
+ `${description} #2: should be scrolled down (got:${container.scrollTop}, previous position: ${previousScrollTop})`);
+ previousScrollTop = container.scrollTop;
+ await doPageDown(editor, container);
+ ok(container.scrollTop > previousScrollTop,
+ `${description} #3: should be scrolled down (got:${container.scrollTop}, previous position: ${previousScrollTop})`);
+ await doPageUp(editor, container);
+ 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(editor, container);
+ ok(container.scrollTop > previousScrollTop,
+ `${description} #1: Should be scrolled down (got: ${container.scrollTop}, previous position: ${previousScrollTop})`);
+ previousScrollTop = container.scrollTop;
+ await doPageDown(editor, container);
+ ok(container.scrollTop > previousScrollTop,
+ `${description} #2: should be scrolled down (got:${container.scrollTop}, previous position: ${previousScrollTop})`);
+ previousScrollTop = container.scrollTop;
+ await doPageDown(editor, container);
+ ok(container.scrollTop > previousScrollTop,
+ `${description} #3: should be scrolled down (got:${container.scrollTop}, previous position: ${previousScrollTop})`);
+ await doPageUp(editor, container);
+ 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>