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