Bug 1642594 - part 3: Add tentative WPT tests which test compatibility with Chrome r=m_kato

This patch adds new tentative WPTs which test Chrome's behavior at modifying
around white spaces.  As mentioned in the test files, these tests just check
compatibility with Chrome, not suggesting any standards.

Depends on D77987

Differential Revision: https://phabricator.services.mozilla.com/D78654
This commit is contained in:
Masayuki Nakano 2020-06-10 06:47:09 +00:00
parent 3d4e1bc4bb
commit abb8192418
10 changed files with 5037 additions and 0 deletions

View File

@ -0,0 +1,31 @@
[white-spaces-after-execCommand-insertlinebreak.tentative.html]
[execCommand("insertlinebreak", false, "") at "a      [\]   b"]
expected: FAIL
[execCommand("insertlinebreak", false, "") at "a [\]        b"]
expected: FAIL
[execCommand("insertlinebreak", false, "") at "a       [\]  b"]
expected: FAIL
[execCommand("insertlinebreak", false, "") at "a        [\] b"]
expected: FAIL
[execCommand("insertlinebreak", false, "") at "a   [\]      b"]
expected: FAIL
[execCommand("insertlinebreak", false, "") at "a    [\]     b"]
expected: FAIL
[execCommand("insertlinebreak", false, "") at "a         [\]b"]
expected: FAIL
[execCommand("insertlinebreak", false, "") at "a     [\]    b"]
expected: FAIL
[execCommand("insertlinebreak", false, "") at "a[\]         b"]
expected: FAIL
[execCommand("insertlinebreak", false, "") at "a  [\]       b"]
expected: FAIL

View File

@ -0,0 +1,31 @@
[white-spaces-after-execCommand-insertparagraph.tentative.html]
[execCommand("insertparagraph", false, "") at "<div>a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[\]b</div>"]
expected: FAIL
[execCommand("insertparagraph", false, "") at "<div>a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[\]&nbsp;&nbsp;b</div>"]
expected: FAIL
[execCommand("insertparagraph", false, "") at "<div>a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[\]&nbsp;&nbsp;&nbsp;b</div>"]
expected: FAIL
[execCommand("insertparagraph", false, "") at "<div>a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[\]&nbsp;&nbsp;&nbsp;&nbsp;b</div>"]
expected: FAIL
[execCommand("insertparagraph", false, "") at "<div>a[\]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b</div>"]
expected: FAIL
[execCommand("insertparagraph", false, "") at "<div>a&nbsp;&nbsp;&nbsp;&nbsp;[\]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b</div>"]
expected: FAIL
[execCommand("insertparagraph", false, "") at "<div>a&nbsp;[\]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b</div>"]
expected: FAIL
[execCommand("insertparagraph", false, "") at "<div>a&nbsp;&nbsp;[\]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b</div>"]
expected: FAIL
[execCommand("insertparagraph", false, "") at "<div>a&nbsp;&nbsp;&nbsp;[\]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b</div>"]
expected: FAIL
[execCommand("insertparagraph", false, "") at "<div>a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[\]&nbsp;b</div>"]
expected: FAIL

View File

@ -0,0 +1,478 @@
[white-spaces-after-execCommand-inserttext.tentative.html]
[execCommand("inserttext", false, " ") at "a[\]"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span><span>b&nbsp;&nbsp;[\]</span></span><span>&nbsp;c</span>"]
expected: FAIL
[execCommand("inserttext", false, ""): "a|&nbsp;[\]b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp; &nbsp;&nbsp;[\]</span>c"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; &nbsp;[\]<span style=white-space:pre>b</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>&nbsp; [\]</span>b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp; &nbsp;[\]</span>c"]
expected: FAIL
[execCommand("inserttext", false, ""): "a[\] |&nbsp;b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span><span>b[\]</span></span><span>c</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a[\]b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp;[\]</span><span><span>&nbsp;c</span></span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a[\]b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span><span>b&nbsp; &nbsp;&nbsp;[\]</span></span><span>c</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a[\]"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp;&nbsp;&nbsp;[\]&nbsp;&nbsp;&nbsp;b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[\] b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [\]b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a[\]b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a[\]"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0") at "a[\]<span style=white-space:pre>&nbsp;</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[\]&nbsp;b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp;[\]</span><span>&nbsp;c</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; &nbsp; &nbsp;[\] b"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0\\u00A0\\u00A0") at "a[\]"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;[\]"]
expected: FAIL
[execCommand("inserttext", false, " ") at "&nbsp; [\]b"]
expected: FAIL
[execCommand("inserttext", false, "b") at "a[\]&nbsp;&nbsp;&nbsp;&nbsp;c"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0\\u00A0\\u00A0\\u00A0\\u00A0") at "a[\]"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a[\]<span style=white-space:pre>&nbsp;</span>"]
expected: FAIL
[execCommand("inserttext", false, "b") at "a&nbsp;&nbsp;&nbsp;&nbsp;[\]c"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0") at "a[\]<span style=white-space:pre>b</span>"]
expected: FAIL
[execCommand("inserttext", false, "b") at "a&nbsp;[\]&nbsp;&nbsp;&nbsp;c"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; &nbsp;&nbsp;[\]<span style=white-space:pre>b</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [\]b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; &nbsp; &nbsp; &nbsp; [\]b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span><span>b&nbsp;[\]</span></span><span>c</span>"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0") at "a&nbsp; &nbsp; [\]b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp;&nbsp;[\]</span><span>c</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[\]b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[\]"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>&nbsp; &nbsp;[\]</span>b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp;&nbsp;[\]</span>c"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp;[\]<span style=white-space:pre> </span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b[\]</span><span>c</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp; &nbsp;[\]</span><span><span>&nbsp;c</span></span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>&nbsp; &nbsp; &nbsp;[\]</span>b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp;&nbsp;[\]"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp;&nbsp;[\]&nbsp;&nbsp;&nbsp;&nbsp;b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a[\]"]
expected: FAIL
[execCommand("inserttext", false, " ") at "&nbsp; &nbsp; &nbsp; [\]b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a[\]"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp;&nbsp;[\]</span><span><span>c</span></span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp; &nbsp;&nbsp;[\]</span>&nbsp;c"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0\\u00A0\\u00A0\\u00A0\\u00A0\\u00A0\\u00A0") at "a[\]"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp; &nbsp;&nbsp;[\]</span><span>&nbsp;c</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp;&nbsp;[\]</span><span>&nbsp;c</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp;[\]</span><span> c</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a[\]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;[\]"]
expected: FAIL
[execCommand("inserttext", false, ""): "a[\]&nbsp;|&nbsp;b"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0\\u00A0\\u00A0\\u00A0\\u00A0\\u00A0\\u00A0") at "a[\]b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; [\]b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; &nbsp; &nbsp; &nbsp;[\]"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span><span>b&nbsp; &nbsp;[\]</span></span><span>&nbsp;c</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b[\]</span><span>&nbsp;c</span>"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0\\u00A0\\u00A0\\u00A0\\u00A0\\u00A0") at "a[\]"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp;&nbsp;&nbsp;[\]&nbsp;&nbsp;b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp; &nbsp;[\]</span><span>c</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp; &nbsp;&nbsp;[\]</span><span><span>c</span></span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; &nbsp; &nbsp; &nbsp;[\] b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; &nbsp;&nbsp;[\]<span style=white-space:pre>&nbsp;</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp;[\]</span><span><span> c</span></span>"]
expected: FAIL
[execCommand("inserttext", false, "b") at "a&nbsp;&nbsp;&nbsp;[\]&nbsp;c"]
expected: FAIL
[execCommand("inserttext", false, ""): "a |&nbsp;[\]b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span> [\]</span>b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b[\]</span><span><span>c</span></span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp;&nbsp;&nbsp;&nbsp;[\]&nbsp;&nbsp;b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a[\]"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; &nbsp;[\]"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp;&nbsp;[\]</span><span><span>&nbsp;c</span></span>"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0\\u00A0\\u00A0\\u00A0") at "a[\]b"]
expected: FAIL
[execCommand("inserttext", false, ""): "a&nbsp;|&nbsp;[\]b"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0\\u00A0\\u00A0\\u00A0\\u00A0") at "a[\]b"]
expected: FAIL
[execCommand("inserttext", false, ""): "a&nbsp;[\]|b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp;[\]&nbsp;&nbsp;&nbsp;&nbsp;b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp;&nbsp;[\]<span style=white-space:pre>&nbsp;</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b[\]</span><span><span>&nbsp;c</span></span>"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0") at "a&nbsp;[\]<span style=white-space:pre>&nbsp;</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a[\]<span style=white-space:pre>b</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; &nbsp;&nbsp;[\]"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp; &nbsp;[\]</span><span>&nbsp;c</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "&nbsp; &nbsp; &nbsp; &nbsp; [\]b"]
expected: FAIL
[execCommand("inserttext", false, ""): "a&nbsp;|[\]&nbsp;b"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0\\u00A0") at "a[\]"]
expected: FAIL
[execCommand("inserttext", false, ""): "a |[\]&nbsp;b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp;&nbsp;&nbsp;&nbsp;[\]&nbsp;b"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0") at "a&nbsp; &nbsp;&nbsp;[\]<span style=white-space:pre>&nbsp;</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp;[\]</span><span>c</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[\]b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a[\]b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; &nbsp;[\]<span style=white-space:pre>&nbsp;</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span><span>b&nbsp; &nbsp;[\]</span></span><span>c</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp;&nbsp;[\]b"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0\\u00A0\\u00A0") at "a[\]b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span><span>b[\]</span></span><span>&nbsp;c</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp; &nbsp;&nbsp;[\]</span><span>c</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp;[\]<span style=white-space:pre>&nbsp;</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp;[\]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0\\u00A0\\u00A0\\u00A0") at "a[\]"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[\] b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[\]"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp; &nbsp;&nbsp;[\]</span><span><span>&nbsp;c</span></span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp;[\]</span>&nbsp;c"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span><span>b&nbsp; &nbsp;&nbsp;[\]</span></span><span>&nbsp;c</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp;[\] b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; &nbsp; &nbsp;&nbsp;[\]"]
expected: FAIL
[execCommand("inserttext", false, ""): "a&nbsp;[\]|&nbsp;b"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0") at "a&nbsp; &nbsp;&nbsp;[\]<span style=white-space:pre>b</span>"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0") at "a&nbsp;&nbsp;[\]<span style=white-space:pre>&nbsp;</span>"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0") at "a&nbsp; &nbsp; &nbsp; [\]b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span><span>b&nbsp;[\]</span></span><span> c</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; &nbsp; &nbsp;[\]"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp; &nbsp;[\]</span><span><span>c</span></span>"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0") at "a&nbsp; &nbsp;[\]<span style=white-space:pre>b</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b[\]</span>&nbsp;c"]
expected: FAIL
[execCommand("inserttext", false, ""): "a [\]|&nbsp;b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a[\]&nbsp;&nbsp;b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span><span>b&nbsp;[\]</span></span><span>&nbsp;c</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; &nbsp;[\] b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; &nbsp; &nbsp; [\]b"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0") at "a&nbsp;[\]<span style=white-space:pre>b</span>"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0") at "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [\]b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp;[\]</span> c"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp;&nbsp;[\]<span style=white-space:pre>b</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp;[\]<span style=white-space:pre>b</span>"]
expected: FAIL
[execCommand("inserttext", false, ""): "a|[\]&nbsp;b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a[\]b"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0\\u00A0\\u00A0\\u00A0\\u00A0\\u00A0") at "a[\]b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp; &nbsp; [\]b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp;&nbsp;[\]</span>&nbsp;c"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0") at "a&nbsp; &nbsp; &nbsp; &nbsp; [\]b"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0") at "a&nbsp;&nbsp;[\]<span style=white-space:pre>b</span>"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0") at "a&nbsp; [\]b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "&nbsp; &nbsp; [\]b"]
expected: FAIL
[execCommand("inserttext", false, ""): "a[\]|&nbsp;b"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0") at "a&nbsp; &nbsp;[\]<span style=white-space:pre>&nbsp;</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span><span>b&nbsp;&nbsp;[\]</span></span><span>c</span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>&nbsp; &nbsp; [\]</span>b"]
expected: FAIL
[execCommand("inserttext", false, ""): "a&nbsp;|[\]b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp;[\]</span><span><span>c</span></span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp; &nbsp;[\]</span>&nbsp;c"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp;[\]&nbsp;b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a[\]"]
expected: FAIL
[execCommand("inserttext", false, "\\u00A0") at "a&nbsp;[\]<span style=white-space:pre> </span>"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b[\]</span>c"]
expected: FAIL
[execCommand("inserttext", false, ""): "a[\]&nbsp;|b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a[\]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a&nbsp;[\]"]
expected: FAIL
[execCommand("inserttext", false, " ") at "a<span>b&nbsp;[\]</span>c"]
expected: FAIL

View File

@ -0,0 +1,340 @@
<!doctype html>
<html>
<head>
<meta charset=utf-8>
<title>Testing normalizing white-space sequence after execCommand("delete", false, "")</title>
<script src=../include/implementation.js></script>
<script>var testsJsLibraryOnly = true</script>
<script src="../include/tests.js"></script>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
"use strict";
setup({explicit_done: true});
function runTests() {
// README:
// These tests based on the behavior of Chrome 83. This test does NOT define
// nor suggest any standard behavior (actually, some expected results might
// look odd), but this test must help you to understand how other browsers
// use different logic to normalize white-space sequence.
document.body.innerHTML = "<div contenteditable></div>";
let editor = document.querySelector("div[contenteditable]");
editor.focus();
let selection = document.getSelection();
function toPlaintext(str) {
return str.replace(/&nbsp;/g, "\u00A0");
}
function escape(str) {
return str.replace(/\u00A0/ig, "&nbsp;");
}
// Test simple removing in a text node.
// - initialText: Set to data of text node (only &nbsp; entity is handled)
// - expectedText: Set to data of the text node after `execCommand("delete")`
// - white-spaceRange: Set first item to start offset of white-space sequence,
// set second item to number of white-spaces.
for (const currentTest of [
{ initialText: "a&nbsp;", expectedText: "a", whiteSpaceRange: [1, 1] },
{ initialText: "a&nbsp;&nbsp;", expectedText: "a&nbsp;", whiteSpaceRange: [1, 2] },
{ initialText: "a &nbsp;", expectedText: "a&nbsp;", whiteSpaceRange: [1, 2] },
{ initialText: "a&nbsp;&nbsp;&nbsp;", expectedText: "a&nbsp;&nbsp;", whiteSpaceRange: [1, 3] },
{ initialText: "a&nbsp; &nbsp;", expectedText: "a&nbsp;&nbsp;", whiteSpaceRange: [1, 3] },
{ initialText: "a &nbsp;&nbsp;", expectedText: "a&nbsp;&nbsp;", whiteSpaceRange: [1, 3] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;", expectedText: "a&nbsp; &nbsp;", whiteSpaceRange: [1, 4] },
{ initialText: "a&nbsp;&nbsp; &nbsp;", expectedText: "a&nbsp; &nbsp;", whiteSpaceRange: [1, 4] },
{ initialText: "a&nbsp; &nbsp;&nbsp;", expectedText: "a&nbsp; &nbsp;", whiteSpaceRange: [1, 4] },
{ initialText: "a &nbsp; &nbsp;", expectedText: "a&nbsp; &nbsp;", whiteSpaceRange: [1, 4] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", expectedText: "a&nbsp; &nbsp;&nbsp;", whiteSpaceRange: [1, 5] },
{ initialText: "a&nbsp; &nbsp; &nbsp;", expectedText: "a&nbsp; &nbsp;&nbsp;", whiteSpaceRange: [1, 5] },
{ initialText: "a&nbsp;&nbsp;&nbsp; &nbsp;", expectedText: "a&nbsp; &nbsp;&nbsp;", whiteSpaceRange: [1, 5] },
{ initialText: "a&nbsp;&nbsp; &nbsp;&nbsp;", expectedText: "a&nbsp; &nbsp;&nbsp;", whiteSpaceRange: [1, 5] },
{ initialText: "a&nbsp; &nbsp;&nbsp;&nbsp;", expectedText: "a&nbsp; &nbsp;&nbsp;", whiteSpaceRange: [1, 5] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", expectedText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;", whiteSpaceRange: [1, 10] },
{ initialText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;", expectedText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;", whiteSpaceRange: [1, 10] },
{ initialText: "a &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;", expectedText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;", whiteSpaceRange: [1, 10] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", expectedText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;", whiteSpaceRange: [1, 11] },
{ initialText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;", expectedText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;", whiteSpaceRange: [1, 11] },
{ initialText: "a&nbsp;b", expectedText: "ab", whiteSpaceRange: [1, 1] },
{ initialText: "a b", expectedText: "ab", whiteSpaceRange: [1, 1] },
{ initialText: "a&nbsp;&nbsp;b", expectedText: "a b", whiteSpaceRange: [1, 2] },
{ initialText: "a&nbsp; b", expectedText: "a b", whiteSpaceRange: [1, 2] },
{ initialText: "a &nbsp;b", expectedText: "a b", whiteSpaceRange: [1, 2] },
{ initialText: "a&nbsp;&nbsp;&nbsp;b", expectedText: "a&nbsp; b", whiteSpaceRange: [1, 3] },
{ initialText: "a&nbsp; &nbsp;b", expectedText: "a&nbsp; b", whiteSpaceRange: [1, 3] },
{ initialText: "a &nbsp; b", expectedText: "a&nbsp; b", whiteSpaceRange: [1, 3] },
{ initialText: "a &nbsp;&nbsp;b", expectedText: "a&nbsp; b", whiteSpaceRange: [1, 3] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;b", expectedText: "a&nbsp; &nbsp;b", whiteSpaceRange: [1, 4] },
{ initialText: "a&nbsp; &nbsp; b", expectedText: "a&nbsp; &nbsp;b", whiteSpaceRange: [1, 4] },
{ initialText: "a &nbsp; &nbsp;b", expectedText: "a&nbsp; &nbsp;b", whiteSpaceRange: [1, 4] },
{ initialText: "a&nbsp;&nbsp; &nbsp;b", expectedText: "a&nbsp; &nbsp;b", whiteSpaceRange: [1, 4] },
{ initialText: "a&nbsp; &nbsp;&nbsp;b", expectedText: "a&nbsp; &nbsp;b", whiteSpaceRange: [1, 4] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b", expectedText: "a&nbsp; &nbsp; b", whiteSpaceRange: [1, 5] },
{ initialText: "a&nbsp; &nbsp; &nbsp;b", expectedText: "a&nbsp; &nbsp; b", whiteSpaceRange: [1, 5] },
{ initialText: "a &nbsp; &nbsp; b", expectedText: "a&nbsp; &nbsp; b", whiteSpaceRange: [1, 5] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp; b", expectedText: "a&nbsp; &nbsp; b", whiteSpaceRange: [1, 5] },
{ initialText: "a&nbsp;&nbsp;&nbsp; &nbsp;b", expectedText: "a&nbsp; &nbsp; b", whiteSpaceRange: [1, 5] },
{ initialText: "a&nbsp;&nbsp; &nbsp;&nbsp;b", expectedText: "a&nbsp; &nbsp; b", whiteSpaceRange: [1, 5] },
{ initialText: "a&nbsp; &nbsp;&nbsp;&nbsp;b", expectedText: "a&nbsp; &nbsp; b", whiteSpaceRange: [1, 5] },
{ initialText: "a &nbsp;&nbsp;&nbsp;&nbsp;b", expectedText: "a&nbsp; &nbsp; b", whiteSpaceRange: [1, 5] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b", expectedText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;b", whiteSpaceRange: [1, 10] },
{ initialText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b", expectedText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;b", whiteSpaceRange: [1, 10] },
{ initialText: "a &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;b", expectedText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;b", whiteSpaceRange: [1, 10] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b", expectedText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b", whiteSpaceRange: [1, 11] },
{ initialText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;b", expectedText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b", whiteSpaceRange: [1, 11] },
{ initialText: "a &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b", expectedText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b", whiteSpaceRange: [1, 11] },
{ initialText: "&nbsp;b", expectedText: "b", whiteSpaceRange: [0, 1] },
{ initialText: "&nbsp;&nbsp;b", expectedText: "&nbsp;b", whiteSpaceRange: [0, 2] },
{ initialText: "&nbsp; b", expectedText: "&nbsp;b", whiteSpaceRange: [0, 2] },
{ initialText: "&nbsp;&nbsp;&nbsp;b", expectedText: "&nbsp; b", whiteSpaceRange: [0, 3] },
{ initialText: "&nbsp; &nbsp;b", expectedText: "&nbsp; b", whiteSpaceRange: [0, 3] },
{ initialText: "&nbsp;&nbsp; b", expectedText: "&nbsp; b", whiteSpaceRange: [0, 3] },
{ initialText: "&nbsp;&nbsp;&nbsp;&nbsp;b", expectedText: "&nbsp; &nbsp;b", whiteSpaceRange: [0, 4] },
{ initialText: "&nbsp; &nbsp; b", expectedText: "&nbsp; &nbsp;b", whiteSpaceRange: [0, 4] },
{ initialText: "&nbsp;&nbsp;&nbsp; b", expectedText: "&nbsp; &nbsp;b", whiteSpaceRange: [0, 4] },
{ initialText: "&nbsp;&nbsp; &nbsp;b", expectedText: "&nbsp; &nbsp;b", whiteSpaceRange: [0, 4] },
{ initialText: "&nbsp; &nbsp;&nbsp;b", expectedText: "&nbsp; &nbsp;b", whiteSpaceRange: [0, 4] },
{ initialText: "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b", expectedText: "&nbsp; &nbsp; b", whiteSpaceRange: [0, 5] },
{ initialText: "&nbsp; &nbsp; &nbsp;b", expectedText: "&nbsp; &nbsp; b", whiteSpaceRange: [0, 5] },
{ initialText: "&nbsp;&nbsp;&nbsp; &nbsp;b", expectedText: "&nbsp; &nbsp; b", whiteSpaceRange: [0, 5] },
{ initialText: "&nbsp;&nbsp; &nbsp;&nbsp;b", expectedText: "&nbsp; &nbsp; b", whiteSpaceRange: [0, 5] },
{ initialText: "&nbsp; &nbsp;&nbsp;&nbsp;b", expectedText: "&nbsp; &nbsp; b", whiteSpaceRange: [0, 5] },
{ initialText: "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;b", whiteSpaceRange: [0, 10] },
{ initialText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;b", whiteSpaceRange: [0, 10] },
{ initialText: "&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;b", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;b", whiteSpaceRange: [0, 10] },
{ initialText: "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b", whiteSpaceRange: [0, 11] },
{ initialText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;b", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b", whiteSpaceRange: [0, 11] },
{ initialText: "&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b", whiteSpaceRange: [0, 11] },
{ initialText: "&nbsp;", expectedText: "", whiteSpaceRange: [0, 1] },
{ initialText: "&nbsp;&nbsp;", expectedText: "&nbsp;", whiteSpaceRange: [0, 2] },
{ initialText: "&nbsp;&nbsp;&nbsp;", expectedText: "&nbsp;&nbsp;", whiteSpaceRange: [0, 3] },
{ initialText: "&nbsp; &nbsp;", expectedText: "&nbsp;&nbsp;", whiteSpaceRange: [0, 3] },
{ initialText: "&nbsp;&nbsp;&nbsp;&nbsp;", expectedText: "&nbsp; &nbsp;", whiteSpaceRange: [0, 4] },
{ initialText: "&nbsp;&nbsp; &nbsp;", expectedText: "&nbsp; &nbsp;", whiteSpaceRange: [0, 4] },
{ initialText: "&nbsp; &nbsp;&nbsp;", expectedText: "&nbsp; &nbsp;", whiteSpaceRange: [0, 4] },
{ initialText: "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", expectedText: "&nbsp; &nbsp;&nbsp;", whiteSpaceRange: [0, 5] },
{ initialText: "&nbsp; &nbsp; &nbsp;", expectedText: "&nbsp; &nbsp;&nbsp;", whiteSpaceRange: [0, 5] },
{ initialText: "&nbsp;&nbsp;&nbsp; &nbsp;", expectedText: "&nbsp; &nbsp;&nbsp;", whiteSpaceRange: [0, 5] },
{ initialText: "&nbsp;&nbsp; &nbsp;&nbsp;", expectedText: "&nbsp; &nbsp;&nbsp;", whiteSpaceRange: [0, 5] },
{ initialText: "&nbsp; &nbsp;&nbsp;&nbsp;", expectedText: "&nbsp; &nbsp;&nbsp;", whiteSpaceRange: [0, 5] },
{ initialText: "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;", whiteSpaceRange: [0, 10] },
{ initialText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;", whiteSpaceRange: [0, 10] },
{ initialText: "&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;", whiteSpaceRange: [0, 10] },
{ initialText: "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;", whiteSpaceRange: [0, 11] },
{ initialText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;", whiteSpaceRange: [0, 11] },
{ initialText: "&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;", whiteSpaceRange: [0, 11] },
]) {
for (let i = currentTest.whiteSpaceRange[0]; i < currentTest.whiteSpaceRange[0] + currentTest.whiteSpaceRange[1]; i++) {
currentTest.getInitialText = function (aCaretPos) {
return escape(`${toPlaintext(this.initialText).slice(0, aCaretPos)}[]${toPlaintext(this.initialText).slice(aCaretPos)}`);
}
test(function () {
editor.innerHTML = "";
editor.appendChild(document.createTextNode(toPlaintext(currentTest.initialText)));
selection.collapse(editor.firstChild, i + 1);
document.execCommand("delete", false, "");
if (currentTest.expectedText.length) {
assert_equals(escape(editor.childNodes.item(0).data), currentTest.expectedText, "Modified text is wrong");
assert_equals(selection.focusNode, editor.childNodes.item(0), "Selection focus node is wrong");
assert_equals(selection.focusOffset, i, "Selection focus offset is wrong");
assert_equals(selection.anchorNode, editor.childNodes.item(0), "Selection anchor node is wrong");
assert_equals(selection.anchorOffset, i, "Selection anchor offset is wrong");
} else {
assert_equals(escape(editor.textContent), "", "Modified text is wrong");
assert_equals(selection.focusNode, editor, "Selection focus node is wrong");
assert_equals(selection.focusOffset, 0, "Selection focus offset is wrong");
assert_equals(selection.anchorNode, editor, "Selection anchor node is wrong");
assert_equals(selection.anchorOffset, 0, "Selection anchor offset is wrong");
}
}, `execCommand("delete", false, ""): "${currentTest.getInitialText(i + 1)}" (length of whiteSpace sequence: ${currentTest.whiteSpaceRange[1]})`);
}
}
// Test white space sequence split to multiple text node.
// - initialText: Set to data of text nodes. This must have "|" at least one.
// Then, the text will be split at every "|".
// Same as above test, only &nbsp; is handled at setting.
// "[]" means that caret position.
// - expectedText: Set to data of all text nodes as an array.
// Same as above test, only &nbsp; is handled before comparing.
for (const currentTest of [
{ initialText: "a&nbsp; &nbsp;|[]&nbsp; &nbsp;b", expectedText: ["a&nbsp; []", "&nbsp; &nbsp;b"] },
{ initialText: "a&nbsp; &nbsp;[]|&nbsp; &nbsp;b", expectedText: ["a&nbsp; []", "&nbsp; &nbsp;b"] },
{ initialText: "a&nbsp; &nbsp;|[] &nbsp; b", expectedText: ["a&nbsp; []", "&nbsp; &nbsp;b"] },
{ initialText: "a&nbsp; &nbsp;[]| &nbsp; b", expectedText: ["a&nbsp; []", "&nbsp; &nbsp;b"] },
{ initialText: "a &nbsp; |[]&nbsp; &nbsp;b", expectedText: ["a &nbsp;[]", "&nbsp; &nbsp;b"] },
{ initialText: "a &nbsp; []|&nbsp; &nbsp;b", expectedText: ["a &nbsp;[]", "&nbsp; &nbsp;b"] },
{ initialText: "a&nbsp; &nbsp;|&nbsp;[] &nbsp;b", expectedText: ["a&nbsp; &nbsp;[]", "&nbsp; b"] },
{ initialText: "a&nbsp; &nbsp;| []&nbsp; b", expectedText: ["a&nbsp; &nbsp;[]", "&nbsp; b"] },
{ initialText: "a &nbsp; |&nbsp;[] &nbsp;b", expectedText: ["a &nbsp; []", "&nbsp; b"] },
{ initialText: "a &nbsp; | []&nbsp; b", expectedText: ["a &nbsp;[]", "&nbsp; b"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;[]&nbsp;&nbsp;b", expectedText: ["a&nbsp;&nbsp;&nbsp;&nbsp;", "&nbsp;[] &nbsp;b"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;[]&nbsp;&nbsp;&nbsp;b", expectedText: ["a&nbsp;&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp;b"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;|[]&nbsp;&nbsp;&nbsp;&nbsp;b", expectedText: ["a&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp; b"] },
{ initialText: "a&nbsp;b[]&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;[] &nbsp;", "&nbsp;&nbsp;&nbsp;&nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;b[]&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp; []&nbsp;&nbsp;", "&nbsp;&nbsp;&nbsp;&nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;b[]|&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp; c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;b|[]&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp; c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;b[]|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp; &nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;b|[]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp; &nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;|b[]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp; &nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;|&nbsp;b[]&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;", "&nbsp;[] &nbsp; &nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;|&nbsp;|[]&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp; c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;| |[]&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp; c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;| []|&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp; c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;[]| |&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;[]", "&nbsp;", "&nbsp;&nbsp;&nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;[]&nbsp;| |&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp; []&nbsp;", " ", "&nbsp;&nbsp;&nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;[]&nbsp;&nbsp;|&nbsp;|&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp; []&nbsp;&nbsp;", "&nbsp;", "&nbsp;&nbsp;&nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;[]&nbsp;&nbsp;| |&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp; []&nbsp;&nbsp;", " ", "&nbsp;&nbsp;&nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;||&nbsp;[]&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;||[]&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp; c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;|[]|&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp; c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;[]||&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp; c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;[]&nbsp;||&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp; []&nbsp;", "", "&nbsp;&nbsp;&nbsp;&nbsp;c"] },
]) {
test(function () {
editor.innerHTML = "";
let caret = { container: null, offset: -1 };
for (let text of toPlaintext(currentTest.initialText).split("|")) {
let caretOffset = text.indexOf("[]");
if (caretOffset >= 0) {
text = text.slice(0, caretOffset) + text.slice(caretOffset + 2);
}
let textNode = document.createTextNode(text);
editor.appendChild(textNode);
if (caretOffset >= 0) {
caret = { container: textNode, offset: caretOffset };
}
}
selection.collapse(caret.container, caret.offset);
document.execCommand("delete", false, "");
let child = editor.firstChild;
for (let expectedText of currentTest.expectedText) {
expectedText = toPlaintext(expectedText);
let caretOffset = expectedText.indexOf("[]");
if (caretOffset >= 0) {
expectedText = expectedText.slice(0, caretOffset) + expectedText.slice(caretOffset + 2);
}
if (!child || child.nodeName !== "#text") {
assert_equals("", escape(expectedText), "Expected text node is not there");
if (caretOffset >= 0) {
assert_equals(-1, caretOffset, "Selection should be contained in this node");
}
} else {
assert_equals(escape(child.data), escape(expectedText), "Modified text is wrong");
if (caretOffset >= 0) {
assert_equals(selection.focusNode, child, "Selection focus node is wrong");
assert_equals(selection.focusOffset, caretOffset, "Selection focus offset is wrong");
assert_equals(selection.anchorNode, child, "Selection anchor node is wrong");
assert_equals(selection.anchorOffset, caretOffset, "Selection anchor offset is wrong");
}
}
child = child.nextSibling;
}
if (child && child.nodeName === "#text") {
assert_equals(escape(child.data), "", "Unexpected text node is there");
}
}, `execCommand("delete", false, ""): "${currentTest.initialText}"`);
}
// Test white spaces around inline element boundary
// - initialHTML: Set to innerHTML of the <div> ("[{" and "]}" set selection to the range)
// - expectedText: Set to innerHTML of the <div> after `execCommand("delete")`
for (const currentTest of [
{ initialHTML: "<span>abc <span>&nbsp;[]def</span></span>", expectedHTML: "<span>abc <span>def</span></span>" },
{ initialHTML: "<span>abc <span>[]&nbsp;def</span></span>", expectedHTML: "<span>abc<span>&nbsp;def</span></span>" },
{ initialHTML: "<span>abc []<span>&nbsp;def</span></span>", expectedHTML: "<span>abc<span>&nbsp;def</span></span>" },
{ initialHTML: "<span>abc&nbsp;<span>&nbsp;[]def</span></span>", expectedHTML: "<span>abc&nbsp;<span>def</span></span>" },
{ initialHTML: "<span>abc&nbsp;<span>[]&nbsp;def</span></span>", expectedHTML: "<span>abc<span>&nbsp;def</span></span>" },
{ initialHTML: "<span>abc&nbsp;[]<span>&nbsp;def</span></span>", expectedHTML: "<span>abc<span>&nbsp;def</span></span>" },
{ initialHTML: "<span>abc&nbsp; <span>&nbsp;[]def</span></span>", expectedHTML: "<span>abc&nbsp; <span>def</span></span>" },
{ initialHTML: "<span>abc&nbsp; <span>[]&nbsp;def</span></span>", expectedHTML: "<span>abc&nbsp;<span>&nbsp;def</span></span>" },
{ initialHTML: "<span>abc&nbsp; []<span>&nbsp;def</span></span>", expectedHTML: "<span>abc&nbsp;<span>&nbsp;def</span></span>" },
{ initialHTML: "<span>abc &nbsp;<span>&nbsp;[]def</span></span>", expectedHTML: "<span>abc &nbsp;<span>def</span></span>" },
{ initialHTML: "<span>abc &nbsp;<span>[]&nbsp;def</span></span>", expectedHTML: "<span>abc <span>&nbsp;def</span></span>" },
{ initialHTML: "<span>abc &nbsp;[]<span>&nbsp;def</span></span>", expectedHTML: "<span>abc <span>&nbsp;def</span></span>" },
{ initialHTML: "<span>abc </span><span>&nbsp;[]def</span>", expectedHTML: "<span>abc </span><span>def</span>" },
{ initialHTML: "<span>abc </span><span>[]&nbsp;def</span>", expectedHTML: "<span>abc</span><span>&nbsp;def</span>" },
{ initialHTML: "<span>abc []</span><span>&nbsp;def</span>", expectedHTML: "<span>abc</span><span>&nbsp;def</span>" },
{ initialHTML: "<span>abc&nbsp;</span><span>&nbsp;[]def</span>", expectedHTML: "<span>abc&nbsp;</span><span>def</span>" },
{ initialHTML: "<span>abc&nbsp;</span><span>[]&nbsp;def</span>", expectedHTML: "<span>abc</span><span>&nbsp;def</span>" },
{ initialHTML: "<span>abc&nbsp;[]</span><span>&nbsp;def</span>", expectedHTML: "<span>abc</span><span>&nbsp;def</span>" },
{ initialHTML: "<span>abc&nbsp; </span><span>&nbsp;[]def</span>", expectedHTML: "<span>abc&nbsp; </span><span>def</span>" },
{ initialHTML: "<span>abc&nbsp; </span><span>[]&nbsp;def</span>", expectedHTML: "<span>abc&nbsp;</span><span>&nbsp;def</span>" },
{ initialHTML: "<span>abc&nbsp; []</span><span>&nbsp;def</span>", expectedHTML: "<span>abc&nbsp;</span><span>&nbsp;def</span>" },
{ initialHTML: "<span>abc &nbsp;</span><span>&nbsp;[]def</span>", expectedHTML: "<span>abc &nbsp;</span><span>def</span>" },
{ initialHTML: "<span>abc &nbsp;</span><span>[]&nbsp;def</span>", expectedHTML: "<span>abc </span><span>&nbsp;def</span>" },
{ initialHTML: "<span>abc &nbsp;[]</span><span>&nbsp;def</span>", expectedHTML: "<span>abc </span><span>&nbsp;def</span>" },
{ initialHTML: "<span>abc&nbsp;</span><span>&nbsp; []def</span>", expectedHTML: "<span>abc&nbsp;</span><span>&nbsp;def</span>" },
{ initialHTML: "<span>abc&nbsp;</span><span>&nbsp; &nbsp;[]def</span>", expectedHTML: "<span>abc&nbsp;</span><span>&nbsp; def</span>" },
{ initialHTML: "<span>abc&nbsp;</span><span>&nbsp; []&nbsp;def</span>", expectedHTML: "<span>abc&nbsp;</span><span>&nbsp; def</span>" },
{ initialHTML: "<span>abc&nbsp;</span><span>&nbsp;[] &nbsp;def</span>", expectedHTML: "<span>abc&nbsp;</span><span>&nbsp; def</span>" },
{ initialHTML: "<span>abc&nbsp;</span><span> &nbsp; []def</span>", expectedHTML: "<span>abc&nbsp;</span><span>&nbsp; def</span>" },
{ initialHTML: "<span>abc&nbsp;</span><span> &nbsp;[] def</span>", expectedHTML: "<span>abc&nbsp;</span><span>&nbsp; def</span>" },
{ initialHTML: "<span>abc&nbsp;</span><span> []&nbsp; def</span>", expectedHTML: "<span>abc&nbsp;</span><span>&nbsp; def</span>" },
{ initialHTML: "<span>abc&nbsp;</span><span>[] &nbsp; def</span>", expectedHTML: "<span>abc</span><span>&nbsp; &nbsp;def</span>" },
{ initialHTML: "<span>abc&nbsp;[]</span><span> &nbsp; def</span>", expectedHTML: "<span>abc</span><span>&nbsp; &nbsp;def</span>" },
{ initialHTML: "<span>abc &nbsp;[]</span><span> &nbsp; def</span>", expectedHTML: "<span>abc </span><span>&nbsp; &nbsp;def</span>" },
{ initialHTML: "<span>abc&nbsp;&nbsp;[]</span><span> &nbsp; def</span>", expectedHTML: "<span>abc&nbsp;</span><span>&nbsp; &nbsp;def</span>" },
{ initialHTML: "<span>abc&nbsp;&nbsp;[]</span><span>&nbsp; &nbsp;def</span>", expectedHTML: "<span>abc&nbsp;</span><span>&nbsp; &nbsp;def</span>" },
{ initialHTML: "<span><span>abc </span>&nbsp;[]def</span>", expectedHTML: "<span><span>abc </span>def</span>" },
{ initialHTML: "<span><span>abc </span>[]&nbsp;def</span>", expectedHTML: "<span><span>abc</span>&nbsp;def</span>" },
{ initialHTML: "<span><span>abc []</span>&nbsp;def</span>", expectedHTML: "<span><span>abc</span>&nbsp;def</span>" },
{ initialHTML: "<span><span>abc&nbsp;</span>&nbsp;[]def</span>", expectedHTML: "<span><span>abc&nbsp;</span>def</span>" },
{ initialHTML: "<span><span>abc&nbsp;</span>[]&nbsp;def</span>", expectedHTML: "<span><span>abc</span>&nbsp;def</span>" },
{ initialHTML: "<span><span>abc&nbsp;[]</span>&nbsp;def</span>", expectedHTML: "<span><span>abc</span>&nbsp;def</span>" },
{ initialHTML: "<span><span>abc&nbsp; </span>&nbsp;[]def</span>", expectedHTML: "<span><span>abc&nbsp; </span>def</span>" },
{ initialHTML: "<span><span>abc&nbsp; </span>[]&nbsp;def</span>", expectedHTML: "<span><span>abc&nbsp;</span>&nbsp;def</span>" },
{ initialHTML: "<span><span>abc&nbsp; []</span>&nbsp;def</span>", expectedHTML: "<span><span>abc&nbsp;</span>&nbsp;def</span>" },
{ initialHTML: "<span><span>abc &nbsp;</span>&nbsp;[]def</span>", expectedHTML: "<span><span>abc &nbsp;</span>def</span>" },
{ initialHTML: "<span><span>abc &nbsp;</span>[]&nbsp;def</span>", expectedHTML: "<span><span>abc </span>&nbsp;def</span>" },
{ initialHTML: "<span><span>abc &nbsp;[]</span>&nbsp;def</span>", expectedHTML: "<span><span>abc </span>&nbsp;def</span>" },
{ initialHTML: "<span><span>abc &nbsp;</span></span><span>&nbsp;[]def</span>", expectedHTML: "<span><span>abc &nbsp;</span></span><span>def</span>" },
{ initialHTML: "<span><span>abc &nbsp;</span></span><span>[]&nbsp;def</span>", expectedHTML: "<span><span>abc </span></span><span>&nbsp;def</span>" },
{ initialHTML: "<span><span>abc &nbsp;[]</span></span><span>&nbsp;def</span>", expectedHTML: "<span><span>abc </span></span><span>&nbsp;def</span>" },
{ initialHTML: "a<span style=white-space:pre;>b[] </span>c", expectedHTML: "a<span style=\"white-space:pre;\"> </span>c" },
{ initialHTML: "a<span style=white-space:pre;>b [] </span>c", expectedHTML: "a<span style=\"white-space:pre;\">b </span>c" },
{ initialHTML: "a<span style=white-space:pre;>b [] </span>c", expectedHTML: "a<span style=\"white-space:pre;\">b </span>c" },
{ initialHTML: "a<span style=white-space:pre;>b []</span>c", expectedHTML: "a<span style=\"white-space:pre;\">b </span>c" },
{ initialHTML: "a<span style=white-space:pre;>b [] </span>", expectedHTML: "a<span style=\"white-space:pre;\">b </span>" },
{ initialHTML: "a<span style=white-space:pre;> </span>[]b", expectedHTML: "ab" },
{ initialHTML: "a&nbsp;&nbsp;&nbsp;<span style=white-space:pre;>[] </span>", expectedHTML: "a&nbsp;&nbsp;<span style=\"white-space:pre;\"> </span>" },
{ initialHTML: "a&nbsp;&nbsp;&nbsp;[]<span style=white-space:pre;> </span>", expectedHTML: "a&nbsp;&nbsp;<span style=\"white-space:pre;\"> </span>" },
{ initialHTML: "a&nbsp;&nbsp;[]&nbsp;<span style=white-space:pre;> </span>", expectedHTML: "a&nbsp;&nbsp;<span style=\"white-space:pre;\"> </span>" },
{ initialHTML: "a&nbsp;[]&nbsp;&nbsp;<span style=white-space:pre;>b </span>", expectedHTML: "a&nbsp;&nbsp;<span style=\"white-space:pre;\">b </span>" },
{ initialHTML: "a&nbsp;&nbsp;&nbsp;&nbsp;<span style=white-space:pre;>[] </span>", expectedHTML: "a&nbsp;&nbsp;&nbsp;<span style=\"white-space:pre;\"> </span>" },
{ initialHTML: "a&nbsp;&nbsp;&nbsp;&nbsp;[]<span style=white-space:pre;> </span>", expectedHTML: "a&nbsp;&nbsp;&nbsp;<span style=\"white-space:pre;\"> </span>" },
{ initialHTML: "a&nbsp;&nbsp;&nbsp;[]&nbsp;<span style=white-space:pre;> </span>", expectedHTML: "a&nbsp; &nbsp;<span style=\"white-space:pre;\"> </span>" },
{ initialHTML: "a&nbsp;&nbsp;[]&nbsp;<span style=white-space:pre;>b </span>", expectedHTML: "a&nbsp;&nbsp;<span style=\"white-space:pre;\">b </span>" },
{ initialHTML: "<span style=white-space:pre;> [] </span>&nbsp;&nbsp;&nbsp;a", expectedHTML: "<span style=\"white-space:pre;\"> </span>&nbsp;&nbsp;&nbsp;a" },
{ initialHTML: "<span style=white-space:pre;> []</span>&nbsp;&nbsp;&nbsp;a", expectedHTML: "<span style=\"white-space:pre;\"> </span>&nbsp; &nbsp;a" },
{ initialHTML: "<span style=white-space:pre;> </span>[]&nbsp;&nbsp;&nbsp;a", expectedHTML: "<span style=\"white-space:pre;\"> </span>&nbsp; &nbsp;a" },
{ initialHTML: "<span style=white-space:pre;> </span>&nbsp;[]&nbsp;&nbsp;&nbsp;a", expectedHTML: "<span style=\"white-space:pre;\"> </span>&nbsp; &nbsp;a" },
]) {
test(function () {
let points = setupDiv(editor, currentTest.initialHTML);
selection.setBaseAndExtent(points[0], points[1], points[2], points[3]);
document.execCommand("delete", false, "");
assert_equals(editor.innerHTML, currentTest.expectedHTML);
}, `execCommand("delete", false, ""): "${currentTest.initialHTML}"`);
}
done();
}
window.addEventListener("load", runTests, {once: true});
</script>
</body>
</html>

View File

@ -0,0 +1,356 @@
<!doctype html>
<html>
<head>
<meta charset=utf-8>
<title>Testing normalizing white space sequence after execCommand("forward", false, "")</title>
<script src=../include/implementation.js></script>
<script>var testsJsLibraryOnly = true</script>
<script src="../include/tests.js"></script>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
"use strict";
setup({explicit_done: true});
function runTests() {
// README:
// These tests based on the behavior of Chrome 83. This test does NOT define
// nor suggest any standard behavior (actually, some expected results might
// look odd), but this test must help you to understand how other browsers
// use different logic to normalize white-space sequence.
document.body.innerHTML = "<div contenteditable></div>";
let editor = document.querySelector("div[contenteditable]");
editor.focus();
let selection = document.getSelection();
function toPlaintext(str) {
return str.replace(/&nbsp;/g, "\u00A0");
}
function escape(str) {
return str.replace(/\u00A0/ig, "&nbsp;");
}
// Test simple removing in a text node.
// - initialText: Set to data of text node (only &nbsp; entity is handled)
// - expectedText: Set to data of the text node after `execCommand("forward")`
// - whiteSpaceRange: Set first item to start offset of whitespace sequence,
// set second item to number of white spaces.
for (const currentTest of [
{ initialText: "a&nbsp;", expectedText: "a", whiteSpaceRange: [1, 1] },
{ initialText: "a&nbsp;&nbsp;", expectedText: "a&nbsp;", whiteSpaceRange: [1, 2] },
{ initialText: "a &nbsp;", expectedText: "a&nbsp;", whiteSpaceRange: [1, 2] },
{ initialText: "a&nbsp;&nbsp;&nbsp;", expectedText: "a&nbsp;&nbsp;", whiteSpaceRange: [1, 3] },
{ initialText: "a&nbsp; &nbsp;", expectedText: "a&nbsp;&nbsp;", whiteSpaceRange: [1, 3] },
{ initialText: "a &nbsp;&nbsp;", expectedText: "a&nbsp;&nbsp;", whiteSpaceRange: [1, 3] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;", expectedText: "a&nbsp; &nbsp;", whiteSpaceRange: [1, 4] },
{ initialText: "a&nbsp;&nbsp; &nbsp;", expectedText: "a&nbsp; &nbsp;", whiteSpaceRange: [1, 4] },
{ initialText: "a&nbsp; &nbsp;&nbsp;", expectedText: "a&nbsp; &nbsp;", whiteSpaceRange: [1, 4] },
{ initialText: "a &nbsp; &nbsp;", expectedText: "a&nbsp; &nbsp;", whiteSpaceRange: [1, 4] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", expectedText: "a&nbsp; &nbsp;&nbsp;", whiteSpaceRange: [1, 5] },
{ initialText: "a&nbsp; &nbsp; &nbsp;", expectedText: "a&nbsp; &nbsp;&nbsp;", whiteSpaceRange: [1, 5] },
{ initialText: "a&nbsp;&nbsp;&nbsp; &nbsp;", expectedText: "a&nbsp; &nbsp;&nbsp;", whiteSpaceRange: [1, 5] },
{ initialText: "a&nbsp;&nbsp; &nbsp;&nbsp;", expectedText: "a&nbsp; &nbsp;&nbsp;", whiteSpaceRange: [1, 5] },
{ initialText: "a&nbsp; &nbsp;&nbsp;&nbsp;", expectedText: "a&nbsp; &nbsp;&nbsp;", whiteSpaceRange: [1, 5] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", expectedText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;", whiteSpaceRange: [1, 10] },
{ initialText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;", expectedText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;", whiteSpaceRange: [1, 10] },
{ initialText: "a &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;", expectedText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;", whiteSpaceRange: [1, 10] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", expectedText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;", whiteSpaceRange: [1, 11] },
{ initialText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;", expectedText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;", whiteSpaceRange: [1, 11] },
{ initialText: "a&nbsp;b", expectedText: "ab", whiteSpaceRange: [1, 1] },
{ initialText: "a b", expectedText: "ab", whiteSpaceRange: [1, 1] },
{ initialText: "a&nbsp;&nbsp;b", expectedText: "a b", whiteSpaceRange: [1, 2] },
{ initialText: "a&nbsp; b", expectedText: "a b", whiteSpaceRange: [1, 2] },
{ initialText: "a &nbsp;b", expectedText: "a b", whiteSpaceRange: [1, 2] },
{ initialText: "a&nbsp;&nbsp;&nbsp;b", expectedText: "a&nbsp; b", whiteSpaceRange: [1, 3] },
{ initialText: "a&nbsp; &nbsp;b", expectedText: "a&nbsp; b", whiteSpaceRange: [1, 3] },
{ initialText: "a &nbsp; b", expectedText: "a&nbsp; b", whiteSpaceRange: [1, 3] },
{ initialText: "a &nbsp;&nbsp;b", expectedText: "a&nbsp; b", whiteSpaceRange: [1, 3] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;b", expectedText: "a&nbsp; &nbsp;b", whiteSpaceRange: [1, 4] },
{ initialText: "a&nbsp; &nbsp; b", expectedText: "a&nbsp; &nbsp;b", whiteSpaceRange: [1, 4] },
{ initialText: "a &nbsp; &nbsp;b", expectedText: "a&nbsp; &nbsp;b", whiteSpaceRange: [1, 4] },
{ initialText: "a&nbsp;&nbsp; &nbsp;b", expectedText: "a&nbsp; &nbsp;b", whiteSpaceRange: [1, 4] },
{ initialText: "a&nbsp; &nbsp;&nbsp;b", expectedText: "a&nbsp; &nbsp;b", whiteSpaceRange: [1, 4] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b", expectedText: "a&nbsp; &nbsp; b", whiteSpaceRange: [1, 5] },
{ initialText: "a&nbsp; &nbsp; &nbsp;b", expectedText: "a&nbsp; &nbsp; b", whiteSpaceRange: [1, 5] },
{ initialText: "a &nbsp; &nbsp; b", expectedText: "a&nbsp; &nbsp; b", whiteSpaceRange: [1, 5] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp; b", expectedText: "a&nbsp; &nbsp; b", whiteSpaceRange: [1, 5] },
{ initialText: "a&nbsp;&nbsp;&nbsp; &nbsp;b", expectedText: "a&nbsp; &nbsp; b", whiteSpaceRange: [1, 5] },
{ initialText: "a&nbsp;&nbsp; &nbsp;&nbsp;b", expectedText: "a&nbsp; &nbsp; b", whiteSpaceRange: [1, 5] },
{ initialText: "a&nbsp; &nbsp;&nbsp;&nbsp;b", expectedText: "a&nbsp; &nbsp; b", whiteSpaceRange: [1, 5] },
{ initialText: "a &nbsp;&nbsp;&nbsp;&nbsp;b", expectedText: "a&nbsp; &nbsp; b", whiteSpaceRange: [1, 5] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b", expectedText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;b", whiteSpaceRange: [1, 10] },
{ initialText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b", expectedText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;b", whiteSpaceRange: [1, 10] },
{ initialText: "a &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;b", expectedText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;b", whiteSpaceRange: [1, 10] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b", expectedText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b", whiteSpaceRange: [1, 11] },
{ initialText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;b", expectedText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b", whiteSpaceRange: [1, 11] },
{ initialText: "a &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b", expectedText: "a&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b", whiteSpaceRange: [1, 11] },
{ initialText: "&nbsp;b", expectedText: "b", whiteSpaceRange: [0, 1] },
{ initialText: "&nbsp;&nbsp;b", expectedText: "&nbsp;b", whiteSpaceRange: [0, 2] },
{ initialText: "&nbsp; b", expectedText: "&nbsp;b", whiteSpaceRange: [0, 2] },
{ initialText: "&nbsp;&nbsp;&nbsp;b", expectedText: "&nbsp; b", whiteSpaceRange: [0, 3] },
{ initialText: "&nbsp; &nbsp;b", expectedText: "&nbsp; b", whiteSpaceRange: [0, 3] },
{ initialText: "&nbsp;&nbsp; b", expectedText: "&nbsp; b", whiteSpaceRange: [0, 3] },
{ initialText: "&nbsp;&nbsp;&nbsp;&nbsp;b", expectedText: "&nbsp; &nbsp;b", whiteSpaceRange: [0, 4] },
{ initialText: "&nbsp; &nbsp; b", expectedText: "&nbsp; &nbsp;b", whiteSpaceRange: [0, 4] },
{ initialText: "&nbsp;&nbsp;&nbsp; b", expectedText: "&nbsp; &nbsp;b", whiteSpaceRange: [0, 4] },
{ initialText: "&nbsp;&nbsp; &nbsp;b", expectedText: "&nbsp; &nbsp;b", whiteSpaceRange: [0, 4] },
{ initialText: "&nbsp; &nbsp;&nbsp;b", expectedText: "&nbsp; &nbsp;b", whiteSpaceRange: [0, 4] },
{ initialText: "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b", expectedText: "&nbsp; &nbsp; b", whiteSpaceRange: [0, 5] },
{ initialText: "&nbsp; &nbsp; &nbsp;b", expectedText: "&nbsp; &nbsp; b", whiteSpaceRange: [0, 5] },
{ initialText: "&nbsp;&nbsp;&nbsp; &nbsp;b", expectedText: "&nbsp; &nbsp; b", whiteSpaceRange: [0, 5] },
{ initialText: "&nbsp;&nbsp; &nbsp;&nbsp;b", expectedText: "&nbsp; &nbsp; b", whiteSpaceRange: [0, 5] },
{ initialText: "&nbsp; &nbsp;&nbsp;&nbsp;b", expectedText: "&nbsp; &nbsp; b", whiteSpaceRange: [0, 5] },
{ initialText: "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;b", whiteSpaceRange: [0, 10] },
{ initialText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;b", whiteSpaceRange: [0, 10] },
{ initialText: "&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;b", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;b", whiteSpaceRange: [0, 10] },
{ initialText: "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b", whiteSpaceRange: [0, 11] },
{ initialText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;b", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b", whiteSpaceRange: [0, 11] },
{ initialText: "&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b", whiteSpaceRange: [0, 11] },
{ initialText: "&nbsp;", expectedText: "", whiteSpaceRange: [0, 1] },
{ initialText: "&nbsp;&nbsp;", expectedText: "&nbsp;", whiteSpaceRange: [0, 2] },
{ initialText: "&nbsp;&nbsp;&nbsp;", expectedText: "&nbsp;&nbsp;", whiteSpaceRange: [0, 3] },
{ initialText: "&nbsp; &nbsp;", expectedText: "&nbsp;&nbsp;", whiteSpaceRange: [0, 3] },
{ initialText: "&nbsp;&nbsp;&nbsp;&nbsp;", expectedText: "&nbsp; &nbsp;", whiteSpaceRange: [0, 4] },
{ initialText: "&nbsp;&nbsp; &nbsp;", expectedText: "&nbsp; &nbsp;", whiteSpaceRange: [0, 4] },
{ initialText: "&nbsp; &nbsp;&nbsp;", expectedText: "&nbsp; &nbsp;", whiteSpaceRange: [0, 4] },
{ initialText: "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", expectedText: "&nbsp; &nbsp;&nbsp;", whiteSpaceRange: [0, 5] },
{ initialText: "&nbsp; &nbsp; &nbsp;", expectedText: "&nbsp; &nbsp;&nbsp;", whiteSpaceRange: [0, 5] },
{ initialText: "&nbsp;&nbsp;&nbsp; &nbsp;", expectedText: "&nbsp; &nbsp;&nbsp;", whiteSpaceRange: [0, 5] },
{ initialText: "&nbsp;&nbsp; &nbsp;&nbsp;", expectedText: "&nbsp; &nbsp;&nbsp;", whiteSpaceRange: [0, 5] },
{ initialText: "&nbsp; &nbsp;&nbsp;&nbsp;", expectedText: "&nbsp; &nbsp;&nbsp;", whiteSpaceRange: [0, 5] },
{ initialText: "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;", whiteSpaceRange: [0, 10] },
{ initialText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;", whiteSpaceRange: [0, 10] },
{ initialText: "&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;", whiteSpaceRange: [0, 10] },
{ initialText: "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;", whiteSpaceRange: [0, 11] },
{ initialText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;", whiteSpaceRange: [0, 11] },
{ initialText: "&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;", expectedText: "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;", whiteSpaceRange: [0, 11] },
]) {
for (let i = currentTest.whiteSpaceRange[0]; i < currentTest.whiteSpaceRange[0] + currentTest.whiteSpaceRange[1]; i++) {
currentTest.getInitialText = function (aCaretPos) {
return escape(`${toPlaintext(this.initialText).slice(0, aCaretPos)}[]${toPlaintext(this.initialText).slice(aCaretPos)}`);
}
test(function () {
editor.innerHTML = "";
editor.appendChild(document.createTextNode(toPlaintext(currentTest.initialText)));
selection.collapse(editor.firstChild, i);
document.execCommand("forwarddelete", false, "");
if (currentTest.expectedText.length) {
assert_equals(escape(editor.childNodes.item(0).data), currentTest.expectedText, "Modified text is wrong");
assert_equals(selection.focusNode, editor.childNodes.item(0), "Selection focus node is wrong");
assert_equals(selection.focusOffset, i, "Selection focus offset is wrong");
assert_equals(selection.anchorNode, editor.childNodes.item(0), "Selection anchor node is wrong");
assert_equals(selection.anchorOffset, i, "Selection anchor offset is wrong");
} else {
assert_equals(escape(editor.textContent), "", "Modified text is wrong");
assert_equals(selection.focusNode, editor, "Selection focus node is wrong");
assert_equals(selection.focusOffset, 0, "Selection focus offset is wrong");
assert_equals(selection.anchorNode, editor, "Selection anchor node is wrong");
assert_equals(selection.anchorOffset, 0, "Selection anchor offset is wrong");
}
}, `execCommand("forwarddelete", false, ""): "${currentTest.getInitialText(i)}" (length of whitespace sequence: ${currentTest.whiteSpaceRange[1]})`);
}
}
// Test white space sequence split to multiple text node.
// - initialText: Set to data of text nodes. This must have "|" at least one.
// Then, the text will be split at every "|".
// Same as above test, only &nbsp; is handled at setting.
// "[]" means that caret position.
// - expectedText: Set to data of all text nodes as an array.
// Same as above test, only &nbsp; is handled before comparing.
for (const currentTest of [
{ initialText: "a&nbsp; []&nbsp;|&nbsp; &nbsp;b", expectedText: ["a&nbsp; []", "&nbsp; &nbsp;b"] },
{ initialText: "a&nbsp; []&nbsp;| &nbsp; b", expectedText: ["a&nbsp; []", "&nbsp; &nbsp;b"] },
{ initialText: "a&nbsp; &nbsp;[]|&nbsp; &nbsp;b", expectedText: ["a&nbsp; &nbsp;[]", "&nbsp; b"] },
{ initialText: "a&nbsp; &nbsp;[]| &nbsp; b", expectedText: ["a&nbsp; &nbsp;[]", "&nbsp; b"] },
{ initialText: "a&nbsp; &nbsp;|[]&nbsp; &nbsp;b", expectedText: ["a&nbsp; &nbsp;[]", "&nbsp; b"] },
{ initialText: "a&nbsp; &nbsp;|[] &nbsp; b", expectedText: ["a&nbsp; &nbsp;[]", "&nbsp; b"] },
{ initialText: "a&nbsp; &nbsp;| []&nbsp; b", expectedText: ["a&nbsp; &nbsp;", "&nbsp;[] b"] },
{ initialText: "a &nbsp; |[]&nbsp; &nbsp;b", expectedText: ["a &nbsp; []", "&nbsp; b"] },
{ initialText: "a &nbsp; []|&nbsp; &nbsp;b", expectedText: ["a &nbsp; []", "&nbsp; b"] },
{ initialText: "a &nbsp;[] |&nbsp; &nbsp;b", expectedText: ["a &nbsp;[]", "&nbsp; &nbsp;b"] },
{ initialText: "a&nbsp;&nbsp;[]&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;b", expectedText: ["a&nbsp; []&nbsp;", "&nbsp;&nbsp;&nbsp;&nbsp;b"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;[]&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;b", expectedText: ["a&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp; b"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;[]|&nbsp;&nbsp;&nbsp;&nbsp;b", expectedText: ["a&nbsp;&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp;b"] },
{ initialText: "a&nbsp;[]b&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;[] &nbsp;", "&nbsp;&nbsp;&nbsp;&nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;[]b&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp; []&nbsp;&nbsp;", "&nbsp;&nbsp;&nbsp;&nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;[]b|&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp; c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;[]|b&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp; c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;|[]b&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp; c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;|&nbsp;[]b&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;", "&nbsp;[] &nbsp; c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;|&nbsp;|[]&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;", "&nbsp;[]", "&nbsp; &nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;| |[]&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;", " []", "&nbsp; &nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;| []|&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;", " []", "&nbsp; &nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;|[] |&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp; c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;[]| |&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;[]&nbsp;| |&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;[]", "&nbsp;", "&nbsp;&nbsp;&nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;[]&nbsp;&nbsp;|&nbsp;|&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp; &nbsp;[]&nbsp;", "&nbsp;", "&nbsp;&nbsp;&nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;[]&nbsp;&nbsp;| |&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp; &nbsp;[]&nbsp;", " ", "&nbsp;&nbsp;&nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;||&nbsp;[]&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;&nbsp;", "", "&nbsp;[] &nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;||[]&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;|[]|&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;&nbsp;[]||&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp;c"] },
{ initialText: "a&nbsp;&nbsp;&nbsp;[]&nbsp;||&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp;&nbsp;&nbsp;[]", "&nbsp; &nbsp; c"] },
{ initialText: "a&nbsp;&nbsp;[]&nbsp;&nbsp;||&nbsp;&nbsp;&nbsp;&nbsp;c", expectedText: ["a&nbsp; []&nbsp;", "", "&nbsp;&nbsp;&nbsp;&nbsp;c"] },
]) {
test(function () {
editor.innerHTML = "";
let caret = { container: null, offset: -1 };
for (let text of toPlaintext(currentTest.initialText).split("|")) {
let caretOffset = text.indexOf("[]");
if (caretOffset >= 0) {
text = text.slice(0, caretOffset) + text.slice(caretOffset + 2);
}
let textNode = document.createTextNode(text);
editor.appendChild(textNode);
if (caretOffset >= 0) {
caret = { container: textNode, offset: caretOffset };
}
}
selection.collapse(caret.container, caret.offset);
document.execCommand("forwarddelete", false, "");
let child = editor.firstChild;
for (let expectedText of currentTest.expectedText) {
expectedText = toPlaintext(expectedText);
let caretOffset = expectedText.indexOf("[]");
if (caretOffset >= 0) {
expectedText = expectedText.slice(0, caretOffset) + expectedText.slice(caretOffset + 2);
}
if (!child || child.nodeName !== "#text") {
assert_equals("", escape(expectedText), "Expected text node is not there");
if (caretOffset >= 0) {
assert_equals(-1, caretOffset, "Selection should be contained in this node");
}
} else {
assert_equals(escape(child.data), escape(expectedText), "Modified text is wrong");
if (caretOffset >= 0) {
assert_equals(selection.focusNode, child, "Selection focus node is wrong");
assert_equals(selection.focusOffset, caretOffset, "Selection focus offset is wrong");
assert_equals(selection.anchorNode, child, "Selection anchor node is wrong");
assert_equals(selection.anchorOffset, caretOffset, "Selection anchor offset is wrong");
}
}
child = child.nextSibling;
}
if (child && child.nodeName === "#text") {
assert_equals(escape(child.data), "", "Unexpected text node is there");
}
}, `execCommand("forwarddelete", false, ""): "${currentTest.initialText}"`);
}
// Test white spaces around inline element boundary
// - initialHTML: Set to innerHTML of the <div> ("[{" and "]}" set selection to the range)
// - expectedText: Set to innerHTML of the <div> after `execCommand("delete")`
for (const currentTest of [
{ initialHTML: "<span>abc[] <span>&nbsp;def</span></span>", expectedHTML: "<span>abc<span>&nbsp;def</span></span>" },
{ initialHTML: "<span>abc[]&nbsp;<span>&nbsp;def</span></span>", expectedHTML: "<span>abc<span>&nbsp;def</span></span>" },
{ initialHTML: "<span>abc[]&nbsp;<span> def</span></span>", expectedHTML: "<span>abc<span>&nbsp;def</span></span>" },
{ initialHTML: "<span>abc []<span>&nbsp;def</span></span>", expectedHTML: "<span>abc <span>def</span></span>" },
{ initialHTML: "<span>abc&nbsp;[]<span>&nbsp;def</span></span>", expectedHTML: "<span>abc&nbsp;<span>def</span></span>" },
{ initialHTML: "<span>abc&nbsp;[]<span> def</span></span>", expectedHTML: "<span>abc&nbsp;<span>def</span></span>" },
{ initialHTML: "<span>abc[]&nbsp;<span>&nbsp; def</span></span>", expectedHTML: "<span>abc<span>&nbsp; def</span></span>" },
{ initialHTML: "<span>abc[]&nbsp;<span> &nbsp;def</span></span>", expectedHTML: "<span>abc<span>&nbsp; def</span></span>" },
{ initialHTML: "<span>abc[]&nbsp; <span>&nbsp;&nbsp;def</span></span>", expectedHTML: "<span>abc&nbsp;<span>&nbsp;&nbsp;def</span></span>" },
{ initialHTML: "<span>abc[]&nbsp; <span>&nbsp; def</span></span>", expectedHTML: "<span>abc&nbsp;<span>&nbsp; def</span></span>" },
{ initialHTML: "<span>abc[]&nbsp;&nbsp;<span>&nbsp;&nbsp;def</span></span>", expectedHTML: "<span>abc&nbsp;<span>&nbsp;&nbsp;def</span></span>" },
{ initialHTML: "<span>abc[] &nbsp;<span>&nbsp;&nbsp;def</span></span>", expectedHTML: "<span>abc&nbsp;<span>&nbsp;&nbsp;def</span></span>" },
{ initialHTML: "<span>abc[] &nbsp;<span> &nbsp;def</span></span>", expectedHTML: "<span>abc&nbsp;<span> &nbsp;def</span></span>" },
{ initialHTML: "<span>abc[] &nbsp;<span>&nbsp; def</span></span>", expectedHTML: "<span>abc&nbsp;<span>&nbsp; def</span></span>" },
{ initialHTML: "<span>abc&nbsp; []<span>&nbsp; def</span></span>", expectedHTML: "<span>abc&nbsp; <span>&nbsp;def</span></span>" },
{ initialHTML: "<span>abc&nbsp; <span>[]&nbsp; def</span></span>", expectedHTML: "<span>abc&nbsp; <span>&nbsp;def</span></span>" },
{ initialHTML: "<span>abc&nbsp;&nbsp;[]<span> &nbsp;def</span></span>", expectedHTML: "<span>abc&nbsp;&nbsp;<span>&nbsp;def</span></span>" },
{ initialHTML: "<span>abc&nbsp;&nbsp;<span>[] &nbsp;def</span></span>", expectedHTML: "<span>abc&nbsp;&nbsp;<span>&nbsp;def</span></span>" },
{ initialHTML: "<span>abc &nbsp;[]<span>&nbsp; def</span></span>", expectedHTML: "<span>abc &nbsp;<span>&nbsp;def</span></span>" },
{ initialHTML: "<span>abc &nbsp;<span>[]&nbsp; def</span></span>", expectedHTML: "<span>abc &nbsp;<span>&nbsp;def</span></span>" },
{ initialHTML: "<span>abc&nbsp; <span>&nbsp;[] def</span></span>", expectedHTML: "<span>abc&nbsp; <span>&nbsp;def</span></span>" },
{ initialHTML: "<span>abc &nbsp;<span>&nbsp;[] def</span></span>", expectedHTML: "<span>abc &nbsp;<span>&nbsp;def</span></span>" },
{ initialHTML: "<span>abc &nbsp;<span> []&nbsp;def</span></span>", expectedHTML: "<span>abc &nbsp;<span>&nbsp;def</span></span>" },
{ initialHTML: "<span><span>abc[] </span>&nbsp;def</span>", expectedHTML: "<span><span>abc</span>&nbsp;def</span>" },
{ initialHTML: "<span><span>abc[]&nbsp;</span>&nbsp;def</span>", expectedHTML: "<span><span>abc</span>&nbsp;def</span>" },
{ initialHTML: "<span><span>abc[]&nbsp;</span> def</span>", expectedHTML: "<span><span>abc</span>&nbsp;def</span>" },
{ initialHTML: "<span><span>abc []</span>&nbsp;def</span>", expectedHTML: "<span><span>abc </span>def</span>" },
{ initialHTML: "<span><span>abc&nbsp;[]</span>&nbsp;def</span>", expectedHTML: "<span><span>abc&nbsp;</span>def</span>" },
{ initialHTML: "<span><span>abc&nbsp;[]</span> def</span>", expectedHTML: "<span><span>abc&nbsp;</span>def</span>" },
{ initialHTML: "<span><span>abc[]&nbsp;</span>&nbsp; def</span>", expectedHTML: "<span><span>abc</span>&nbsp; def</span>" },
{ initialHTML: "<span><span>abc[]&nbsp;</span> &nbsp;def</span>", expectedHTML: "<span><span>abc</span>&nbsp; def</span>" },
{ initialHTML: "<span><span>abc[]&nbsp; </span>&nbsp;&nbsp;def</span>", expectedHTML: "<span><span>abc&nbsp;</span>&nbsp;&nbsp;def</span>" },
{ initialHTML: "<span><span>abc[]&nbsp; </span>&nbsp; def</span>", expectedHTML: "<span><span>abc&nbsp;</span>&nbsp; def</span>" },
{ initialHTML: "<span><span>abc[]&nbsp;&nbsp;</span>&nbsp;&nbsp;def</span>", expectedHTML: "<span><span>abc&nbsp;</span>&nbsp;&nbsp;def</span>" },
{ initialHTML: "<span><span>abc[] &nbsp;</span>&nbsp;&nbsp;def</span>", expectedHTML: "<span><span>abc&nbsp;</span>&nbsp;&nbsp;def</span>" },
{ initialHTML: "<span><span>abc[] &nbsp;</span> &nbsp;def</span>", expectedHTML: "<span><span>abc&nbsp;</span> &nbsp;def</span>" },
{ initialHTML: "<span><span>abc[] &nbsp;</span>&nbsp; def</span>", expectedHTML: "<span><span>abc&nbsp;</span>&nbsp; def</span>" },
{ initialHTML: "<span><span>abc&nbsp; []</span>&nbsp; def</span>", expectedHTML: "<span><span>abc&nbsp; </span>&nbsp;def</span>" },
{ initialHTML: "<span><span>abc&nbsp; </span>[]&nbsp; def</span>", expectedHTML: "<span><span>abc&nbsp; </span>&nbsp;def</span>" },
{ initialHTML: "<span><span>abc&nbsp;&nbsp;[]</span> &nbsp;def</span>", expectedHTML: "<span><span>abc&nbsp;&nbsp;</span>&nbsp;def</span>" },
{ initialHTML: "<span><span>abc&nbsp;&nbsp;</span>[] &nbsp;def</span>", expectedHTML: "<span><span>abc&nbsp;&nbsp;</span>&nbsp;def</span>" },
{ initialHTML: "<span><span>abc &nbsp;[]</span>&nbsp; def</span>", expectedHTML: "<span><span>abc &nbsp;</span>&nbsp;def</span>" },
{ initialHTML: "<span><span>abc &nbsp;</span>[]&nbsp; def</span>", expectedHTML: "<span><span>abc &nbsp;</span>&nbsp;def</span>" },
{ initialHTML: "<span><span>abc&nbsp; </span>&nbsp;[] def</span>", expectedHTML: "<span><span>abc&nbsp; </span>&nbsp;def</span>" },
{ initialHTML: "<span><span>abc &nbsp;</span>&nbsp;[] def</span>", expectedHTML: "<span><span>abc &nbsp;</span>&nbsp;def</span>" },
{ initialHTML: "<span><span>abc &nbsp;</span> []&nbsp;def</span>", expectedHTML: "<span><span>abc &nbsp;</span>&nbsp;def</span>" },
{ initialHTML: "<span>abc[] </span><span>&nbsp;def</span>", expectedHTML: "<span>abc</span><span>&nbsp;def</span>" },
{ initialHTML: "<span>abc[]&nbsp;</span><span>&nbsp;def</span>", expectedHTML: "<span>abc</span><span>&nbsp;def</span>" },
{ initialHTML: "<span>abc[]&nbsp;</span><span> def</span>", expectedHTML: "<span>abc</span><span>&nbsp;def</span>" },
{ initialHTML: "<span>abc []</span><span>&nbsp;def</span>", expectedHTML: "<span>abc </span><span>def</span>" },
{ initialHTML: "<span>abc&nbsp;[]</span><span>&nbsp;def</span>", expectedHTML: "<span>abc&nbsp;</span><span>def</span>" },
{ initialHTML: "<span>abc&nbsp;[]</span><span> def</span>", expectedHTML: "<span>abc&nbsp;</span><span>def</span>" },
{ initialHTML: "<span>abc[]&nbsp;</span><span>&nbsp; def</span>", expectedHTML: "<span>abc</span><span>&nbsp; def</span>" },
{ initialHTML: "<span>abc[]&nbsp;</span><span> &nbsp;def</span>", expectedHTML: "<span>abc</span><span>&nbsp; def</span>" },
{ initialHTML: "<span>abc[]&nbsp; </span><span>&nbsp;&nbsp;def</span>", expectedHTML: "<span>abc&nbsp;</span><span>&nbsp;&nbsp;def</span>" },
{ initialHTML: "<span>abc[]&nbsp; </span><span>&nbsp; def</span>", expectedHTML: "<span>abc&nbsp;</span><span>&nbsp; def</span>" },
{ initialHTML: "<span>abc[]&nbsp;&nbsp;</span><span>&nbsp;&nbsp;def</span>", expectedHTML: "<span>abc&nbsp;</span><span>&nbsp;&nbsp;def</span>" },
{ initialHTML: "<span>abc[] &nbsp;</span><span>&nbsp;&nbsp;def</span>", expectedHTML: "<span>abc&nbsp;</span><span>&nbsp;&nbsp;def</span>" },
{ initialHTML: "<span>abc[] &nbsp;</span><span> &nbsp;def</span>", expectedHTML: "<span>abc&nbsp;</span><span> &nbsp;def</span>" },
{ initialHTML: "<span>abc[] &nbsp;</span><span>&nbsp; def</span>", expectedHTML: "<span>abc&nbsp;</span><span>&nbsp; def</span>" },
{ initialHTML: "<span>abc&nbsp; []</span><span>&nbsp; def</span>", expectedHTML: "<span>abc&nbsp; </span><span>&nbsp;def</span>" },
{ initialHTML: "<span>abc&nbsp; </span><span>[]&nbsp; def</span>", expectedHTML: "<span>abc&nbsp; </span><span>&nbsp;def</span>" },
{ initialHTML: "<span>abc&nbsp;&nbsp;[]</span><span> &nbsp;def</span>", expectedHTML: "<span>abc&nbsp;&nbsp;</span><span>&nbsp;def</span>" },
{ initialHTML: "<span>abc&nbsp;&nbsp;</span><span>[] &nbsp;def</span>", expectedHTML: "<span>abc&nbsp;&nbsp;</span><span>&nbsp;def</span>" },
{ initialHTML: "<span>abc &nbsp;[]</span><span>&nbsp; def</span>", expectedHTML: "<span>abc &nbsp;</span><span>&nbsp;def</span>" },
{ initialHTML: "<span>abc &nbsp;</span><span>[]&nbsp; def</span>", expectedHTML: "<span>abc &nbsp;</span><span>&nbsp;def</span>" },
{ initialHTML: "<span>abc&nbsp; </span><span>&nbsp;[] def</span>", expectedHTML: "<span>abc&nbsp; </span><span>&nbsp;def</span>" },
{ initialHTML: "<span>abc &nbsp;</span><span>&nbsp;[] def</span>", expectedHTML: "<span>abc &nbsp;</span><span>&nbsp;def</span>" },
{ initialHTML: "<span>abc &nbsp;</span><span> []&nbsp;def</span>", expectedHTML: "<span>abc &nbsp;</span><span>&nbsp;def</span>" },
{ initialHTML: "a[]<span style=white-space:pre;>b </span>c", expectedHTML: "a<span style=\"white-space:pre;\"> </span>c" },
{ initialHTML: "a<span style=white-space:pre;>b[] </span>c", expectedHTML: "a<span style=\"white-space:pre;\">b </span>c" },
{ initialHTML: "a<span style=white-space:pre;>b [] </span>c", expectedHTML: "a<span style=\"white-space:pre;\">b </span>c" },
{ initialHTML: "a<span style=white-space:pre;>b [] </span>c", expectedHTML: "a<span style=\"white-space:pre;\">b </span>c" },
{ initialHTML: "a<span style=white-space:pre;>b []</span>c", expectedHTML: "a<span style=\"white-space:pre;\">b </span>" },
{ initialHTML: "a<span style=white-space:pre;>b [] </span>", expectedHTML: "a<span style=\"white-space:pre;\">b </span>" },
{ initialHTML: "a[]<span style=white-space:pre;> </span>b", expectedHTML: "ab" },
{ initialHTML: "a&nbsp;&nbsp;&nbsp;[]<span style=white-space:pre;> </span>", expectedHTML: "a&nbsp;&nbsp;&nbsp;<span style=\"white-space:pre;\"> </span>" },
{ initialHTML: "a&nbsp;&nbsp;[]&nbsp;<span style=white-space:pre;> </span>", expectedHTML: "a&nbsp;&nbsp;<span style=\"white-space:pre;\"> </span>" },
{ initialHTML: "a&nbsp;[]&nbsp;&nbsp;<span style=white-space:pre;> </span>", expectedHTML: "a&nbsp;&nbsp;<span style=\"white-space:pre;\"> </span>" },
{ initialHTML: "a&nbsp;[]&nbsp;&nbsp;<span style=white-space:pre;>b </span>", expectedHTML: "a&nbsp;&nbsp;<span style=\"white-space:pre;\">b </span>" },
{ initialHTML: "a&nbsp;&nbsp;&nbsp;[]&nbsp;<span style=white-space:pre;> </span>", expectedHTML: "a&nbsp;&nbsp;&nbsp;<span style=\"white-space:pre;\"> </span>" },
{ initialHTML: "a&nbsp;&nbsp;[]&nbsp;&nbsp;<span style=white-space:pre;> </span>", expectedHTML: "a&nbsp; &nbsp;<span style=\"white-space:pre;\"> </span>" },
{ initialHTML: "a&nbsp;&nbsp;[]&nbsp;&nbsp;<span style=white-space:pre;>b </span>", expectedHTML: "a&nbsp; &nbsp;<span style=\"white-space:pre;\">b </span>" },
{ initialHTML: "<span style=white-space:pre;> [] </span>&nbsp;&nbsp;&nbsp;a", expectedHTML: "<span style=\"white-space:pre;\"> </span>&nbsp;&nbsp;&nbsp;a" },
{ initialHTML: "<span style=white-space:pre;> [] </span>&nbsp;&nbsp;&nbsp;a", expectedHTML: "<span style=\"white-space:pre;\"> </span>&nbsp; &nbsp;a" },
{ initialHTML: "<span style=white-space:pre;> []</span>&nbsp;&nbsp;&nbsp;&nbsp;a", expectedHTML: "<span style=\"white-space:pre;\"> </span>&nbsp; &nbsp;a" },
{ initialHTML: "<span style=white-space:pre;> </span>[]&nbsp;&nbsp;&nbsp;&nbsp;a", expectedHTML: "<span style=\"white-space:pre;\"> </span>&nbsp; &nbsp;a" },
]) {
test(function () {
let points = setupDiv(editor, currentTest.initialHTML);
selection.setBaseAndExtent(points[0], points[1], points[2], points[3]);
document.execCommand("forwarddelete", false, "");
assert_equals(editor.innerHTML, currentTest.expectedHTML);
}, `execCommand("forwarddelete", false, ""): "${currentTest.initialHTML}"`);
}
done();
}
window.addEventListener("load", runTests, {once: true});
</script>
</body>
</html>

View File

@ -0,0 +1,150 @@
<!doctype html>
<html>
<head>
<meta charset=utf-8>
<title>Testing normalizing white-space sequence after execCommand("insertlinebreak", false, "foo")</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
"use strict";
setup({explicit_done: true});
function runTests() {
// README:
// These tests based on the behavior of Chrome 83. This test does NOT define
// nor suggest any standard behavior (actually, some expected results might
// look odd), but this test must help you to understand how other browsers
// use different logic to normalize white-space sequence.
document.body.innerHTML = "<div contenteditable></div>";
let editor = document.querySelector("div[contenteditable]");
editor.focus();
let selection = document.getSelection();
function escape(str) {
return typeof(str) === "string" ? str.replace(/\u00A0/ig, "&nbsp;") : "";
}
function generateWhiteSpaces(num, lastIsAlwaysNBSP) {
let str = "";
for (let i = 0; i < num - 1; i++) {
str += i % 2 ? " " : "\u00A0";
}
str += lastIsAlwaysNBSP || num % 2 ? "\u00A0" : " ";
return escape(str);
}
function getDescriptionForTextNode(textNode) {
return selection.focusNode === textNode ?
`${escape(textNode.data.slice(0, selection.focusOffset))}[]${escape(textNode.data.slice(selection.focusOffset))}` :
escape(textNode);
}
editor.innerHTML = "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b";
selection.collapse(editor.firstChild, 0);
test(function () {
document.execCommand("insertlinebreak", false, "");
assert_equals(editor.innerHTML,
`<br>a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b`,
"Modified text is wrong");
}, `execCommand("insertlinebreak", false, "") at "${getDescriptionForTextNode(editor.firstChild)}"`);
editor.innerHTML = "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b";
selection.collapse(editor.firstChild, 1);
test(function () {
document.execCommand("insertlinebreak", false, "");
assert_equals(editor.innerHTML,
`a<br>${escape(generateWhiteSpaces(9, false))}b`,
"Modified text is wrong");
}, `execCommand("insertlinebreak", false, "") at "${getDescriptionForTextNode(editor.firstChild)}"`);
editor.innerHTML = "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b";
selection.collapse(editor.firstChild, 2);
test(function () {
document.execCommand("insertlinebreak", false, "");
assert_equals(editor.innerHTML,
`a&nbsp;<br>${escape(generateWhiteSpaces(8, false))}b`,
"Modified text is wrong");
}, `execCommand("insertlinebreak", false, "") at "${getDescriptionForTextNode(editor.firstChild)}"`);
editor.innerHTML = "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b";
selection.collapse(editor.firstChild, 3);
test(function () {
document.execCommand("insertlinebreak", false, "");
assert_equals(editor.innerHTML,
`a&nbsp;&nbsp;<br>${escape(generateWhiteSpaces(7, false))}b`,
"Modified text is wrong");
}, `execCommand("insertlinebreak", false, "") at "${getDescriptionForTextNode(editor.firstChild)}"`);
editor.innerHTML = "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b";
selection.collapse(editor.firstChild, 4);
test(function () {
document.execCommand("insertlinebreak", false, "");
assert_equals(editor.innerHTML,
`a&nbsp;&nbsp;&nbsp;<br>${escape(generateWhiteSpaces(6, false))}b`,
"Modified text is wrong");
}, `execCommand("insertlinebreak", false, "") at "${getDescriptionForTextNode(editor.firstChild)}"`);
editor.innerHTML = "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b";
selection.collapse(editor.firstChild, 5);
test(function () {
document.execCommand("insertlinebreak", false, "");
assert_equals(editor.innerHTML,
`a&nbsp;&nbsp;&nbsp;&nbsp;<br>${escape(generateWhiteSpaces(5, false))}b`,
"Modified text is wrong");
}, `execCommand("insertlinebreak", false, "") at "${getDescriptionForTextNode(editor.firstChild)}"`);
editor.innerHTML = "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b";
selection.collapse(editor.firstChild, 6);
test(function () {
document.execCommand("insertlinebreak", false, "");
assert_equals(editor.innerHTML,
`a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>${escape(generateWhiteSpaces(4, false))}b`,
"Modified text is wrong");
}, `execCommand("insertlinebreak", false, "") at "${getDescriptionForTextNode(editor.firstChild)}"`);
editor.innerHTML = "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b";
selection.collapse(editor.firstChild, 7);
test(function () {
document.execCommand("insertlinebreak", false, "");
assert_equals(editor.innerHTML,
`a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>${escape(generateWhiteSpaces(3, false))}b`,
"Modified text is wrong");
}, `execCommand("insertlinebreak", false, "") at "${getDescriptionForTextNode(editor.firstChild)}"`);
editor.innerHTML = "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b";
selection.collapse(editor.firstChild, 8);
test(function () {
document.execCommand("insertlinebreak", false, "");
assert_equals(editor.innerHTML,
`a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>${escape(generateWhiteSpaces(2, false))}b`,
"Modified text is wrong");
}, `execCommand("insertlinebreak", false, "") at "${getDescriptionForTextNode(editor.firstChild)}"`);
editor.innerHTML = "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b";
selection.collapse(editor.firstChild, 9);
test(function () {
document.execCommand("insertlinebreak", false, "");
assert_equals(editor.innerHTML,
`a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>${escape(generateWhiteSpaces(1, false))}b`,
"Modified text is wrong");
}, `execCommand("insertlinebreak", false, "") at "${getDescriptionForTextNode(editor.firstChild)}"`);
editor.innerHTML = "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b";
selection.collapse(editor.firstChild, 10);
test(function () {
document.execCommand("insertlinebreak", false, "");
assert_equals(editor.innerHTML,
`a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>b`,
"Modified text is wrong");
}, `execCommand("insertlinebreak", false, "") at "${getDescriptionForTextNode(editor.firstChild)}"`);
done();
}
window.addEventListener("load", runTests, {once: true});
</script>
</body>
</html>

View File

@ -0,0 +1,72 @@
<!doctype html>
<html>
<head>
<meta charset=utf-8>
<title>Testing normalizing white-space sequence after execCommand("insertparagraph", false, "foo")</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
"use strict";
setup({explicit_done: true});
function runTests() {
// README:
// These tests based on the behavior of Chrome 83. This test does NOT define
// nor suggest any standard behavior (actually, some expected results might
// look odd), but this test must help you to understand how other browsers
// use different logic to normalize white-space sequence.
document.body.innerHTML = "<div contenteditable></div>";
let editor = document.querySelector("div[contenteditable]");
editor.focus();
let selection = document.getSelection();
function escape(str) {
return typeof(str) === "string" ? str.replace(/\u00A0/ig, "&nbsp;") : "";
}
function generateWhiteSpaces(num, lastIsAlwaysNBSP) {
let str = "";
for (let i = 0; i < num - 1; i++) {
str += i % 2 ? " " : "\u00A0";
}
str += lastIsAlwaysNBSP || num % 2 ? "\u00A0" : " ";
return escape(str);
}
function getDescriptionForTextNode(textNode) {
return selection.focusNode === textNode ?
`${escape(textNode.data.slice(0, selection.focusOffset))}[]${escape(textNode.data.slice(selection.focusOffset))}` :
escape(textNode);
}
editor.innerHTML = "<div>a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b</div>";
selection.collapse(editor.firstChild.firstChild, 0);
test(function () {
document.execCommand("insertparagraph", false, "");
assert_equals(editor.innerHTML,
`<div><br></div><div>a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b</div>`,
"Modified text is wrong");
}, `execCommand("insertparagraph", false, "") at "<div>${getDescriptionForTextNode(editor.firstChild.firstChild)}</div>"`);
for (let i = 1; i <= 10; i++) {
editor.innerHTML = "<div>a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b</div>";
selection.collapse(editor.firstChild.firstChild, i);
test(function () {
let text = editor.firstChild.firstChild.data;
document.execCommand("insertparagraph", false, "");
assert_equals(editor.innerHTML,
`<div>${escape(text.slice(0, i))}</div><div>${escape(text.slice(i))}</div>`,
"Modified text is wrong");
}, `execCommand("insertparagraph", false, "") at "<div>${getDescriptionForTextNode(editor.firstChild.firstChild)}</div>"`);
}
done();
}
window.addEventListener("load", runTests, {once: true});
</script>
</body>
</html>

View File

@ -0,0 +1,526 @@
<!doctype html>
<html>
<head>
<meta charset=utf-8>
<title>Testing normalizing white-space sequence after execCommand("inserttext", false, "foo")</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
"use strict";
setup({explicit_done: true});
function runTests() {
// README:
// These tests based on the behavior of Chrome 83. This test does NOT define
// nor suggest any standard behavior (actually, some expected results might
// look odd), but this test must help you to understand how other browsers
// use different logic to normalize white-space sequence.
document.body.innerHTML = "<div contenteditable></div>";
let editor = document.querySelector("div[contenteditable]");
editor.focus();
let selection = document.getSelection();
function toPlaintext(str) {
return str.replace(/&nbsp;/g, "\u00A0");
}
function escape(str) {
return typeof(str) === "string" ? str.replace(/\u00A0/ig, "&nbsp;") : "";
}
function generateWhiteSpaces(num, lastIsAlwaysNBSP) {
if (!num) {
return "";
}
let str = "";
for (let i = 0; i < num - 1; i++) {
str += i % 2 ? " " : "\u00A0";
}
str += lastIsAlwaysNBSP || num % 2 ? "\u00A0" : " ";
return escape(str);
}
function getDescriptionForTextNode(textNode) {
return selection.focusNode === textNode ?
`${escape(textNode.data.slice(0, selection.focusOffset))}[]${escape(textNode.data.slice(selection.focusOffset))}` :
escape(textNode);
}
for (let i = 0; i < 12; i++) {
editor.innerHTML = `a${i === 1 ? " " : generateWhiteSpaces(i, false)}b`;
selection.collapse(editor.firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(escape(editor.firstChild.data),
`a${i === 0 ? " " : escape(generateWhiteSpaces(i + 1, false))}b`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "${getDescriptionForTextNode(editor.firstChild)}"`);
}
for (let i = 0; i < 12; i++) {
editor.innerHTML = `a${generateWhiteSpaces(i, true)}`;
selection.collapse(editor.firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(escape(editor.firstChild.data),
`a${escape(generateWhiteSpaces(i + 1, true))}`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "${getDescriptionForTextNode(editor.firstChild)}"`);
}
for (let i = 0; i < 12; i++) {
editor.innerHTML = `${generateWhiteSpaces(i, false)}b`;
selection.collapse(editor.firstChild, i);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(escape(editor.firstChild.data),
`${i === 0 ? "&nbsp;" : escape(generateWhiteSpaces(i + 1, false))}b`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "${getDescriptionForTextNode(editor.firstChild)}"`);
}
for (let i = 0; i < 12; i++) {
editor.innerHTML = `a${i === 0 ? " " : generateWhiteSpaces(i + 1, false)}b`;
selection.collapse(editor.firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(escape(editor.firstChild.data),
`a${i === 0 ? "&nbsp; " : escape(generateWhiteSpaces(i + 2, false))}b`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "${getDescriptionForTextNode(editor.firstChild)}"`);
}
editor.innerHTML = "a&nbsp;b";
selection.collapse(editor.firstChild, 1);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(escape(editor.firstChild.data), "a&nbsp; b", "Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "${getDescriptionForTextNode(editor.firstChild)}"`);
for (let i = 1; i <= 3; i++) {
editor.innerHTML = "a&nbsp;&nbsp;b";
selection.collapse(editor.firstChild, i);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(escape(editor.firstChild.data),
`a${escape(generateWhiteSpaces(3, false))}b`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "${getDescriptionForTextNode(editor.firstChild)}"`);
}
for (let i = 1; i <= 6; i++) {
editor.innerHTML = "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b";
selection.collapse(editor.firstChild, i);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(escape(editor.firstChild.data),
`a${escape(generateWhiteSpaces(6, false))}b`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "${getDescriptionForTextNode(editor.firstChild)}"`);
}
for (let i = 1; i <= 7; i++) {
editor.innerHTML = "a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b";
selection.collapse(editor.firstChild, i);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(escape(editor.firstChild.data),
`a${escape(generateWhiteSpaces(7, false))}b`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "${getDescriptionForTextNode(editor.firstChild)}"`);
}
for (let i = 0; i < 12; i++) {
editor.innerHTML = `a${generateWhiteSpaces(i)}b`;
selection.collapse(editor.firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, "\u00A0");
assert_equals(escape(editor.firstChild.data),
`a${i === 0 ? " " : escape(generateWhiteSpaces(i + 1, false))}b`,
"Modified text is wrong");
}, `execCommand("inserttext", false, "\\u00A0") at "${getDescriptionForTextNode(editor.firstChild)}"`);
}
for (let i = 0; i < 5; i++) {
editor.innerHTML = `a<span>${i === 0 ? " " : generateWhiteSpaces(i + 1)}</span>b`;
selection.collapse(editor.querySelector("span").firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(editor.innerHTML,
`a<span>${escape(generateWhiteSpaces(i + 2, true))}</span>b`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "a<span>${getDescriptionForTextNode(editor.querySelector("span").firstChild)}</span>b"`);
}
for (let i = 0; i < 5; i++) {
editor.innerHTML = `a<span>b${generateWhiteSpaces(i, true)}</span>c`;
selection.collapse(editor.querySelector("span").firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(editor.innerHTML,
`a<span>b${escape(generateWhiteSpaces(i + 1, true))}</span>c`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "a<span>${getDescriptionForTextNode(editor.querySelector("span").firstChild)}</span>c"`);
}
for (let i = 0; i < 5; i++) {
editor.innerHTML = `a<span>b${generateWhiteSpaces(i, true)}</span> c`;
selection.collapse(editor.querySelector("span").firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(editor.innerHTML,
`a<span>b${escape(generateWhiteSpaces(i + 1, true))}</span> c`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "a<span>${getDescriptionForTextNode(editor.querySelector("span").firstChild)}</span> c"`);
}
for (let i = 0; i < 5; i++) {
editor.innerHTML = `a<span>b${generateWhiteSpaces(i, true)}</span>&nbsp;c`;
selection.collapse(editor.querySelector("span").firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(editor.innerHTML,
`a<span>b${escape(generateWhiteSpaces(i + 1, true))}</span>&nbsp;c`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "a<span>${getDescriptionForTextNode(editor.querySelector("span").firstChild)}</span>&nbsp;c"`);
}
for (let i = 0; i < 5; i++) {
editor.innerHTML = `a<span>b${generateWhiteSpaces(i, true)}</span><span>c</span>`;
selection.collapse(editor.querySelector("span").firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(editor.innerHTML,
`a<span>b${escape(generateWhiteSpaces(i + 1, true))}</span><span>c</span>`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "a<span>${getDescriptionForTextNode(editor.querySelector("span").firstChild)}</span><span>c</span>"`);
}
for (let i = 0; i < 5; i++) {
editor.innerHTML = `a<span>b${generateWhiteSpaces(i, true)}</span><span> c</span>`;
selection.collapse(editor.querySelector("span").firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(editor.innerHTML,
`a<span>b${escape(generateWhiteSpaces(i + 1, true))}</span><span> c</span>`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "a<span>${getDescriptionForTextNode(editor.querySelector("span").firstChild)}</span><span> c</span>"`);
}
for (let i = 0; i < 5; i++) {
editor.innerHTML = `a<span>b${generateWhiteSpaces(i, true)}</span><span>&nbsp;c</span>`;
selection.collapse(editor.querySelector("span").firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(editor.innerHTML,
`a<span>b${escape(generateWhiteSpaces(i + 1, true))}</span><span>&nbsp;c</span>`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "a<span>${getDescriptionForTextNode(editor.querySelector("span").firstChild)}</span><span>&nbsp;c</span>"`);
}
for (let i = 0; i < 5; i++) {
editor.innerHTML = `a<span>b${generateWhiteSpaces(i, true)}</span><span><span>c</span></span>`;
selection.collapse(editor.querySelector("span").firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(editor.innerHTML,
`a<span>b${escape(generateWhiteSpaces(i + 1, true))}</span><span><span>c</span></span>`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "a<span>${getDescriptionForTextNode(editor.querySelector("span").firstChild)}</span><span><span>c</span></span>"`);
}
for (let i = 0; i < 5; i++) {
editor.innerHTML = `a<span>b${generateWhiteSpaces(i, true)}</span><span><span> c</span></span>`;
selection.collapse(editor.querySelector("span").firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(editor.innerHTML,
`a<span>b${escape(generateWhiteSpaces(i + 1, true))}</span><span><span> c</span></span>`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "a<span>${getDescriptionForTextNode(editor.querySelector("span").firstChild)}</span><span><span> c</span></span>"`);
}
for (let i = 0; i < 5; i++) {
editor.innerHTML = `a<span>b${generateWhiteSpaces(i, true)}</span><span><span>&nbsp;c</span></span>`;
selection.collapse(editor.querySelector("span").firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(editor.innerHTML,
`a<span>b${escape(generateWhiteSpaces(i + 1, true))}</span><span><span>&nbsp;c</span></span>`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "a<span>${getDescriptionForTextNode(editor.querySelector("span").firstChild)}</span><span><span>&nbsp;c</span></span>"`);
}
for (let i = 0; i < 5; i++) {
editor.innerHTML = `a<span><span>b${generateWhiteSpaces(i, true)}</span></span><span>c</span>`;
selection.collapse(editor.querySelector("span span").firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(editor.innerHTML,
`a<span><span>b${escape(generateWhiteSpaces(i + 1, true))}</span></span><span>c</span>`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "a<span><span>${getDescriptionForTextNode(editor.querySelector("span span").firstChild)}</span></span><span>c</span>"`);
}
for (let i = 0; i < 5; i++) {
editor.innerHTML = `a<span><span>b${generateWhiteSpaces(i, true)}</span></span><span> c</span>`;
selection.collapse(editor.querySelector("span span").firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(editor.innerHTML,
`a<span><span>b${escape(generateWhiteSpaces(i + 1, true))}</span></span><span> c</span>`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "a<span><span>${getDescriptionForTextNode(editor.querySelector("span span").firstChild)}</span></span><span> c</span>"`);
}
for (let i = 0; i < 5; i++) {
editor.innerHTML = `a<span><span>b${generateWhiteSpaces(i, true)}</span></span><span>&nbsp;c</span>`;
selection.collapse(editor.querySelector("span span").firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(editor.innerHTML,
`a<span><span>b${escape(generateWhiteSpaces(i + 1, true))}</span></span><span>&nbsp;c</span>`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "a<span><span>${getDescriptionForTextNode(editor.querySelector("span span").firstChild)}</span></span><span>&nbsp;c</span>"`);
}
for (let i = 2; i < 8; i++) {
editor.innerHTML = "ab";
selection.collapse(editor.firstChild, 1);
test(function () {
document.execCommand("inserttext", false, " ".repeat(i));
assert_equals(escape(editor.firstChild.data),
`a${i > 0 ? escape(generateWhiteSpaces(i, false)) : " "}b`,
"Modified text is wrong");
}, `execCommand("inserttext", false, "${" ".repeat(i)}") at "${getDescriptionForTextNode(editor.firstChild)}"`);
}
for (let i = 2; i < 8; i++) {
editor.innerHTML = "a";
selection.collapse(editor.firstChild, 1);
test(function () {
document.execCommand("inserttext", false, " ".repeat(i));
assert_equals(escape(editor.firstChild.data),
`a${i > 0 ? escape(generateWhiteSpaces(i, true)) : " "}`,
"Modified text is wrong");
}, `execCommand("inserttext", false, "${" ".repeat(i)}") at "${getDescriptionForTextNode(editor.firstChild)}"`);
}
for (let i = 2; i < 8; i++) {
editor.innerHTML = "ab";
selection.collapse(editor.firstChild, 1);
test(function () {
document.execCommand("inserttext", false, "\u00A0".repeat(i));
assert_equals(escape(editor.firstChild.data),
`a${i > 0 ? escape(generateWhiteSpaces(i, false)) : " "}b`,
"Modified text is wrong");
}, `execCommand("inserttext", false, "${"\\u00A0".repeat(i)}") at "${getDescriptionForTextNode(editor.firstChild)}"`);
}
for (let i = 2; i < 8; i++) {
editor.innerHTML = "a";
selection.collapse(editor.firstChild, 1);
test(function () {
document.execCommand("inserttext", false, "\u00A0".repeat(i));
assert_equals(escape(editor.firstChild.data),
`a${i > 0 ? escape(generateWhiteSpaces(i, true)) : " "}`,
"Modified text is wrong");
}, `execCommand("inserttext", false, "${"\\u00A0".repeat(i)}") at "${getDescriptionForTextNode(editor.firstChild)}"`);
}
for (let i = 0; i < 5; i++) {
editor.innerHTML = `a${generateWhiteSpaces(i, true)}<span style=white-space:pre>b</span>`;
selection.collapse(editor.firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(editor.innerHTML,
`a${escape(generateWhiteSpaces(i + 1, true))}<span style=\"white-space:pre\">b</span>`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "${getDescriptionForTextNode(editor.firstChild)}<span style=white-space:pre>b</span>"`);
}
for (let i = 0; i < 5; i++) {
editor.innerHTML = `a${generateWhiteSpaces(i, true)}<span style=white-space:pre> </span>`;
selection.collapse(editor.firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(editor.innerHTML,
`a${escape(generateWhiteSpaces(i + 1, true))}<span style=\"white-space:pre\"> </span>`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "${getDescriptionForTextNode(editor.firstChild)}<span style=white-space:pre> </span>"`);
}
for (let i = 0; i < 5; i++) {
editor.innerHTML = `a${generateWhiteSpaces(i, true)}<span style=white-space:pre>&nbsp;</span>`;
selection.collapse(editor.firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, " ");
assert_equals(editor.innerHTML,
`a${escape(generateWhiteSpaces(i + 1, true))}<span style=\"white-space:pre\">&nbsp;</span>`,
"Modified text is wrong");
}, `execCommand("inserttext", false, " ") at "${getDescriptionForTextNode(editor.firstChild)}<span style=white-space:pre>&nbsp;</span>"`);
}
for (let i = 0; i < 5; i++) {
editor.innerHTML = `a${generateWhiteSpaces(i, true)}<span style=white-space:pre>b</span>`;
selection.collapse(editor.firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, "\u00A0");
assert_equals(editor.innerHTML,
`a${escape(generateWhiteSpaces(i + 1, true))}<span style=\"white-space:pre\">b</span>`,
"Modified text is wrong");
}, `execCommand("inserttext", false, "\\u00A0") at "${getDescriptionForTextNode(editor.firstChild)}<span style=white-space:pre>b</span>"`);
}
for (let i = 0; i < 5; i++) {
editor.innerHTML = `a${generateWhiteSpaces(i, true)}<span style=white-space:pre> </span>`;
selection.collapse(editor.firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, "\u00A0");
assert_equals(editor.innerHTML,
`a${escape(generateWhiteSpaces(i + 1, true))}<span style=\"white-space:pre\"> </span>`,
"Modified text is wrong");
}, `execCommand("inserttext", false, "\\u00A0") at "${getDescriptionForTextNode(editor.firstChild)}<span style=white-space:pre> </span>"`);
}
for (let i = 0; i < 5; i++) {
editor.innerHTML = `a${generateWhiteSpaces(i, true)}<span style=white-space:pre>&nbsp;</span>`;
selection.collapse(editor.firstChild, i + 1);
test(function () {
document.execCommand("inserttext", false, "\u00A0");
assert_equals(editor.innerHTML,
`a${escape(generateWhiteSpaces(i + 1, true))}<span style=\"white-space:pre\">&nbsp;</span>`,
"Modified text is wrong");
}, `execCommand("inserttext", false, "\\u00A0") at "${getDescriptionForTextNode(editor.firstChild)}<span style=white-space:pre>&nbsp;</span>"`);
}
editor.innerHTML = "a&nbsp;&nbsp;c";
selection.collapse(editor.firstChild, 2);
test(function () {
document.execCommand("inserttext", false, "b");
assert_equals(escape(editor.firstChild.data), "a b c", "Modified text is wrong");
}, `execCommand("inserttext", false, "b") at "${getDescriptionForTextNode(editor.firstChild)}"`);
editor.innerHTML = "a&nbsp;&nbsp;&nbsp;&nbsp;c";
selection.collapse(editor.firstChild, 1);
test(function () {
document.execCommand("inserttext", false, "b");
assert_equals(escape(editor.firstChild.data), `ab${escape(generateWhiteSpaces(4))}c`, "Modified text is wrong");
}, `execCommand("inserttext", false, "b") at "${getDescriptionForTextNode(editor.firstChild)}"`);
editor.innerHTML = "a&nbsp;&nbsp;&nbsp;&nbsp;c";
selection.collapse(editor.firstChild, 2);
test(function () {
document.execCommand("inserttext", false, "b");
assert_equals(escape(editor.firstChild.data), `a b${escape(generateWhiteSpaces(3))}c`, "Modified text is wrong");
}, `execCommand("inserttext", false, "b") at "${getDescriptionForTextNode(editor.firstChild)}"`);
editor.innerHTML = "a&nbsp;&nbsp;&nbsp;&nbsp;c";
selection.collapse(editor.firstChild, 3);
test(function () {
document.execCommand("inserttext", false, "b");
assert_equals(escape(editor.firstChild.data),
`a${escape(generateWhiteSpaces(2))}b${escape(generateWhiteSpaces(2))}c`,
"Modified text is wrong");
}, `execCommand("inserttext", false, "b") at "${getDescriptionForTextNode(editor.firstChild)}"`);
editor.innerHTML = "a&nbsp;&nbsp;&nbsp;&nbsp;c";
selection.collapse(editor.firstChild, 4);
test(function () {
document.execCommand("inserttext", false, "b");
assert_equals(escape(editor.firstChild.data),
`a${escape(generateWhiteSpaces(3))}b c`,
"Modified text is wrong");
}, `execCommand("inserttext", false, "b") at "${getDescriptionForTextNode(editor.firstChild)}"`);
editor.innerHTML = "a&nbsp;&nbsp;&nbsp;&nbsp;c";
selection.collapse(editor.firstChild, 5);
test(function () {
document.execCommand("inserttext", false, "b");
assert_equals(escape(editor.firstChild.data), `a${escape(generateWhiteSpaces(4))}bc`, "Modified text is wrong");
}, `execCommand("inserttext", false, "b") at "${getDescriptionForTextNode(editor.firstChild)}"`);
// Test white space sequence split to multiple text node.
// - initialText: Set to data of text nodes. This must have "|" at least one.
// Then, the text will be split at every "|".
// Same as above test, only &nbsp; is handled at setting.
// "[]" means that caret position.
// - expectedText: Set to data of all text nodes as an array.
// Same as above test, only &nbsp; is handled before comparing.
for (const currentTest of [
{ initialText: "a[]|b", expectedText: ["a", "b"] },
{ initialText: "a []|b", expectedText: ["a ", "b"] },
{ initialText: "a |[]b", expectedText: ["a ", "b"] },
{ initialText: "a[]&nbsp;|b", expectedText: ["a&nbsp;", "b"] },
{ initialText: "a&nbsp;[]|b", expectedText: ["a&nbsp;", "b"] },
{ initialText: "a&nbsp;|[]b", expectedText: ["a&nbsp;", "b"] },
{ initialText: "a[]|&nbsp;b", expectedText: ["a", "&nbsp;b"] },
{ initialText: "a|[]&nbsp;b", expectedText: ["a", "&nbsp;b"] },
{ initialText: "a|&nbsp;[]b", expectedText: ["a", "&nbsp;b"] },
{ initialText: "a[] |&nbsp;b", expectedText: ["a ", "&nbsp;b"] },
{ initialText: "a []|&nbsp;b", expectedText: ["a ", "&nbsp;b"] },
{ initialText: "a |[]&nbsp;b", expectedText: ["a ", "&nbsp;b"] },
{ initialText: "a |&nbsp;[]b", expectedText: ["a ", "&nbsp;b"] },
{ initialText: "a[]&nbsp;| b", expectedText: ["a&nbsp;", " b"] },
{ initialText: "a&nbsp;[]| b", expectedText: ["a&nbsp;", " b"] },
{ initialText: "a&nbsp;|[] b", expectedText: ["a&nbsp;", " b"] },
{ initialText: "a&nbsp;| []b", expectedText: ["a&nbsp;", " b"] },
{ initialText: "a[]&nbsp;|&nbsp;b", expectedText: ["a&nbsp;", "&nbsp;b"] },
{ initialText: "a&nbsp;[]|&nbsp;b", expectedText: ["a&nbsp;", "&nbsp;b"] },
{ initialText: "a&nbsp;|[]&nbsp;b", expectedText: ["a&nbsp;", "&nbsp;b"] },
{ initialText: "a&nbsp;|&nbsp;[]b", expectedText: ["a&nbsp;", "&nbsp;b"] },
]) {
test(function () {
editor.innerHTML = "";
let caret = { container: null, offset: -1 };
for (let text of toPlaintext(currentTest.initialText).split("|")) {
let caretOffset = text.indexOf("[]");
if (caretOffset >= 0) {
text = text.slice(0, caretOffset) + text.slice(caretOffset + 2);
}
let textNode = document.createTextNode(text);
editor.appendChild(textNode);
if (caretOffset >= 0) {
caret = { container: textNode, offset: caretOffset };
}
}
selection.collapse(caret.container, caret.offset);
document.execCommand("inserttext", false, "");
let child = editor.firstChild;
for (let expectedText of currentTest.expectedText) {
expectedText = toPlaintext(expectedText);
let caretOffset = expectedText.indexOf("[]");
if (caretOffset >= 0) {
expectedText = expectedText.slice(0, caretOffset) + expectedText.slice(caretOffset + 2);
}
if (!child || child.nodeName !== "#text") {
assert_equals("", escape(expectedText), "Expected text node is not there");
if (caretOffset >= 0) {
assert_equals(-1, caretOffset, "Selection should be contained in this node");
}
} else {
assert_equals(escape(child.data), escape(expectedText), "Modified text is wrong");
if (caretOffset >= 0) {
assert_equals(selection.focusNode, child, "Selection focus node is wrong");
assert_equals(selection.focusOffset, caretOffset, "Selection focus offset is wrong");
assert_equals(selection.anchorNode, child, "Selection anchor node is wrong");
assert_equals(selection.anchorOffset, caretOffset, "Selection anchor offset is wrong");
}
}
child = child.nextSibling;
}
if (child && child.nodeName === "#text") {
assert_equals(escape(child.data), "", "Unexpected text node is there");
}
}, `execCommand("inserttext", false, ""): "${currentTest.initialText}"`);
}
done();
}
window.addEventListener("load", runTests, {once: true});
</script>
</body>
</html>