Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Test for caret movement around generated content</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<script>
"use strict";
function getRangeDescription(range) {
function getNodeDescription(node) {
if (!node) {
return "null";
}
switch (node.nodeType) {
case Node.TEXT_NODE:
return `${node.nodeName} "${node.data}"`;
case Node.ELEMENT_NODE:
return `<${node.nodeName.toLowerCase()}>`;
default:
return `${node.nodeName}`;
}
}
if (range === null) {
return "null";
}
if (range === undefined) {
return "undefined";
}
return range.startContainer == range.endContainer &&
range.startOffset == range.endOffset
? `(${getNodeDescription(range.startContainer)}, ${range.startOffset})`
: `(${getNodeDescription(range.startContainer)}, ${
range.startOffset
}) - (${getNodeDescription(range.endContainer)}, ${range.endOffset})`;
}
const kArrowLeft = "\uE012";
const kArrowUp = "\uE013";
const kArrowRight = "\uE014";
const kArrowDown = "\uE015";
function sendKey(k) {
return new test_driver.Actions().keyDown(k).keyUp(k).send();
}
promise_test(async () => {
await new Promise(resolve => {
addEventListener("load", resolve, {once: true});
});
}, "Initializing tests");
promise_test(async t => {
const editingHost = document.querySelector("#test1");
editingHost.focus();
const p = editingHost.querySelector("#a");
test(() => {
assert_equals(
getRangeDescription(getSelection().getRangeAt(0)),
getRangeDescription({
startContainer: editingHost.querySelector("#a").firstChild,
startOffset: 0,
endContainer: editingHost.querySelector("#a").firstChild,
endOffset: 0,
}),
);
}, `${t.name}: caret should start at the beginning of the first line`);
await sendKey(kArrowDown);
test(() => {
assert_equals(
getRangeDescription(getSelection().getRangeAt(0)),
getRangeDescription({
startContainer: editingHost.querySelector("#one").firstChild,
startOffset: 0,
endContainer: editingHost.querySelector("#one").firstChild,
endOffset: 0,
}),
);
}, `${t.name}: arrow-down should move the caret to the start of the first list item`);
await sendKey(kArrowDown);
test(() => {
assert_equals(
getRangeDescription(getSelection().getRangeAt(0)),
getRangeDescription({
startContainer: editingHost.querySelector("#two"),
startOffset: 0,
endContainer: editingHost.querySelector("#two"),
endOffset: 0,
}),
);
}, `${t.name}: arrow-down should move the caret to the second list item`);
await sendKey(kArrowDown);
test(() => {
assert_equals(
getRangeDescription(getSelection().getRangeAt(0)),
getRangeDescription({
startContainer: editingHost.querySelector("#three").firstChild,
startOffset: 0,
endContainer: editingHost.querySelector("#three").firstChild,
endOffset: 0,
}),
);
}, `${t.name}: arrow-down should move the caret to the third list item`);
await sendKey(kArrowDown);
test(() => {
assert_equals(
getRangeDescription(getSelection().getRangeAt(0)),
getRangeDescription({
startContainer: editingHost.querySelector("#z").firstChild,
startOffset: 0,
endContainer: editingHost.querySelector("#z").firstChild,
endOffset: 0,
}),
);
}, `${t.name}: arrow-down should move the caret to the final paragraph`);
}, "Moving caret between list items using arrow keys");
promise_test(async t => {
const editingHost = document.querySelector("#test2");
editingHost.focus();
const p = editingHost.querySelector("#before");
test(() => {
assert_equals(
getRangeDescription(getSelection().getRangeAt(0)),
getRangeDescription({
startContainer: editingHost.querySelector("#before").firstChild,
startOffset: 0,
endContainer: editingHost.querySelector("#before").firstChild,
endOffset: 0,
}),
);
}, `${t.name}: caret should start at the beginning of the first line`);
await sendKey(kArrowDown);
test(() => {
assert_equals(
getRangeDescription(getSelection().getRangeAt(0)),
getRangeDescription({
startContainer: editingHost.querySelector("#quote").firstChild,
startOffset: 0,
endContainer: editingHost.querySelector("#quote").firstChild,
endOffset: 0,
}),
);
}, `${t.name}: arrow-down should move the caret to the start of the block quote`);
await sendKey(kArrowDown);
test(() => {
assert_equals(
getRangeDescription(getSelection().getRangeAt(0)),
getRangeDescription({
startContainer: editingHost.querySelector("#after").firstChild,
startOffset: 0,
endContainer: editingHost.querySelector("#after").firstChild,
endOffset: 0,
}),
);
}, `${t.name}: arrow-down should move the caret to the final paragraph`);
await sendKey(kArrowLeft);
test(() => {
assert_equals(
getRangeDescription(getSelection().getRangeAt(0)),
getRangeDescription({
startContainer: editingHost.querySelector("#quote").firstChild,
startOffset: 5,
endContainer: editingHost.querySelector("#quote").firstChild,
endOffset: 5,
}),
);
}, `${t.name}: arrow-left should move the caret to the end of the quote`);
await sendKey(kArrowUp);
test(() => {
assert_equals(
getRangeDescription(getSelection().getRangeAt(0)),
getRangeDescription({
startContainer: editingHost.querySelector("#before").firstChild,
startOffset: 10,
endContainer: editingHost.querySelector("#before").firstChild,
endOffset: 10,
}),
);
}, `${t.name}: arrow-up should move the caret to into the first line`);
await sendKey(kArrowRight);
test(() => {
assert_equals(
getRangeDescription(getSelection().getRangeAt(0)),
getRangeDescription({
startContainer: editingHost.querySelector("#before").firstChild,
startOffset: 11,
endContainer: editingHost.querySelector("#before").firstChild,
endOffset: 11,
}),
);
}, `${t.name}: arrow-right should move the caret forward by one character`);
await sendKey(kArrowDown);
test(() => {
assert_equals(
getRangeDescription(getSelection().getRangeAt(0)),
getRangeDescription({
startContainer: editingHost.querySelector("#quote").firstChild,
startOffset: 5,
endContainer: editingHost.querySelector("#quote").firstChild,
endOffset: 5,
}),
);
}, `${t.name}: arrow-down should move the caret to the end of the quote`);
}, "Moving caret past the block-quote using arrow keys");
</script>
<style>
div {
font-family: monospace;
}
ul {
list-style-type: none;
}
li::before {
content: "*\00a0";
display: inline-block;
}
blockquote {
margin-inline-start: 5ch;
}
blockquote::after {
content: "\00a0*";
display: inline-block;
}
</style>
</head>
<body>
<div id=test1 contenteditable>
<p id=a>abc</p>
<ul>
<li id=one>one</li>
<li id=two><br></li>
<li id=three>three</li>
</ul>
<p id=z>xyz</p>
</div>
<div id=test2 contenteditable>
<p id=before>paragraph before the blockquote</p>
<blockquote id=quote>quote</blockquote>
<p id=after>after the blockquote</p>
</div>
</body>
</html>