special-paste.html (5026B)
1 <!doctype html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <meta name="timeout" content="long"> 6 <meta name="variant" content="?white-space=normal"> 7 <meta name="variant" content="?white-space=pre"> 8 <meta name="variant" content="?white-space=pre-line"> 9 <meta name="variant" content="?white-space=pre-wrap"> 10 <title>Pasting rich text into contenteditable=plaintext-only</title> 11 <script src="/resources/testharness.js"></script> 12 <script src="/resources/testharnessreport.js"></script> 13 <script src="/resources/testdriver.js"></script> 14 <script src="/resources/testdriver-vendor.js"></script> 15 <script src="/resources/testdriver-actions.js"></script> 16 <script src="../../../editing/include/editor-test-utils.js"></script> 17 <script> 18 "use strict"; 19 20 const searchParams = new URLSearchParams(document.location.search); 21 const whiteSpace = searchParams.get("white-space"); 22 const useBR = whiteSpace == "normal"; 23 const isMac = navigator.platform.includes("Mac"); 24 25 addEventListener("load", () => { 26 const placeholderForCopy = document.createElement("div"); 27 document.body.appendChild(placeholderForCopy); 28 const editingHost = document.createElement("div"); 29 editingHost.style.whiteSpace = whiteSpace; 30 editingHost.contentEditable = "plaintext-only"; 31 document.body.appendChild(editingHost); 32 editingHost.focus(); 33 editingHost.getBoundingClientRect(); 34 const utils = new EditorTestUtils(editingHost); 35 let lastBeforeInput; 36 editingHost.addEventListener("beforeinput", event => lastBeforeInput = event); 37 38 promise_test(async t => { 39 placeholderForCopy.innerHTML = "<b>abc</b>"; 40 document.activeElement?.blur(); 41 getSelection().selectAllChildren(placeholderForCopy); 42 await utils.sendCopyShortcutKey(); 43 utils.setupEditingHost("A[]B"); 44 lastBeforeInput = undefined; 45 await new test_driver.Actions() 46 .keyDown(isMac ? utils.kMeta : utils.kControl) 47 .keyDown(utils.kShift) 48 .keyDown("v") 49 .keyUp("v") 50 .keyUp(utils.kShift) 51 .keyUp(isMac ? utils.kMeta : utils.kControl) 52 .send(); 53 test(() => { 54 assert_equals(lastBeforeInput?.inputType, "insertFromPaste", `inputType should be "insertFromPaste"`); 55 assert_equals(lastBeforeInput?.data, null, `data should be null`); 56 assert_true( 57 String(lastBeforeInput?.dataTransfer?.getData("text/html")).includes(placeholderForCopy.innerHTML), 58 `dataTransfer should have the copied HTML source` 59 ); 60 }, `${t.name}: beforeinput`); 61 test(() => { 62 assert_equals(editingHost.innerHTML, "AabcB", "<b> should not be pasted"); 63 }, `${t.name}: pasted result`); 64 }, "Pasting without format"); 65 66 // FIXME: I don't know why Ctrl-middle click fails on macOS (it's not Command). 67 if (!navigator.platform.includes("Mac")) { 68 promise_test(async t => { 69 placeholderForCopy.innerHTML = "<b>abc</b>"; 70 document.activeElement?.blur(); 71 getSelection().selectAllChildren(placeholderForCopy); 72 await utils.sendCopyShortcutKey(); 73 // For primary selection on Linux, we need to select text with user input emulation. 74 getSelection().collapse(placeholderForCopy, 0); 75 const arrowRight = "\uE014"; 76 await new test_driver.Actions() 77 .keyDown(utils.kShift) 78 .keyDown(arrowRight) 79 .keyUp(arrowRight) 80 .keyDown(arrowRight) 81 .keyUp(arrowRight) 82 .keyDown(arrowRight) 83 .keyUp(arrowRight) 84 .keyUp(utils.kShift) 85 .send(); 86 utils.setupEditingHost("{}<br>"); 87 lastBeforeInput = undefined; 88 const actions = new test_driver.Actions(); 89 await actions 90 .pointerMove(1, 1, {origin: "viewport"}) 91 .pointerMove(0, 0, {origin: editingHost}) 92 .keyDown(utils.kControl) 93 .pointerDown({button: actions.ButtonType.MIDDLE}) 94 .pointerUp({button: actions.ButtonType.MIDDLE}) 95 .keyUp(utils.kControl) 96 .send(); 97 test(() => { 98 assert_equals( 99 lastBeforeInput?.inputType, 100 "insertFromPasteAsQuotation", 101 `inputType should be "insertFromPasteAsQuotation"` 102 ); 103 assert_equals(lastBeforeInput?.data, null, `data should be null`); 104 assert_true( 105 String(lastBeforeInput?.dataTransfer?.getData("text/html")).includes(placeholderForCopy.innerHTML), 106 `dataTransfer should have the copied HTML source` 107 ); 108 }, `${t.name}: beforeinput`); 109 test(() => { 110 if (useBR) { 111 assert_equals(editingHost.innerHTML, "> abc<br><br><br>", "<b> should not be pasted"); 112 } else { 113 assert_in_array( 114 editingHost.innerHTML, 115 // The last break is a padding line break to make the last empty line visible. 116 // Therefore, it should not appear in `.textContent`. So, only the last line 117 // break should be <br>. 118 "> abc\n\n<br>", 119 "<b> should not be pasted" 120 ); 121 } 122 }, `${t.name}: pasted result`); 123 }, "Pasting as quotation"); 124 } 125 }, {once: true}); 126 </script> 127 </head> 128 <body></body> 129 </html>