diff options
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.html | 353 |
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> |