insertparagraph-in-inline-editing-host.tentative.html (18574B)
1 <!doctype html> 2 <meta chareset="utf-8"> 3 <meta name="timeout" content="long"> 4 5 <meta name="variant" content="?white-space=normal&display=inline&method=enter"> 6 <meta name="variant" content="?white-space=normal&display=inline&method=shift-enter"> 7 <meta name="variant" content="?white-space=normal&display=inline-block&method=enter"> 8 <meta name="variant" content="?white-space=normal&display=inline-block&method=shift-enter"> 9 <meta name="variant" content="?white-space=normal&display=block&method=enter"> 10 <meta name="variant" content="?white-space=normal&display=block&method=shift-enter"> 11 <meta name="variant" content="?white-space=normal&display=list-item&method=enter"> 12 <meta name="variant" content="?white-space=normal&display=list-item&method=shift-enter"> 13 <meta name="variant" content="?white-space=normal&display=table-cell&method=enter"> 14 <meta name="variant" content="?white-space=normal&display=table-cell&method=shift-enter"> 15 16 <meta name="variant" content="?white-space=pre&display=inline&method=enter"> 17 <meta name="variant" content="?white-space=pre&display=inline&method=shift-enter"> 18 <meta name="variant" content="?white-space=pre&display=inline-block&method=enter"> 19 <meta name="variant" content="?white-space=pre&display=inline-block&method=shift-enter"> 20 <meta name="variant" content="?white-space=pre&display=block&method=enter"> 21 <meta name="variant" content="?white-space=pre&display=block&method=shift-enter"> 22 <meta name="variant" content="?white-space=pre&display=list-item&method=enter"> 23 <meta name="variant" content="?white-space=pre&display=list-item&method=shift-enter"> 24 <meta name="variant" content="?white-space=pre&display=table-cell&method=enter"> 25 <meta name="variant" content="?white-space=pre&display=table-cell&method=shift-enter"> 26 27 <meta name="variant" content="?white-space=pre-line&display=inline&method=enter"> 28 <meta name="variant" content="?white-space=pre-line&display=inline&method=shift-enter"> 29 <meta name="variant" content="?white-space=pre-line&display=inline-block&method=enter"> 30 <meta name="variant" content="?white-space=pre-line&display=inline-block&method=shift-enter"> 31 <meta name="variant" content="?white-space=pre-line&display=block&method=enter"> 32 <meta name="variant" content="?white-space=pre-line&display=block&method=shift-enter"> 33 <meta name="variant" content="?white-space=pre-line&display=list-item&method=enter"> 34 <meta name="variant" content="?white-space=pre-line&display=list-item&method=shift-enter"> 35 <meta name="variant" content="?white-space=pre-line&display=table-cell&method=enter"> 36 <meta name="variant" content="?white-space=pre-line&display=table-cell&method=shift-enter"> 37 38 <meta name="variant" content="?white-space=pre-wrap&display=inline&method=enter"> 39 <meta name="variant" content="?white-space=pre-wrap&display=inline&method=shift-enter"> 40 <meta name="variant" content="?white-space=pre-wrap&display=inline-block&method=enter"> 41 <meta name="variant" content="?white-space=pre-wrap&display=inline-block&method=shift-enter"> 42 <meta name="variant" content="?white-space=pre-wrap&display=block&method=enter"> 43 <meta name="variant" content="?white-space=pre-wrap&display=block&method=shift-enter"> 44 <meta name="variant" content="?white-space=pre-wrap&display=list-item&method=enter"> 45 <meta name="variant" content="?white-space=pre-wrap&display=list-item&method=shift-enter"> 46 <meta name="variant" content="?white-space=pre-wrap&display=table-cell&method=enter"> 47 <meta name="variant" content="?white-space=pre-wrap&display=table-cell&method=shift-enter"> 48 49 <title>Line breaking in inline editing host</title> 50 <script src="/resources/testharness.js"></script> 51 <script src="/resources/testharnessreport.js"></script> 52 <script src="/resources/testdriver.js"></script> 53 <script src="/resources/testdriver-vendor.js"></script> 54 <script src="/resources/testdriver-actions.js"></script> 55 <script src="../include/editor-test-utils.js"></script> 56 <div><span contenteditable></span></div> 57 <script> 58 "use strict"; 59 60 const searchParams = new URLSearchParams(document.location.search); 61 const testingInsertParagraph = searchParams.get("method") == "enter"; 62 const whiteSpace = searchParams.get("white-space"); 63 const display = searchParams.get("display"); 64 65 const isPreformatted = 66 whiteSpace == "pre" || whiteSpace == "pre-line" || whiteSpace == "pre-wrap"; 67 68 const editingHost = document.querySelector("span[contenteditable]"); 69 const container = editingHost.parentElement; 70 const utils = new EditorTestUtils(editingHost); 71 const modifiers = (() => { 72 if (testingInsertParagraph) { 73 return null; 74 } 75 // Only Safari treats `Ctrl+Enter` as insertLineBreak 76 if (navigator.platform.includes("Mac") && 77 navigator.userAgent.includes("Safari") && 78 !navigator.userAgent.includes("Chrom")) { 79 return utils.kControl; 80 } 81 // The others including WebKitGTK treat `Shift+Enter` as it. 82 return utils.kShift; 83 })(); 84 85 for (const defaultParagraphSeparator of ["div", "p"]) { 86 document.execCommand( 87 "defaultParagraphSeparator", 88 false, 89 defaultParagraphSeparator 90 ); 91 92 promise_test(async t => { 93 editingHost.setAttribute( 94 "style", 95 `display:${display};white-space:${whiteSpace}` 96 ); 97 utils.setupEditingHost("{}"); 98 await utils.sendEnterKey(modifiers); 99 editingHost.removeAttribute("style"); 100 // In this case, the inserting line break is the last visible thing in the 101 // block. Therefore, additional <br> or a preformatted linefeed is also 102 // required to make the new line visible. 103 if (!isPreformatted) { 104 assert_equals( 105 container.innerHTML, 106 '<span contenteditable=""><br><br></span>', 107 `A <br> and additional <br> should be inserted when ${t.name}` 108 ); 109 } else { 110 assert_in_array( 111 container.innerHTML, 112 [ 113 '<span contenteditable="">\n<br></span>', 114 '<span contenteditable="">\n\n</span>', 115 ], 116 `A linefeed and additional line breaker should be inserted when ${t.name}` 117 ); 118 } 119 }, `${ 120 testingInsertParagraph ? "insertParagraph" : "insertLineBreak" 121 } in <span contenteditable style="display:${ 122 display 123 };white-space:${whiteSpace}">{}</span> (defaultParagraphSeparator=${ 124 defaultParagraphSeparator 125 })`); 126 127 promise_test(async t => { 128 editingHost.setAttribute( 129 "style", 130 `display:${display};white-space:${whiteSpace}` 131 ); 132 const brElement = document.createElement("br"); 133 try { 134 container.appendChild(brElement); 135 utils.setupEditingHost("{}"); 136 await utils.sendEnterKey(modifiers); 137 editingHost.removeAttribute("style"); 138 // Even if the <span> element is followed by an invisible <br>, it does 139 // not make the new line in the <span> element visible. Therefore, 140 // inserting additional line break is required in this case too. 141 if (!isPreformatted) { 142 assert_equals( 143 container.innerHTML, 144 '<span contenteditable=""><br><br></span><br>', 145 `A <br> and additional <br> should be inserted when ${t.name}` 146 ); 147 } else { 148 assert_in_array( 149 container.innerHTML, 150 [ 151 `<span contenteditable="">\n\n</span><br>`, 152 `<span contenteditable="">\n<br></span><br>`, 153 ], 154 `A linefeed and additional line break should be inserted when ${t.name}` 155 ); 156 } 157 } finally { 158 brElement.remove(); 159 } 160 }, `${ 161 testingInsertParagraph ? "insertParagraph" : "insertLineBreak" 162 } in <span contenteditable style="display:${ 163 display 164 };white-space:${ 165 whiteSpace 166 }">{}</span> followed by a <br> (defaultParagraphSeparator=${ 167 defaultParagraphSeparator 168 })`); 169 170 promise_test(async t => { 171 editingHost.setAttribute( 172 "style", 173 `display:${display};white-space:${whiteSpace}` 174 ); 175 const divElement = document.createElement("div"); 176 divElement.textContent = "efg"; 177 try { 178 container.appendChild(divElement); 179 utils.setupEditingHost("{}"); 180 await utils.sendEnterKey(modifiers); 181 editingHost.removeAttribute("style"); 182 // When the <span> element is followed by a <div>, making empty last 183 // line visible requires an invisible <br> after a line break. 184 if (!isPreformatted) { 185 assert_equals( 186 container.innerHTML, 187 '<span contenteditable=""><br><br></span><div>efg</div>', 188 `A <br> and additional <br> should be inserted when ${t.name}` 189 ); 190 } else { 191 assert_in_array( 192 container.innerHTML, 193 [ 194 `<span contenteditable="">\n\n</span><div>efg</div>`, 195 `<span contenteditable="">\n<br></span><div>efg</div>`, 196 ], 197 `A linefeed and additional line break should be inserted when ${t.name}` 198 ); 199 } 200 } finally { 201 divElement.remove(); 202 } 203 }, `${ 204 testingInsertParagraph ? "insertParagraph" : "insertLineBreak" 205 } in <span contenteditable style="display:${ 206 display 207 };white-space:${ 208 whiteSpace 209 }">{}</span> followed by a <div> (defaultParagraphSeparator=${ 210 defaultParagraphSeparator 211 })`); 212 213 promise_test(async t => { 214 editingHost.setAttribute( 215 "style", 216 `display:${display};white-space:${whiteSpace}` 217 ); 218 const text = document.createTextNode("abc"); 219 try { 220 container.appendChild(text); 221 utils.setupEditingHost("{}"); 222 await utils.sendEnterKey(modifiers); 223 editingHost.removeAttribute("style"); 224 // Even if the <span> element is followed by visible text, it does 225 // not make the new line in the <span> element visible. Therefore, 226 // inserting additional line break is required in this case too. 227 if (!isPreformatted) { 228 assert_equals( 229 container.innerHTML, 230 '<span contenteditable=""><br><br></span>abc', 231 `A <br> and additional <br> should be inserted when ${t.name}` 232 ); 233 } else { 234 assert_in_array( 235 container.innerHTML, 236 [ 237 `<span contenteditable="">\n\n</span>abc`, 238 `<span contenteditable="">\n<br></span>abc`, 239 ], 240 `A linefeed and additional line break should be inserted when ${t.name}` 241 ); 242 } 243 } finally { 244 text.remove(); 245 } 246 }, `${ 247 testingInsertParagraph ? "insertParagraph" : "insertLineBreak" 248 } in <span contenteditable style="display:${ 249 display 250 };white-space:${ 251 whiteSpace 252 }">{}</span> followed by text (defaultParagraphSeparator=${ 253 defaultParagraphSeparator 254 })`); 255 256 promise_test(async t => { 257 editingHost.setAttribute( 258 "style", 259 `display:${display};white-space:${whiteSpace}` 260 ); 261 utils.setupEditingHost("{}<br>"); 262 await utils.sendEnterKey(modifiers); 263 editingHost.removeAttribute("style"); 264 // In this case, there is a <br> element which makes the new line (last 265 // line) visible. Therefore, only a line break should be inserted. 266 if (!isPreformatted) { 267 assert_equals( 268 container.innerHTML, 269 `<span contenteditable=""><br><br></span>`, 270 `A <br> should be inserted when ${t.name}` 271 ); 272 } else { 273 assert_equals( 274 container.innerHTML, 275 `<span contenteditable="">\n<br></span>`, 276 `A <br> should be inserted when ${t.name}` 277 ); 278 } 279 }, `${ 280 testingInsertParagraph ? "insertParagraph" : "insertLineBreak" 281 } in <span contenteditable style="display:${ 282 display 283 };white-space:${whiteSpace}">{}<br></span> (defaultParagraphSeparator=${ 284 defaultParagraphSeparator 285 })`); 286 287 promise_test(async t => { 288 editingHost.setAttribute( 289 "style", 290 `display:${display};white-space:${whiteSpace}` 291 ); 292 utils.setupEditingHost("[]abcd"); 293 await utils.sendEnterKey(modifiers); 294 editingHost.removeAttribute("style"); 295 assert_equals( 296 container.innerHTML, 297 `<span contenteditable="">${ 298 isPreformatted ? "\n" : "<br>" 299 }abcd</span>`, 300 `${ 301 isPreformatted ? "A linefeed" : "A <br>" 302 } should be inserted when ${t.name}` 303 ); 304 }, `${ 305 testingInsertParagraph ? "insertParagraph" : "insertLineBreak" 306 } in <span contenteditable style="display:${ 307 display 308 };white-space:${whiteSpace}">[]abcd</span> (defaultParagraphSeparator=${ 309 defaultParagraphSeparator 310 })`); 311 312 promise_test(async t => { 313 editingHost.setAttribute( 314 "style", 315 `display:${display};white-space:${whiteSpace}` 316 ); 317 utils.setupEditingHost("ab[]cd"); 318 await utils.sendEnterKey(modifiers); 319 editingHost.removeAttribute("style"); 320 assert_equals( 321 container.innerHTML, 322 `<span contenteditable="">ab${ 323 isPreformatted ? "\n" : "<br>" 324 }cd</span>`, 325 `${ 326 isPreformatted ? "A linefeed" : "A <br>" 327 } should be inserted when ${t.name}` 328 ); 329 }, `${ 330 testingInsertParagraph ? "insertParagraph" : "insertLineBreak" 331 } in <span contenteditable style="display:${ 332 display 333 };white-space:${whiteSpace}">ab[]cd</span> (defaultParagraphSeparator=${ 334 defaultParagraphSeparator 335 })`); 336 337 promise_test(async t => { 338 editingHost.setAttribute( 339 "style", 340 `display:${display};white-space:${whiteSpace}` 341 ); 342 utils.setupEditingHost("abcd[]"); 343 await utils.sendEnterKey(modifiers); 344 editingHost.removeAttribute("style"); 345 // In this case, the inserting line break is the last visible thing in the 346 // block. Therefore, additional line break is also required to make the 347 // new line visible. 348 if (!isPreformatted) { 349 assert_equals( 350 container.innerHTML, 351 `<span contenteditable="">abcd<br><br></span>`, 352 `A <br> and additional <br> should be inserted when ${t.name}` 353 ); 354 } else { 355 assert_in_array( 356 container.innerHTML, 357 [ 358 `<span contenteditable="">abcd\n<br></span>`, 359 `<span contenteditable="">abcd\n\n</span>`, 360 ], 361 `A linefeed and additional line break should be inserted when ${t.name}` 362 ); 363 } 364 }, `${ 365 testingInsertParagraph ? "insertParagraph" : "insertLineBreak" 366 } in <span contenteditable style="display:${ 367 display 368 };white-space:${whiteSpace}">abcd[]</span> (defaultParagraphSeparator=${ 369 defaultParagraphSeparator 370 })`); 371 372 promise_test(async t => { 373 editingHost.setAttribute( 374 "style", 375 `display:${display};white-space:${whiteSpace}` 376 ); 377 const brElement = document.createElement("br"); 378 try { 379 container.appendChild(brElement); 380 utils.setupEditingHost("abcd[]"); 381 await utils.sendEnterKey(modifiers); 382 editingHost.removeAttribute("style"); 383 // Even if the <span> element is followed by an invisible <br>, it does 384 // not make the new line in the <span> element visible. Therefore, 385 // inserting additional line break is required in this case too. 386 if (!isPreformatted) { 387 assert_equals( 388 container.innerHTML, 389 '<span contenteditable="">abcd<br><br></span><br>', 390 `A <br> and additional <br> should be inserted when ${t.name}` 391 ); 392 } else { 393 assert_in_array( 394 container.innerHTML, 395 [ 396 `<span contenteditable="">abcd\n<br></span><br>`, 397 `<span contenteditable="">abcd\n\n</span><br>`, 398 ], 399 `A linefeed and additional line break should be inserted when ${t.name}` 400 ); 401 } 402 } finally { 403 brElement.remove(); 404 } 405 }, `${ 406 testingInsertParagraph ? "insertParagraph" : "insertLineBreak" 407 } in <span contenteditable style="display:${ 408 display 409 };white-space:${ 410 whiteSpace 411 }">abcd[]</span> followed by a <br> element (defaultParagraphSeparator=${ 412 defaultParagraphSeparator 413 })`); 414 415 promise_test(async t => { 416 editingHost.setAttribute( 417 "style", 418 `display:${display};white-space:${whiteSpace}` 419 ); 420 const divElement = document.createElement("div"); 421 divElement.textContent = "efg"; 422 try { 423 container.appendChild(divElement); 424 utils.setupEditingHost("abcd[]"); 425 await utils.sendEnterKey(modifiers); 426 editingHost.removeAttribute("style"); 427 // When the <span> element is followed by a <div>, making empty last 428 // line visible requires an invisible <br> after a line break. 429 if (!isPreformatted) { 430 assert_equals( 431 container.innerHTML, 432 '<span contenteditable="">abcd<br><br></span><div>efg</div>', 433 `A <br> and additional <br> should be inserted when ${t.name}` 434 ); 435 } else { 436 assert_in_array( 437 container.innerHTML, 438 [ 439 `<span contenteditable="">abcd\n<br></span><div>efg</div>`, 440 `<span contenteditable="">abcd\n\n</span><div>efg</div>`, 441 ], 442 `A linefeed and additional line break should be inserted when ${t.name}` 443 ); 444 } 445 } finally { 446 divElement.remove(); 447 } 448 }, `${ 449 testingInsertParagraph ? "insertParagraph" : "insertLineBreak" 450 } in <span contenteditable style="display:${ 451 display 452 };white-space:${ 453 whiteSpace 454 }">abcd[]</span> followed by a <div> element (defaultParagraphSeparator=${ 455 defaultParagraphSeparator 456 })`); 457 458 promise_test(async t => { 459 editingHost.setAttribute( 460 "style", 461 `display:${display};white-space:${whiteSpace}` 462 ); 463 const text = document.createTextNode("efg"); 464 try { 465 container.appendChild(text); 466 utils.setupEditingHost("abcd[]"); 467 await utils.sendEnterKey(modifiers); 468 editingHost.removeAttribute("style"); 469 // Even if the <span> element is followed by visible text, it does 470 // not make the new line in the <span> element visible. Therefore, 471 // inserting additional line break is required in this case too. 472 if (!isPreformatted) { 473 assert_equals( 474 container.innerHTML, 475 '<span contenteditable="">abcd<br><br></span>efg', 476 `A <br> and additional <br> should be inserted when ${t.name}` 477 ); 478 } else { 479 assert_in_array( 480 container.innerHTML, 481 [ 482 `<span contenteditable="">abcd\n<br></span>efg`, 483 `<span contenteditable="">abcd\n\n</span>efg`, 484 ], 485 `A linefeed and additional line break should be inserted when ${t.name}` 486 ); 487 } 488 } finally { 489 text.remove(); 490 } 491 }, `${ 492 testingInsertParagraph ? "insertParagraph" : "insertLineBreak" 493 } in <span contenteditable style="display:${ 494 display 495 };white-space:${ 496 whiteSpace 497 }">abcd[]</span> followed by text (defaultParagraphSeparator=${ 498 defaultParagraphSeparator 499 })`); 500 } 501 502 </script>