1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Testing `nsIHTMLEditor.insertElementAtSelection()`</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
</head>
<body>
<script>
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(runTests);
function getRangeDescription(range) {
function getNodeDescription(node) {
if (!node) {
return "null";
}
switch (node.nodeType) {
case Node.TEXT_NODE:
case Node.COMMENT_NODE:
case Node.CDATA_SECTION_NODE:
return `${node.nodeName} "${node.data}"`;
case Node.ELEMENT_NODE:
return `<${node.nodeName.toLowerCase()}${
node.hasAttribute("id")
? ` id="${node.getAttribute("id")}"`
: ""
}${
node.hasAttribute("class")
? ` class="${node.getAttribute("class")}"`
: ""
}${
node.hasAttribute("contenteditable")
? ` contenteditable="${node.getAttribute("contenteditable")}"`
: ""
}>`;
default:
return `${node.nodeName}`;
}
}
if (range === null) {
return "null";
}
if (range === undefined) {
return "undefined";
}
return range.startContainer == range.endContainer &&
range.startOffset == range.endOffset
? `(${getNodeDescription(range.startContainer)}, ${range.startOffset})`
: `(${getNodeDescription(range.startContainer)}, ${
range.startOffset
}) - (${getNodeDescription(range.endContainer)}, ${range.endOffset})`;
}
function doTest(aEditingHost, aHTMLEditor, aDeleteSelection) {
const description = `aDeleteSelection=${aDeleteSelection}:`;
(() => {
aEditingHost.innerHTML = "abc";
aEditingHost.focus();
getSelection().collapse(aEditingHost.firstChild, 0);
const p = document.createElement("p");
p.appendChild(document.createElement("br"));
aHTMLEditor.insertElementAtSelection(p, aDeleteSelection);
is(
aEditingHost.innerHTML,
"<p><br></p>abc",
`${description} The <p> element should be inserted before the text node when selection is collapsed at start of the text node`
);
is(
getRangeDescription(getSelection().getRangeAt(0)),
'(<div contenteditable="">, 1)',
`${description} The selection should be collapsed after the inserted <p> element`
);
})();
(() => {
aEditingHost.innerHTML = "abc";
aEditingHost.focus();
getSelection().collapse(aEditingHost.firstChild, 1);
const p = document.createElement("p");
p.appendChild(document.createElement("br"));
aHTMLEditor.insertElementAtSelection(p, aDeleteSelection);
is(
aEditingHost.innerHTML,
"a<p><br></p>bc",
`${description} The <p> element should be inserted middle of the text node when selection is collapsed at middle of the text node`
);
is(
getRangeDescription(getSelection().getRangeAt(0)),
'(<div contenteditable="">, 2)',
`${description} The selection should be collapsed after the inserted <p> element (i.e., at right text node)`
);
})();
(() => {
aEditingHost.innerHTML = "abc";
aEditingHost.focus();
getSelection().collapse(aEditingHost.firstChild, 3);
const p = document.createElement("p");
p.appendChild(document.createElement("br"));
aHTMLEditor.insertElementAtSelection(p, aDeleteSelection);
is(
aEditingHost.innerHTML,
"abc<p><br></p>",
`${description} The <p> element should be inserted after the text node when selection is collapsed at end of the text node`
);
is(
getRangeDescription(getSelection().getRangeAt(0)),
'(<div contenteditable="">, 2)',
`${description} The selection should be collapsed at end of the editing host`
);
})();
(() => {
aEditingHost.innerHTML = "abc";
aEditingHost.focus();
getSelection().setBaseAndExtent(aEditingHost.firstChild, 0, aEditingHost.firstChild, 1);
const p = document.createElement("p");
p.appendChild(document.createElement("br"));
aHTMLEditor.insertElementAtSelection(p, aDeleteSelection);
is(
aEditingHost.innerHTML,
aDeleteSelection ? "<p><br></p>bc" : "a<p><br></p>bc",
`${description} The <p> element should be inserted after selected character when selection selects the first character of the text node`
);
is(
getRangeDescription(getSelection().getRangeAt(0)),
`(<div contenteditable="">, ${aDeleteSelection ? "1" : "2"})`,
`${description} The selection should be collapsed after the inserted <p> element (when selection selected the first character)`
);
})();
(() => {
aEditingHost.innerHTML = "abc";
aEditingHost.focus();
getSelection().setBaseAndExtent(aEditingHost.firstChild, 1, aEditingHost.firstChild, 2);
const p = document.createElement("p");
p.appendChild(document.createElement("br"));
aHTMLEditor.insertElementAtSelection(p, aDeleteSelection);
is(
aEditingHost.innerHTML,
aDeleteSelection ? "a<p><br></p>c" : "ab<p><br></p>c",
`${description} The <p> element should be inserted after selected character when selection selects a middle character of the text node`
);
is(
getRangeDescription(getSelection().getRangeAt(0)),
'(<div contenteditable="">, 2)',
`${description} The selection should be collapsed after the inserted <p> element (i.e., at right text node, when selection selected the middle character)`
);
})();
(() => {
aEditingHost.innerHTML = "abc";
aEditingHost.focus();
getSelection().setBaseAndExtent(aEditingHost.firstChild, 2, aEditingHost.firstChild, 3);
const p = document.createElement("p");
p.appendChild(document.createElement("br"));
aHTMLEditor.insertElementAtSelection(p, aDeleteSelection);
is(
aEditingHost.innerHTML,
aDeleteSelection ? "ab<p><br></p>" : "abc<p><br></p>",
`${description} The <p> element should be inserted after selected character when selection selects the last character of the text node`
);
is(
getRangeDescription(getSelection().getRangeAt(0)),
'(<div contenteditable="">, 2)',
`${description} The selection should be collapsed at end of the editing host (when selection selected the last character)`
);
})();
}
async function runTests() {
const editingHost = document.createElement("div");
editingHost.setAttribute("contenteditable", "");
document.body.appendChild(editingHost);
const editor =
SpecialPowers.
wrap(window).
docShell.
editingSession.
getEditorForWindow(window).
QueryInterface(SpecialPowers.Ci.nsIHTMLEditor);
doTest(editingHost, editor, true);
doTest(editingHost, editor, false);
SimpleTest.finish();
}
</script>
</body>
</html>
|