gecko-dev/layout/base/tests/test_expanding_selection_pe...

312 строки
16 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<title>Test for expanding selection per page</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" 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) {
const IS_WIN = navigator.platform.includes("Win");
// On macOS and Linux, Shift + 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);
}
// 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 = !IS_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 doSelectPageDown() {
if (kUseKeyboardEvent) {
synthesizeKey("KEY_PageDown", {shiftKey: true}, aWindow);
} else {
selectionController.pageMove(true, true);
}
}
function doSelectPageUp() {
if (kUseKeyboardEvent) {
synthesizeKey("KEY_PageUp", {shiftKey: true}, aWindow);
} else {
selectionController.pageMove(false, true);
}
}
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 = "Expanding selection to forward in non-scrollable body: ";
is(container.scrollTop, 0, description + "scrollTop should be 0 at initialization");
selection.collapse(doc.getElementById("s1").firstChild, 3);
doSelectPageDown();
is(container.scrollTop, 0, description + "this test shouldn't create scrollable document");
let range = selection.getRangeAt(0);
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`);
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 = "Expanding selection to backward in non-scrollable body: ";
selection.collapse(doc.getElementById("s3").firstChild, 3);
doSelectPageUp();
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`);
}
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`);
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 = "Expanding selection 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);
doSelectPageDown();
isnot(container.scrollTop, 0, description + "should be scrolled down");
range = selection.getRangeAt(0);
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`);
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 = "Expanding selection to backward in scrollable area in the body: ";
selection.collapse(doc.getElementById("s4").firstChild, 3);
let previousScrollTop = container.scrollTop;
doSelectPageUp();
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`);
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`);
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 = "Expanding selection 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);
doSelectPageDown();
isnot(container.scrollTop, 0, description + "should be scrolled down");
range = selection.getRangeAt(0);
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`);
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 = "Expanding selection to backward in scrollable editable div in the body: ";
selection.collapse(doc.getElementById("s4").firstChild, 3);
previousScrollTop = container.scrollTop;
doSelectPageUp();
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`);
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`);
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 = "Expanding selection 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);
doSelectPageDown();
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 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`);
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 = "Expanding selection to backward in non-scrollable editable div in the body: ";
selection.collapse(doc.getElementById("s5").firstChild, 3);
doSelectPageUp();
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`);
}
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`);
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 = "Expanding selection 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);
doSelectPageDown();
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);
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`);
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 = "Expanding selection to backward in scrollable div (but not scrollable along y-axis) in the editable div: ";
selection.collapse(doc.getElementById("s4").firstChild, 3);
doSelectPageUp();
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`);
}
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`);
aWindow.close();
SimpleTest.finish();
}
</script>
</html>