329 lines
10 KiB
HTML
329 lines
10 KiB
HTML
<!doctype html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="variant" content="?method=backspace&block=div">
|
|
<meta name="variant" content="?method=backspace&block=p">
|
|
<meta name="variant" content="?method=backspace&block=blockquote">
|
|
<meta name="variant" content="?method=forwarddelete&block=div">
|
|
<meta name="variant" content="?method=forwarddelete&block=p">
|
|
<meta name="variant" content="?method=forwarddelete&block=blockquote">
|
|
<meta name="variant" content="?method=select-boundary&block=div">
|
|
<meta name="variant" content="?method=select-boundary&block=p">
|
|
<meta name="variant" content="?method=select-boundary&block=blockquote">
|
|
<title>Tests for joining pre and other block element</title>
|
|
<script src="/resources/testharness.js"></script>
|
|
<script src="/resources/testharnessreport.js"></script>
|
|
<script src="/resources/testdriver.js"></script>
|
|
<script src="/resources/testdriver-vendor.js"></script>
|
|
<script src="/resources/testdriver-actions.js"></script>
|
|
<script src="../include/editor-test-utils.js"></script>
|
|
</head>
|
|
<body>
|
|
<div contenteditable></div>
|
|
<script>
|
|
"use strict";
|
|
|
|
const searchParams = new URLSearchParams(document.location.search);
|
|
const testingBackspace = searchParams.get("method") == "backspace";
|
|
const testingSelectBoundary = searchParams.get("method") == "select-boundary";
|
|
const commandName =
|
|
testingBackspace || testingSelectBoundary ? "delete" : "forwarddelete";
|
|
const editingHost = document.querySelector("div[contenteditable]");
|
|
const caretInLeft = (() => {
|
|
if (testingSelectBoundary) {
|
|
return "[";
|
|
}
|
|
return testingBackspace ? "" : "[]";
|
|
})();
|
|
const caretInRight = (() => {
|
|
if (testingSelectBoundary) {
|
|
return "]";
|
|
}
|
|
return testingBackspace ? "[]" : "";
|
|
})();
|
|
const tag = searchParams.get("block");
|
|
|
|
// These expectations are odd because they don't preserve white-space style
|
|
// coming from another element. However, this is traditional behavior so that
|
|
// browsers should not change the behavior.
|
|
const tests = [
|
|
{
|
|
initialHTML:
|
|
`<pre>abc${caretInLeft}</pre>` +
|
|
`<${tag}>${caretInRight}def</${tag}>`,
|
|
expectedHTML: [
|
|
"<pre>abcdef</pre>",
|
|
],
|
|
},
|
|
{
|
|
initialHTML:
|
|
`<${tag}>abc${caretInLeft}</${tag}>` +
|
|
`<pre>${caretInRight}def</pre>`,
|
|
expectedHTML: [
|
|
`<${tag}>abcdef</${tag}>`,
|
|
],
|
|
expectedHTMLWithStyledPre: [
|
|
`<${tag}>abc<span style="white-space:pre">def</span></${tag}>`,
|
|
],
|
|
},
|
|
{
|
|
initialHTML:
|
|
`<pre>abc${caretInLeft}</pre>` +
|
|
`<${tag}>${caretInRight}def<br>ghi</${tag}>`,
|
|
expectedHTML: [
|
|
`<pre>abcdef</pre>` +
|
|
`<${tag}>ghi</${tag}>`,
|
|
],
|
|
},
|
|
{
|
|
initialHTML:
|
|
`<pre>abc${caretInLeft}</pre>` +
|
|
`<${tag}>${caretInRight}def<div>ghi</div></${tag}>`,
|
|
expectedHTML: [
|
|
"<pre>abcdef</pre>" +
|
|
`<${tag}><div>ghi</div></${tag}>`,
|
|
],
|
|
skip: tag == "p",
|
|
},
|
|
{
|
|
initialHTML:
|
|
`<${tag}>abc${caretInLeft}</${tag}>` +
|
|
`<pre>${caretInRight}def\nghi</pre>`,
|
|
expectedHTML: [
|
|
`<${tag}>abcdef</${tag}>` +
|
|
"<pre>ghi</pre>",
|
|
],
|
|
expectedHTMLWithStyledPre: [
|
|
`<${tag}>abc<span style="white-space:pre">def</span></${tag}>` +
|
|
"<pre>ghi</pre>",
|
|
],
|
|
},
|
|
{
|
|
initialHTML:
|
|
`<${tag}>abc${caretInLeft}</${tag}>` +
|
|
`<pre>${caretInRight}def<br>ghi</pre>`,
|
|
expectedHTML: [
|
|
`<${tag}>abcdef</${tag}>` +
|
|
"<pre>ghi</pre>",
|
|
],
|
|
expectedHTMLWithStyledPre: [
|
|
`<${tag}>abc<span style="white-space:pre">def</span></${tag}>` +
|
|
"<pre>ghi</pre>",
|
|
],
|
|
},
|
|
{
|
|
initialHTML:
|
|
`<pre>abc${caretInLeft}</pre>` +
|
|
`<${tag}><b>${caretInRight}def</b></${tag}>`,
|
|
expectedHTML: [
|
|
"<pre>abc<b>def</b></pre>",
|
|
],
|
|
},
|
|
{
|
|
initialHTML:
|
|
`<pre>abc${caretInLeft}</pre>` +
|
|
`<${tag}><b>${caretInRight}def<br>ghi</b></${tag}>`,
|
|
expectedHTML: [
|
|
"<pre>abc<b>def</b></pre>" +
|
|
`<${tag}><b>ghi</b></${tag}>`,
|
|
],
|
|
},
|
|
{
|
|
initialHTML:
|
|
`<${tag}>abc${caretInLeft}</${tag}>` +
|
|
`<pre><b>${caretInRight}def\nghi</b></pre>`,
|
|
expectedHTML: [
|
|
`<${tag}>abc<b>def</b></${tag}>` +
|
|
"<pre><b>ghi</b></pre>",
|
|
],
|
|
expectedHTMLWithStyledPre: [
|
|
`<${tag}>abc<b style="white-space:pre">def</b></${tag}>` +
|
|
"<pre><b>ghi</b></pre>",
|
|
`<${tag}>abc<span style="white-space:pre"><b>def</b></span></${tag}>` +
|
|
"<pre><b>ghi</b></pre>",
|
|
],
|
|
},
|
|
{
|
|
initialHTML:
|
|
`<${tag}>abc${caretInLeft}</${tag}>` +
|
|
`<pre><b>${caretInRight}def<br>ghi</b></pre>`,
|
|
expectedHTML: [
|
|
`<${tag}>abc<b>def</b></${tag}>` +
|
|
"<pre><b>ghi</b></pre>",
|
|
],
|
|
expectedHTMLWithStyledPre: [
|
|
`<${tag}>abc<b style="white-space:pre">def</b></${tag}>` +
|
|
"<pre><b>ghi</b></pre>",
|
|
`<${tag}>abc<span style="white-space:pre"><b>def</b></span></${tag}>` +
|
|
"<pre><b>ghi</b></pre>",
|
|
],
|
|
},
|
|
{
|
|
initialHTML:
|
|
`<${tag}>abc${caretInLeft}</${tag}>` +
|
|
`<pre><b>${caretInRight}def</b>\nghi</pre>`,
|
|
expectedHTML: [
|
|
`<${tag}>abc<b>def</b></${tag}>` +
|
|
"<pre>ghi</pre>",
|
|
],
|
|
expectedHTMLWithStyledPre: [
|
|
`<${tag}>abc<b style="white-space:pre">def</b></${tag}>` +
|
|
"<pre>ghi</pre>",
|
|
`<${tag}>abc<span style="white-space:pre"><b>def</b></span></${tag}>` +
|
|
"<pre>ghi</pre>",
|
|
],
|
|
},
|
|
{
|
|
initialHTML:
|
|
`<${tag}>abc${caretInLeft}</${tag}>` +
|
|
`<pre><b>${caretInRight}def</b><br>ghi</pre>`,
|
|
expectedHTML: [
|
|
`<${tag}>abc<b>def</b></${tag}>` +
|
|
"<pre>ghi</pre>",
|
|
],
|
|
expectedHTMLWithStyledPre: [
|
|
`<${tag}>abc<b style="white-space:pre">def</b></${tag}>` +
|
|
"<pre>ghi</pre>",
|
|
`<${tag}>abc<span style="white-space:pre"><b>def</b></span></${tag}>` +
|
|
"<pre>ghi</pre>",
|
|
],
|
|
},
|
|
{
|
|
initialHTML:
|
|
`<${tag}>abc${caretInLeft}</${tag}>` +
|
|
`<pre><b>${caretInRight}def\n</b>ghi</pre>`,
|
|
expectedHTML: [
|
|
`<${tag}>abc<b>def</b></${tag}>` +
|
|
"<pre>ghi</pre>",
|
|
],
|
|
expectedHTMLWithStyledPre: [
|
|
`<${tag}>abc<b style="white-space:pre">def</b></${tag}>` +
|
|
`<pre>ghi</pre>`,
|
|
`<${tag}>abc<span style="white-space:pre"><b>def</b></span></${tag}>` +
|
|
"<pre>ghi</pre>",
|
|
],
|
|
},
|
|
{
|
|
initialHTML:
|
|
`<${tag}>abc${caretInLeft}</${tag}>` +
|
|
`<pre><b>${caretInRight}def<br></b>ghi</pre>`,
|
|
expectedHTML: [
|
|
`<${tag}>abc<b>def</b></${tag}>` +
|
|
"<pre>ghi</pre>",
|
|
],
|
|
expectedHTMLWithStyledPre: [
|
|
`<${tag}>abc<b style="white-space:pre">def</b></${tag}>` +
|
|
"<pre>ghi</pre>",
|
|
`<${tag}>abc<span style="white-space:pre"><b>def</b></span></${tag}>` +
|
|
"<pre>ghi</pre>",
|
|
],
|
|
},
|
|
// One linefeed at start of <pre> should be ignored.
|
|
// Note that if setupEditingHost() does not touch the text node in <pre>,
|
|
// the leading line break is ignored, but if it touches the text node,
|
|
// the value is set to as-is. Therefore, the following tests can work
|
|
// with empty caretInRight value.
|
|
{
|
|
initialHTML:
|
|
`<${tag}>abc${caretInLeft}</${tag}>` +
|
|
`<pre>\ndef\nghi</pre>`,
|
|
expectedHTML: [
|
|
`<${tag}>abcdef</${tag}>` +
|
|
`<pre>ghi</pre>`,
|
|
],
|
|
expectedHTMLWithStyledPre: [
|
|
`<${tag}>abc<span style="white-space:pre">def</span></${tag}>` +
|
|
"<pre>ghi</pre>",
|
|
],
|
|
skip: caretInRight !== "",
|
|
},
|
|
// When there are two line breaks at start of <pre>, the first one should be
|
|
// ignored by the parser but the second one should make empty first line.
|
|
// Therefore, the first empty line should be removed.
|
|
{
|
|
initialHTML:
|
|
`<${tag}>abc${caretInLeft}</${tag}>` +
|
|
`<pre>\n\ndef\nghi</pre>`,
|
|
expectedHTML: [
|
|
`<${tag}>abc</${tag}>` +
|
|
"<pre>def\nghi</pre>",
|
|
],
|
|
skip: caretInRight !== "",
|
|
},
|
|
];
|
|
const utils = new EditorTestUtils(editingHost);
|
|
|
|
const betweenBlockAndPre = new RegExp(`</${tag}><pre>`);
|
|
const betweenPreAndBlock = new RegExp(`</pre><${tag}>`);
|
|
function putStyleElement() {
|
|
const styleElement = document.createElement("style");
|
|
styleElement.textContent = "pre { white-space: pre; }";
|
|
document.head.appendChild(styleElement);
|
|
}
|
|
|
|
for (const specifyPreStyle of [false, true]) {
|
|
for (const t of tests) {
|
|
if (t.skip) {
|
|
continue;
|
|
}
|
|
if (specifyPreStyle && !t.expectedHTMLWithStyledPre) {
|
|
continue;
|
|
}
|
|
promise_test(async () => {
|
|
if (specifyPreStyle) {
|
|
putStyleElement();
|
|
}
|
|
try {
|
|
utils.setupEditingHost(t.initialHTML);
|
|
await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey());
|
|
utils.normalizeStyleAttributeValues();
|
|
assert_in_array(
|
|
editingHost.innerHTML,
|
|
specifyPreStyle ? t.expectedHTMLWithStyledPre : t.expectedHTML,
|
|
`white-space should${
|
|
!specifyPreStyle ? " not" : ""
|
|
} be preserved by <span> elements`
|
|
);
|
|
} finally {
|
|
if (specifyPreStyle) {
|
|
document.querySelector("style")?.remove();
|
|
}
|
|
}
|
|
}, `${commandName} at ${t.initialHTML.replace(/\n/g, "\\n")}${
|
|
specifyPreStyle ? " (with <style>pre { white-space: pre; }</style>)" : ""
|
|
}`);
|
|
|
|
// Repeat same tests with inserting a line break between the paragraphs.
|
|
const initialHTMLWithLineBreak =
|
|
t.initialHTML
|
|
.replace(betweenBlockAndPre, `</${tag}>\n<pre>`)
|
|
.replace(betweenPreAndBlock, `</pre>\n<${tag}>`);
|
|
promise_test(async () => {
|
|
if (specifyPreStyle) {
|
|
putStyleElement();
|
|
}
|
|
try {
|
|
utils.setupEditingHost(initialHTMLWithLineBreak);
|
|
await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey());
|
|
utils.normalizeStyleAttributeValues();
|
|
assert_in_array(
|
|
editingHost.innerHTML,
|
|
specifyPreStyle ? t.expectedHTMLWithStyledPre : t.expectedHTML,
|
|
`white-space should${
|
|
!specifyPreStyle ? " not" : ""
|
|
} be preserved by <span> elements (testing with a line break between paragraphs)`
|
|
);
|
|
} finally {
|
|
if (specifyPreStyle) {
|
|
document.querySelector("style")?.remove();
|
|
}
|
|
}
|
|
}, `${commandName} at ${initialHTMLWithLineBreak.replace(/\n/g, "\\n")}${
|
|
specifyPreStyle ? " (with <style>pre { white-space: pre; }</style>)" : ""
|
|
}`);
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|