typing-around-link-element-at-non-collapsed-selection.tentative.html (8085B)
1 <!doctype html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <meta name="timeout" content="long"> 6 <meta name="variant" content="?target=ContentEditable"> 7 <meta name="variant" content="?target=ContentEditable&parent=b"> 8 <meta name="variant" content="?target=ContentEditable&child=b"> 9 <meta name="variant" content="?target=ContentEditable&parent=b&child=i"> 10 <meta name="variant" content="?target=DesignMode"> 11 <meta name="variant" content="?target=DesignMode&parent=b"> 12 <meta name="variant" content="?target=DesignMode&child=b"> 13 <meta name="variant" content="?target=DesignMode&parent=b&child=i"> 14 <title>Testing inserting content at non-collapsed selection around link element</title> 15 <script src="/resources/testharness.js"></script> 16 <script src="/resources/testharnessreport.js"></script> 17 <script src="/resources/testdriver.js"></script> 18 <script src="/resources/testdriver-vendor.js"></script> 19 <script src="/resources/testdriver-actions.js"></script> 20 <script src="../include/editor-test-utils.js"></script> 21 </head> 22 <body> 23 <div contenteditable></div> 24 <iframe srcdoc=" 25 <!doctype html> 26 <html> 27 <script>document.designMode='on';</script> 28 <script src='/resources/testdriver.js'></script> 29 <script src='/resources/testdriver-vendor.js'></script> 30 <script src='/resources/testdriver-actions.js'></script> 31 <body></body> 32 </html>"></iframe> 33 <script> 34 "use strict"; 35 36 const params = new URLSearchParams(location.search.substring(1)); 37 const kTarget = params.get("target"); 38 const kParentTag = params.get("parent") === null 39 ? ["", ""] 40 : [`<${params.get("parent")}>`, `</${params.get("parent")}>`]; 41 const kChildTag = params.get("child") === null 42 ? ["", ""] 43 : [`<${params.get("child")}>`, `</${params.get("child")}>`]; 44 const kLinkDesc = (() => { 45 let result = "" 46 if (kParentTag[0] !== "") { 47 result += `in ${kParentTag[0]} `; 48 if (kChildTag[0] !== "") { 49 result += "and "; 50 } 51 } 52 if (kChildTag[0] !== "") { 53 result += `containing ${kChildTag[0]} `; 54 } 55 return result; 56 })(); 57 const kNewContainerOfLink = (() => { 58 if (kParentTag !== "" && kChildTag !== "") { 59 return [`${kParentTag[0]}${kChildTag[0]}`, `${kChildTag[1]}${kParentTag[1]}`]; 60 } 61 if (kParentTag !== "") { 62 return kParentTag; 63 } 64 if (kChildTag !== "") { 65 return kChildTag; 66 } 67 return ["", ""]; 68 })(); 69 70 function getEditingHost() { 71 return kTarget === "ContentEditable" 72 ? document.querySelector("div[contenteditable]") 73 : document.querySelector("iframe").contentDocument.body; 74 } 75 76 function addPromiseTest(test) { 77 promise_test(async () => { 78 let editingHost = getEditingHost(); 79 let utils = new EditorTestUtils(editingHost); 80 utils.setupEditingHost(test.innerHTML); 81 utils.window.focus(); 82 utils.document.body.focus(); 83 editingHost.focus(); 84 await test.run(utils); 85 if (Array.isArray(test.expectedResult)) { 86 assert_in_array(editingHost.innerHTML, test.expectedResult); 87 } else { 88 assert_equals(editingHost.innerHTML, test.expectedResult); 89 } 90 }, `${test.description} in ${test.innerHTML}`); 91 } 92 93 promise_test(async () => { 94 await new Promise(resolve => { 95 addEventListener("load", resolve, { once: true }); 96 }); 97 }, ""); 98 99 for (const test of [ 100 ["Direct typing", utils => {}], 101 ["Backspace", utils => { return utils.sendBackspaceKey(); }], 102 ["Delete", utils => { return utils.sendDeleteKey(); }], 103 ["execCommand(\"delete\")", utils => { utils.document.execCommand("delete", false); }], 104 ["execCommand(\"forwarddelete\")", utils => { utils.document.execCommand("forwarddelete", false); }], 105 ]) { 106 107 addPromiseTest({ 108 description: `Inserting "XY" after deleting first character of a link ${kLinkDesc}(${test[0]})`, 109 innerHTML: `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}[z]abc${kChildTag[1]}</a>${kParentTag[1]}</p>`, 110 run: async (utils) => { 111 await test[1](utils); 112 await utils.sendKey("X", utils.kShiftKey); 113 await utils.sendKey("Y", utils.kShiftKey); 114 }, 115 expectedResult: (() => { 116 if (test[0] === "Direct typing") { 117 return [ 118 `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}XYabc${kChildTag[1]}</a>${kParentTag[1]}</p>`, 119 `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}XYabc${kChildTag[1]}</a>${kParentTag[1]}<br></p>`, 120 ]; 121 } 122 return [ 123 `<p>${kNewContainerOfLink[0]}XY<a href="about:blank">abc</a>${kNewContainerOfLink[1]}</p>`, 124 `<p>${kNewContainerOfLink[0]}XY<a href="about:blank">abc</a>${kNewContainerOfLink[1]}<br></p>`, 125 ]; 126 })(), 127 }); 128 129 addPromiseTest({ 130 description: `Inserting "XY" after deleting last character in a non-collapsed range of a link ${kLinkDesc}(${test[0]})`, 131 innerHTML: `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}abc[d]${kChildTag[1]}</a>${kParentTag[1]}</p>`, 132 run: async (utils) => { 133 await test[1](utils); 134 await utils.sendKey("X", utils.kShiftKey); 135 await utils.sendKey("Y", utils.kShiftKey); 136 }, 137 expectedResult: (() => { 138 if (test[0] === "Direct typing") { 139 return [ 140 `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}abcXY${kChildTag[1]}</a>${kParentTag[1]}</p>`, 141 `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}abcXY${kChildTag[1]}</a>${kParentTag[1]}<br></p>`, 142 ]; 143 } 144 return [ 145 `<p>${kNewContainerOfLink[0]}<a href="about:blank">abc</a>XY${kNewContainerOfLink[1]}</p>`, 146 `<p>${kNewContainerOfLink[0]}<a href="about:blank">abc</a>XY${kNewContainerOfLink[1]}<br></p>`, 147 ]; 148 })(), 149 }); 150 151 addPromiseTest({ 152 description: `Inserting "XY" after deleting text after middle of a link ${kLinkDesc}(${test[0]})`, 153 innerHTML: `<p>${kParentTag[0]}<a href="about:blank">${kChildTag[0]}ab[cd${kChildTag[1]}</a>de]f${kParentTag[1]}</p>`, 154 run: async (utils) => { 155 await test[1](utils); 156 await utils.sendKey("X", utils.kShiftKey); 157 await utils.sendKey("Y", utils.kShiftKey); 158 }, 159 expectedResult: [ 160 `<p>${kNewContainerOfLink[0]}<a href="about:blank">ab</a>XY${kChildTag[1]}f${kParentTag[1]}</p>`, 161 `<p>${kNewContainerOfLink[0]}<a href="about:blank">ab</a>XY${kChildTag[1]}f${kParentTag[1]}<br></p>`, 162 ], 163 }); 164 165 addPromiseTest({ 166 description: `Inserting "XY" after deleting text before middle of a link ${kLinkDesc}(${test[0]})`, 167 innerHTML: `<p>${kParentTag[0]}a[bc<a href="about:blank">${kChildTag[0]}de]f${kChildTag[1]}</a>${kParentTag[1]}</p>`, 168 run: async (utils) => { 169 await test[1](utils); 170 await utils.sendKey("X", utils.kShiftKey); 171 await utils.sendKey("Y", utils.kShiftKey); 172 }, 173 expectedResult: [ 174 `<p>${kParentTag[0]}aXY<a href="about:blank">${kChildTag[0]}f${kChildTag[1]}</a>${kParentTag[1]}</p>`, 175 `<p>${kParentTag[0]}aXY<a href="about:blank">${kChildTag[0]}f${kChildTag[1]}</a>${kParentTag[1]}<br></p>`, 176 ], 177 }); 178 179 if (kParentTag[0] !== "" || kChildTag[0] !== "") { 180 continue; 181 } 182 183 addPromiseTest({ 184 description: `Inserting "XY" after deleting text between 2 same links (${test[0]})`, 185 innerHTML: '<p><a href="about:blank">a[bc</a><a href="about:blank">de]f</a></p>', 186 run: async (utils) => { 187 await test[1](utils); 188 await utils.sendKey("X", utils.kShiftKey); 189 await utils.sendKey("Y", utils.kShiftKey); 190 }, 191 expectedResult: [ 192 '<p><a href="about:blank">a</a>XY<a href="about:blank">f</a></p>', 193 '<p><a href="about:blank">a</a>XY<a href="about:blank">f</a><br></p>', 194 ], 195 }); 196 197 addPromiseTest({ 198 description: `Inserting "XY" after deleting text between 2 different links (${test[0]})`, 199 innerHTML: '<p><a href="about:blank">a[bc</a><a href="http://example.com/">de]f</a></p>', 200 run: async (utils) => { 201 await test[1](utils); 202 await utils.sendKey("X", utils.kShiftKey); 203 await utils.sendKey("Y", utils.kShiftKey); 204 }, 205 expectedResult: [ 206 '<p><a href="about:blank">a</a>XY<a href="http://example.com/">f</a></p>', 207 '<p><a href="about:blank">a</a>XY<a href="http://example.com/">f</a><br></p>', 208 ], 209 }); 210 } 211 212 </script> 213 </body> 214 </html>