test_paste_no_formatting.html (7202B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Test pasting formatted test into various fields</title> 6 <script src="/tests/SimpleTest/SimpleTest.js"></script> 7 <script src="/tests/SimpleTest/EventUtils.js"></script> 8 <link rel="stylesheet" href="/tests/SimpleTest/test.css"/> 9 </head> 10 <body> 11 12 <input id="input"> 13 <textarea id="textarea"></textarea> 14 <div id="editable" contenteditable="true"></div> 15 <div id="noneditable">Text</div> 16 17 <div id="source">Some <b>Bold</b> Text</div> 18 <script> 19 20 const includeCommonAncestor = SpecialPowers.getBoolPref( 21 "dom.serializer.includeCommonAncestor.enabled" 22 ); 23 const expectedText = "Some Bold Text"; 24 const expectedHTML = `${includeCommonAncestor ? "<div id=\"source\">" : ""}` + 25 `Some <b>Bold</b> Text` + 26 `${includeCommonAncestor ? "</div>" : ""}`; 27 28 const htmlPrefix = navigator.platform.includes("Win") 29 ? "<html><body>\n<!--StartFragment-->" 30 : ""; 31 const htmlPostfix = navigator.platform.includes("Win") 32 ? "<!--EndFragment-->\n</body>\n</html>" 33 : ""; 34 35 add_task(async function test_paste_formatted() { 36 window.getSelection().selectAllChildren(document.getElementById("source")); 37 synthesizeKey("c", { accelKey: true }); 38 39 function doKey(element, withShiftKey) 40 { 41 let inputEventPromise = new Promise(resolve => { 42 element.addEventListener("input", event => { 43 is(event.inputType, "insertFromPaste", "correct inputType"); 44 resolve(); 45 }, { once: true }); 46 }); 47 synthesizeKey("v", { accelKey: true, shiftKey: withShiftKey }); 48 return inputEventPromise; 49 } 50 51 function cancelEvent(event) { 52 event.preventDefault(); 53 } 54 55 // Paste into input and textarea 56 for (let fieldid of ["input", "textarea"]) { 57 const field = document.getElementById(fieldid); 58 field.focus(); 59 60 field.addEventListener("paste", cancelEvent); 61 doKey(field, false); 62 is( 63 field.value, 64 "", 65 `Nothing should be pasted into <${field.tagName.toLowerCase()}> when paste event is canceled (shift key is not pressed)` 66 ); 67 68 doKey(field, true); 69 is( 70 field.value, 71 "", 72 `Nothing should be pasted into <${field.tagName.toLowerCase()}> when paste event is canceled (shift key is pressed)` 73 ); 74 field.removeEventListener("paste", cancelEvent); 75 76 doKey(field, false); 77 is(field.value, expectedText, "paste into " + fieldid); 78 79 doKey(field, true); 80 is(field.value, expectedText + expectedText, "paste unformatted into " + field); 81 } 82 83 const selection = window.getSelection(); 84 85 const editable = document.getElementById("editable"); 86 const innerHTMLBeforeTest = editable.innerHTML; 87 88 (function test_pasteWithFormatIntoEditableArea() { 89 selection.selectAllChildren(editable); 90 selection.collapseToStart(); 91 editable.addEventListener("paste", cancelEvent); 92 doKey(editable, false); 93 is( 94 editable.innerHTML, 95 "", 96 "test_pasteWithFormatIntoEditableArea: Nothing should be pasted when paste event is canceled" 97 ); 98 editable.removeEventListener("paste", cancelEvent); 99 100 doKey(editable, false); 101 is( 102 editable.innerHTML, 103 expectedHTML, 104 "test_pasteWithFormatIntoEditableArea: Pasting with format should work as expected" 105 ); 106 editable.innerHTML = innerHTMLBeforeTest; 107 }()); 108 109 (function test_pasteWithoutFormatIntoEditableArea() { 110 selection.selectAllChildren(editable); 111 selection.collapseToEnd(); 112 doKey(editable, true); 113 is( 114 editable.innerHTML, 115 expectedText, 116 "test_pasteWithoutFormatIntoEditableArea: Pasting without format should work as expected", 117 ); 118 editable.innerHTML = innerHTMLBeforeTest; 119 })(); 120 121 (function test_pasteWithFormatIntoEditableAreaWhenHTMLEditorIsInReadonlyMode() { 122 getEditor().flags |= SpecialPowers.Ci.nsIEditor.eEditorReadonlyMask; 123 selection.selectAllChildren(editable); 124 selection.collapseToStart(); 125 let beforeInputEvents = []; 126 function onBeforeInput(aEvent) { 127 beforeInputEvents.push(aEvent); 128 } 129 editable.addEventListener("beforeinput", onBeforeInput); 130 doKey(editable, false); 131 const description = "test_pasteWithFormatIntoEditableAreaWhenHTMLEditorIsInReadonlyMode"; 132 is( 133 editable.innerHTML, 134 innerHTMLBeforeTest, 135 `${description}: Pasting with format should not work` 136 ); 137 is( 138 beforeInputEvents.length, 139 0, 140 `${description}: Pasting with format should not cause "beforeinput", but fired "${ 141 beforeInputEvents[0]?.inputType 142 }"` 143 ); 144 editable.removeEventListener("beforeinput", onBeforeInput); 145 editable.innerHTML = innerHTMLBeforeTest; 146 getEditor().flags &= ~SpecialPowers.Ci.nsIEditor.eEditorReadonlyMask; 147 })(); 148 149 (function test_pasteWithoutFormatIntoEditableAreaWhenHTMLEditorIsInReadonlyMode() { 150 getEditor().flags |= SpecialPowers.Ci.nsIEditor.eEditorReadonlyMask; 151 selection.selectAllChildren(editable); 152 selection.collapseToStart(); 153 let beforeInputEvents = []; 154 function onBeforeInput(aEvent) { 155 beforeInputEvents.push(aEvent); 156 } 157 editable.addEventListener("beforeinput", onBeforeInput); 158 doKey(editable, false); 159 const description = "test_pasteWithoutFormatIntoEditableAreaWhenHTMLEditorIsInReadonlyMode"; 160 is( 161 editable.innerHTML, 162 innerHTMLBeforeTest, 163 `${description}: Pasting with format should not work` 164 ); 165 is( 166 beforeInputEvents.length, 167 0, 168 `${description}: Pasting with format should not cause "beforeinput", but fired "${ 169 beforeInputEvents[0]?.inputType 170 }"` 171 ); 172 editable.removeEventListener("beforeinput", onBeforeInput); 173 editable.innerHTML = innerHTMLBeforeTest; 174 getEditor().flags &= ~SpecialPowers.Ci.nsIEditor.eEditorReadonlyMask; 175 })(); 176 177 let noneditable = document.getElementById("noneditable"); 178 selection.selectAllChildren(noneditable); 179 selection.collapseToStart(); 180 181 function getPasteResult() { 182 return new Promise(resolve => { 183 noneditable.addEventListener("paste", event => { 184 resolve({ 185 text: event.clipboardData.getData("text/plain"), 186 html: event.clipboardData.getData("text/html"), 187 }); 188 }, { once: true}); 189 }); 190 } 191 192 // Normal paste into non-editable area 193 let pastePromise = getPasteResult(); 194 doKey(noneditable, false); 195 is(noneditable.innerHTML, "Text", "paste into non-editable"); 196 197 let result = await pastePromise; 198 is(result.text, expectedText, "paste text into non-editable"); 199 is(result.html, 200 htmlPrefix + expectedHTML + htmlPostfix, 201 "paste html into non-editable"); 202 203 // Unformatted paste into non-editable area 204 pastePromise = getPasteResult(); 205 doKey(noneditable, true); 206 is(noneditable.innerHTML, "Text", "paste unformatted into non-editable"); 207 208 result = await pastePromise; 209 is(result.text, expectedText, "paste unformatted text into non-editable"); 210 // Formatted HTML text should not exist when pasting unformatted. 211 is(result.html, "", "paste unformatted html into non-editable"); 212 }); 213 214 function getEditor() { 215 const editingSession = SpecialPowers.wrap(window).docShell.editingSession; 216 return editingSession.getEditorForWindow(window); 217 } 218 </script> 219 </body>