summaryrefslogtreecommitdiffstats
path: root/dom/events/test/test_moving_and_expanding_selection_per_page.html
diff options
context:
space:
mode:
Diffstat (limited to 'dom/events/test/test_moving_and_expanding_selection_per_page.html')
-rw-r--r--dom/events/test/test_moving_and_expanding_selection_per_page.html353
1 files changed, 353 insertions, 0 deletions
diff --git a/dom/events/test/test_moving_and_expanding_selection_per_page.html b/dom/events/test/test_moving_and_expanding_selection_per_page.html
new file mode 100644
index 0000000000..cc4786235d
--- /dev/null
+++ b/dom/events/test/test_moving_and_expanding_selection_per_page.html
@@ -0,0 +1,353 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Test for expanding selection per page</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.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");
+});
+
+async function doTests(aWindow) {
+ // On macOS, there is no shortcut keys to extend selection per page.
+ // Therefore, we need to use nsISelectionController.pageMove() instead.
+ const kUseKeyboardEvent = !navigator.platform.includes("Mac");
+ let selectionController = SpecialPowers.wrap(aWindow)
+ .docShell
+ .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
+ .getInterface(SpecialPowers.Ci.nsISelectionDisplay)
+ .QueryInterface(SpecialPowers.Ci.nsISelectionController);
+ // On Windows, per-page selection to start or end expands selection to same
+ // column of first or last line. On the other platforms, it expands selection
+ // to start or end of first or last line.
+ const kSelectToStartOrEnd = !navigator.platform.includes("Win");
+
+ 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 doTest(aExpandSelection) {
+ // Note that when neither editor has focus nor in caret mode, key navigation
+ // does not call nsISelectionController::PageMove(). Therefore, in such
+ // cases, you need to call doPageDown() and doPageUp() with setting true
+ // to aUseSelectionController.
+ function doPageDown(aUseSelectionController) {
+ if (kUseKeyboardEvent && !aUseSelectionController) {
+ synthesizeKey("KEY_PageDown", {shiftKey: aExpandSelection}, aWindow);
+ } else {
+ selectionController.pageMove(true, aExpandSelection);
+ }
+ }
+
+ function doPageUp(aUseSelectionController) {
+ if (kUseKeyboardEvent && !aUseSelectionController) {
+ synthesizeKey("KEY_PageUp", {shiftKey: aExpandSelection}, aWindow);
+ } else {
+ selectionController.pageMove(false, aExpandSelection);
+ }
+ }
+
+ let doc = aWindow.document;
+ let body = doc.body;
+ let selection = doc.getSelection();
+ let container;
+
+ body.innerHTML = '<span id="s1">first line</span><br>' +
+ '<span id="s2">second line</span><br>' +
+ '<span id="s3">last line</span>';
+ container = doc.documentElement;
+
+ let description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to forward in non-scrollable body: `;
+ is(container.scrollTop, 0, description + "scrollTop should be 0 at initialization");
+ selection.collapse(doc.getElementById("s1").firstChild, 3);
+ doPageDown(!aExpandSelection);
+ is(container.scrollTop, 0, description + "this test shouldn't create scrollable document");
+ let range = selection.getRangeAt(0);
+ if (aExpandSelection) {
+ is(range.startContainer, doc.getElementById("s1").firstChild,
+ `${description} selection should be expanded from the first line (got: ${getNodeDescription(range.startContainer)})`);
+ is(range.startOffset, 3,
+ `${description} selection should be expanded from the first line's 3rd insertion point`);
+ } else {
+ ok(range.collapsed, `${description} selection should be collapsed`);
+ }
+ is(range.endContainer, doc.getElementById("s3").firstChild,
+ `${description} selection should be expanded into the last line (got: ${getNodeDescription(range.endContainer)})`);
+ if (kSelectToStartOrEnd) {
+ is(range.endOffset, range.endContainer.length,
+ `${description} selection should be expanded to end of the last line`);
+ } else {
+ isfuzzy(range.endOffset, 3, 2,
+ `${description} selection should be expanded to around the last line's 3rd insertion point`);
+ }
+
+ description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to backward in non-scrollable body: `;
+ selection.collapse(doc.getElementById("s3").firstChild, 3);
+ doPageUp(!aExpandSelection);
+ is(container.scrollTop, 0, description + "this test shouldn't create scrollable document");
+ range = selection.getRangeAt(0);
+ is(range.startContainer, doc.getElementById("s1").firstChild,
+ `${description} selection should be expanded into the first line (got: ${getNodeDescription(range.startContainer)})`);
+ if (kSelectToStartOrEnd) {
+ is(range.startOffset, 0,
+ `${description} selection should be expanded to start of the first line`);
+ } else {
+ isfuzzy(range.startOffset, 3, 2,
+ `${description} selection should be expanded to around the first line's 3rd insertion point`);
+ }
+ if (aExpandSelection) {
+ is(range.endContainer, doc.getElementById("s3").firstChild,
+ `${description} selection should be expanded from the last line (got: ${getNodeDescription(range.endContainer)})`);
+ is(range.endOffset, 3,
+ `${description} selection should be expanded from the last line's 3rd insertion point`);
+ } else {
+ ok(range.collapsed, `${description} selection should be collapsed`);
+ }
+
+ body.innerHTML = '<span id="s1">first line in the body</span>' +
+ '<div id="d1" style="height: 2em; line-height: 1em; overflow: auto;">' +
+ '<span id="s2">first line</span><br>' +
+ '<span id="s3">second line</span><br>' +
+ '<span id="s4">third line</span><br>' +
+ '<span id="s5">last line</span>' +
+ "</div>" +
+ '<span id="s6">last line in the body</span>';
+ container = doc.getElementById("d1");
+
+ description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to forward in scrollable area in the body: `;
+ is(container.scrollTop, 0, description + "scrollTop should be 0 at initialization");
+ selection.collapse(doc.getElementById("s2").firstChild, 3);
+ doPageDown(!aExpandSelection);
+ isnot(container.scrollTop, 0, description + "should be scrolled down");
+ range = selection.getRangeAt(0);
+ if (aExpandSelection) {
+ is(range.startContainer, doc.getElementById("s2").firstChild,
+ `${description} selection should be expanded from the first line (got: ${getNodeDescription(range.startContainer)})`);
+ is(range.startOffset, 3,
+ `${description} selection should be expanded from the first line's 3rd insertion point`);
+ } else {
+ ok(range.collapsed, `${description} selection should be collapsed`);
+ }
+ is(range.endContainer, doc.getElementById("s4").firstChild,
+ `${description} selection should be expanded into the 3rd line (got: ${getNodeDescription(range.endContainer)})`);
+ isfuzzy(range.endOffset, 3, 2,
+ `${description} selection should be expanded to around the 3rd line's 3rd insertion point`);
+
+ description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to backward in scrollable area in the body: `;
+ selection.collapse(doc.getElementById("s4").firstChild, 3);
+ let previousScrollTop = container.scrollTop;
+ doPageUp(!aExpandSelection);
+ ok(container.scrollTop < previousScrollTop, description + "should be scrolled up");
+ range = selection.getRangeAt(0);
+ is(range.startContainer, doc.getElementById("s2").firstChild,
+ `${description} selection should be expanded into the first line (got: ${getNodeDescription(range.startContainer)})`);
+ isfuzzy(range.startOffset, 3, 2,
+ `${description} selection should be expanded to around the first line's 3rd insertion point`);
+ if (aExpandSelection) {
+ is(range.endContainer, doc.getElementById("s4").firstChild,
+ `${description} selection should be expanded from the 3rd line (got: ${getNodeDescription(range.endContainer)})`);
+ is(range.endOffset, 3,
+ `${description} selection should be expanded from the 3rd line's 3rd insertion point`);
+ } else {
+ ok(range.collapsed, `${description} selection should be collapsed`);
+ }
+
+ body.innerHTML = '<span id="s1">first line in the body</span>' +
+ '<div id="d1" contenteditable style="height: 2em; line-height: 1em; overflow: auto;">' +
+ '<span id="s2">first line</span><br>' +
+ '<span id="s3">second line</span><br>' +
+ '<span id="s4">third line</span><br>' +
+ '<span id="s5">last line</span>' +
+ "</div>" +
+ '<span id="s6">last line in the body</span>';
+ container = doc.getElementById("d1");
+
+ description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to forward in scrollable editable div in the body: `;
+ is(container.scrollTop, 0, description + "scrollTop should be 0 at initialization");
+ selection.collapse(doc.getElementById("s2").firstChild, 3);
+ doPageDown();
+ isnot(container.scrollTop, 0, description + "should be scrolled down");
+ range = selection.getRangeAt(0);
+ if (aExpandSelection) {
+ is(range.startContainer, doc.getElementById("s2").firstChild,
+ `${description} selection should be expanded from the first line (got: ${getNodeDescription(range.startContainer)})`);
+ is(range.startOffset, 3,
+ `${description} selection should be expanded from the first line's 3rd insertion point`);
+ } else {
+ ok(range.collapsed, `${description} selection should be collapsed`);
+ }
+ is(range.endContainer, doc.getElementById("s4").firstChild,
+ `${description} selection should be expanded into the 3rd line (got: ${getNodeDescription(range.endContainer)})`);
+ isfuzzy(range.endOffset, 3, 2,
+ `${description} selection should be expanded to around the 3rd line's 3rd insertion point`);
+
+ description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to backward in scrollable editable div in the body: `;
+ selection.collapse(doc.getElementById("s4").firstChild, 3);
+ previousScrollTop = container.scrollTop;
+ doPageUp();
+ ok(container.scrollTop < previousScrollTop, description + "should be scrolled up");
+ range = selection.getRangeAt(0);
+ is(range.startContainer, doc.getElementById("s2").firstChild,
+ `${description} selection should be expanded into the first line (got: ${getNodeDescription(range.startContainer)})`);
+ isfuzzy(range.startOffset, 3, 2,
+ `${description} selection should be expanded to around the first line's 3rd insertion point`);
+ if (aExpandSelection) {
+ is(range.endContainer, doc.getElementById("s4").firstChild,
+ `${description} selection should be expanded from the 3rd line (got: ${getNodeDescription(range.endContainer)})`);
+ is(range.endOffset, 3,
+ `${description} selection should be expanded from the 3rd line's 3rd insertion point`);
+ } else {
+ ok(range.collapsed, `${description} selection should be collapsed`);
+ }
+
+ body.innerHTML = '<span id="s1">first line in the body</span>' +
+ '<div id="d1" contenteditable>' +
+ '<span id="s2">first line</span><br>' +
+ '<span id="s3">second line</span><br>' +
+ '<span id="s4">third line</span><br>' +
+ '<span id="s5">last line</span>' +
+ "</div>" +
+ '<span id="s6">last line in the body</span>';
+ container = doc.getElementById("d1");
+
+ description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to forward in non-scrollable editable div in the body: `;
+ is(container.scrollTop, 0, description + "scrollTop should be 0 at initialization");
+ selection.collapse(doc.getElementById("s2").firstChild, 3);
+ doPageDown();
+ is(container.scrollTop, 0, description + "editable div shouldn't be scrollable");
+ range = selection.getRangeAt(0);
+ if (aExpandSelection) {
+ is(range.startContainer, doc.getElementById("s2").firstChild,
+ `${description} selection should be expanded from the first line (got: ${getNodeDescription(range.startContainer)})`);
+ is(range.startOffset, 3,
+ `${description} selection should be expanded from the first line's 3rd insertion point`);
+ } else {
+ ok(range.collapsed, `${description} selection should be collapsed`);
+ }
+ is(range.endContainer, doc.getElementById("s5").firstChild,
+ `${description} selection should be expanded into the last line (got: ${getNodeDescription(range.endContainer)})`);
+ if (kSelectToStartOrEnd) {
+ is(range.endOffset, range.endContainer.length,
+ `${description} selection should be expanded to end of the last line`);
+ } else {
+ isfuzzy(range.endOffset, 3, 2,
+ `${description} selection should be expanded to around the last line's 3rd insertion point`);
+ }
+
+ description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to backward in non-scrollable editable div in the body: `;
+ selection.collapse(doc.getElementById("s5").firstChild, 3);
+ doPageUp();
+ is(container.scrollTop, 0, description + "editable div shouldn't be scrollable");
+ range = selection.getRangeAt(0);
+ is(range.startContainer, doc.getElementById("s2").firstChild,
+ `${description} selection should be expanded into the first line (got: ${getNodeDescription(range.startContainer)})`);
+ if (kSelectToStartOrEnd) {
+ is(range.startOffset, 0,
+ `${description} selection should be expanded to start of the first line`);
+ } else {
+ isfuzzy(range.startOffset, 3, 2,
+ `${description} selection should be expanded to around the first line's 3rd insertion point`);
+ }
+ if (aExpandSelection) {
+ is(range.endContainer, doc.getElementById("s5").firstChild,
+ `${description} selection should be expanded from the last line (got: ${getNodeDescription(range.endContainer)})`);
+ is(range.endOffset, 3,
+ `${description} selection should be expanded from the last line's 3rd insertion point`);
+ } else {
+ ok(range.collapsed, `${description} selection should be collapsed`);
+ }
+
+ body.innerHTML = '<span id="s1">first line in the body</span>' +
+ '<div id="d1" contenteditable>' +
+ '<span id="s2">first editable line</span><br>' +
+ '<div id="d2" style="height: 3em; line-height: 1em; overflow: auto;">' +
+ '<span id="s3">first line</span><br>' +
+ '<span id="s4">second line</span>' +
+ "</div>" +
+ '<span id="s5">last editable line</span>' +
+ "</div>" +
+ '<span id="s6">last line in the body</span>';
+ container = doc.getElementById("d2");
+
+ description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to forward in scrollable div (but not scrollable along y-axis) in the editable div: `;
+ is(container.scrollTop, 0, description + "scrollTop should be 0 at initialization");
+ selection.collapse(doc.getElementById("s3").firstChild, 3);
+ doPageDown();
+ is(container.scrollTop, 0, description + "scrollable div in the editable div (but not scrollable along y-axis) shouldn't be scrollable");
+ range = selection.getRangeAt(0);
+ if (aExpandSelection) {
+ is(range.startContainer, doc.getElementById("s3").firstChild,
+ `${description} selection should be expanded from the first line (got: ${getNodeDescription(range.startContainer)})`);
+ is(range.startOffset, 3,
+ `${description} selection should be expanded from the first line's 3rd insertion point`);
+ } else {
+ ok(range.collapsed, `${description} selection should be collapsed`);
+ }
+ is(range.endContainer, doc.getElementById("s5").firstChild,
+ `${description} selection should be expanded into the last editable line (got: ${getNodeDescription(range.endContainer)})`);
+ if (kSelectToStartOrEnd) {
+ is(range.endOffset, range.endContainer.length,
+ `${description} selection should be expanded to end of the last editable line`);
+ } else {
+ isfuzzy(range.endOffset, 3, 2,
+ `${description} selection should be expanded to around the last editable line's 3rd insertion point`);
+ }
+
+ description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to backward in scrollable div (but not scrollable along y-axis) in the editable div: `;
+ selection.collapse(doc.getElementById("s4").firstChild, 3);
+ doPageUp();
+ is(container.scrollTop, 0, description + "scrollable div (but not scrollable along y-axis) in the editable div shouldn't be scrollable");
+ range = selection.getRangeAt(0);
+ is(range.startContainer, doc.getElementById("s2").firstChild,
+ `${description} selection should be expanded into the first editable line (got: ${getNodeDescription(range.startContainer)})`);
+ if (kSelectToStartOrEnd) {
+ is(range.startOffset, 0,
+ `${description} selection should be expanded to start of the first editable line`);
+ } else {
+ isfuzzy(range.startOffset, 3, 2,
+ `${description} selection should be expanded to around the first editable line's 3rd insertion point`);
+ }
+ if (aExpandSelection) {
+ is(range.endContainer, doc.getElementById("s4").firstChild,
+ `${description} selection should be expanded from the last line (got: ${getNodeDescription(range.endContainer)})`);
+ is(range.endOffset, 3,
+ `${description} selection should be expanded from the last line's 3rd insertion point`);
+ } else {
+ ok(range.collapsed, `${description} selection should be collapsed`);
+ }
+ }
+
+ doTest(false);
+ doTest(true);
+
+ aWindow.close();
+ SimpleTest.finish();
+}
+</script>
+</html>