keeping-attributes-at-joining-elements.tentative.html (43393B)
1 <!doctype html> 2 <meta chareset="utf-8"> 3 <meta name="timeout" content="long"> 4 <meta name="variant" content="?method=backspace"> 5 <meta name="variant" content="?method=forwarddelete"> 6 <title>Not merging attributes at joining elements in contenteditable</title> 7 <script src="/resources/testharness.js"></script> 8 <script src="/resources/testharnessreport.js"></script> 9 <script src="/resources/testdriver.js"></script> 10 <script src="/resources/testdriver-vendor.js"></script> 11 <script src="/resources/testdriver-actions.js"></script> 12 <script src="../include/editor-test-utils.js"></script> 13 </style> 14 <div contenteditable></div> 15 <script> 16 "use strict"; 17 18 const testingBackspace = 19 new URLSearchParams(document.location.search).get("method") == "backspace"; 20 const caretForBackSpace = testingBackspace ? "[]" : ""; 21 const caretForForwardDelete = testingBackspace ? "" : "[]"; 22 document.execCommand("defaultParagraphSeparator", false, "div"); 23 const utils = 24 new EditorTestUtils(document.querySelector("div[contenteditable]")); 25 26 // DO NOT USE multi-line comment in this file, then, you can comment out 27 // unnecessary tests when you need to attach the browser with a debugger. 28 29 // At joining 2 elements, the attributes shouldn't be merged, and from point of 30 // view of JS/DOM, both element kept after the join and element deleted from the 31 // DOM tree should have attributes as-is. 32 promise_test(async t => { 33 utils.setupEditingHost( 34 `<div id="left">abc${caretForForwardDelete}</div><div id="right">${caretForBackSpace}def</div>` 35 ); 36 const leftNode = document.getElementById("left"); 37 const rightNode = document.getElementById("right"); 38 39 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 40 41 test(() => { 42 assert_equals( 43 leftNode.getAttribute("id"), 44 "left", 45 `The left node should keep having id=left (isConnected=${leftNode.isConnected}, ${t.name})` 46 ); 47 }); 48 test(() => { 49 assert_equals( 50 rightNode.getAttribute("id"), 51 "right", 52 `The right node should keep having id=right (isConnected=${rightNode.isConnected}, ${t.name})` 53 ); 54 }); 55 assert_equals( 56 leftNode.isConnected ^ rightNode.isConnected, 57 1, 58 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 59 ); 60 }, "Joining <div id=\"left\"> and <div id=\"right\">"); 61 62 promise_test(async t => { 63 utils.setupEditingHost( 64 `<div class="left">abc${caretForForwardDelete}</div><div class="right">${caretForBackSpace}def</div>` 65 ); 66 const leftNode = utils.editingHost.querySelector(".left"); 67 const rightNode = utils.editingHost.querySelector(".right"); 68 69 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 70 71 test(() => { 72 assert_equals( 73 leftNode.getAttribute("class"), 74 "left", 75 `The left node should keep having class=left (isConnected=${leftNode.isConnected}, ${t.name})` 76 ); 77 }); 78 test(() => { 79 assert_equals( 80 rightNode.getAttribute("class"), 81 "right", 82 `The right node should keep having class=right (isConnected=${rightNode.isConnected}, ${t.name})` 83 ); 84 }); 85 assert_equals( 86 leftNode.isConnected ^ rightNode.isConnected, 87 1, 88 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 89 ); 90 }, "Joining <div class=\"left\"> and <div class=\"right\">"); 91 92 promise_test(async t => { 93 utils.setupEditingHost( 94 `<div style="font-size:0.8rem">abc${caretForForwardDelete}</div><div style="font-weight:bold">${caretForBackSpace}def</div>` 95 ); 96 const leftNode = utils.editingHost.querySelector("div[style]"); 97 const rightNode = leftNode.nextSibling; 98 99 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 100 101 // style attribute values shouldn't be touched in this but case, but it's 102 // okay if the values are not merged. 103 test(() => { 104 assert_true( 105 leftNode.getAttribute("style").includes("font-size"), 106 `The left node should keep having style attribute containing font-size (style="${leftNode.getAttribute("style")}", ${t.name})` 107 ); 108 assert_false( 109 leftNode.getAttribute("style").includes("font-weight"), 110 `The left node should have font-weight in its style attribute (style="${leftNode.getAttribute("style")}", ${t.name})` 111 ); 112 }); 113 test(() => { 114 assert_true( 115 rightNode.getAttribute("style").includes("font-weight"), 116 `The right node should keep having style attribute containing font-size (style="${rightNode.getAttribute("style")}", ${t.name})` 117 ); 118 assert_false( 119 rightNode.getAttribute("style").includes("font-style"), 120 `The right node should have font-size in its style attribute (style="${rightNode.getAttribute("style")}", ${t.name})` 121 ); 122 }); 123 assert_equals( 124 leftNode.isConnected ^ rightNode.isConnected, 125 1, 126 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 127 ); 128 }, "Joining <div style=\"font-size:0.8rem\"> and <div style=\"font-weight:bold\">"); 129 130 promise_test(async t => { 131 utils.setupEditingHost( 132 `<div data-foo="left">abc${caretForForwardDelete}</div><div data-bar="right">${caretForBackSpace}def</div>` 133 ); 134 const leftNode = utils.editingHost.querySelector("[data-foo=left]"); 135 const rightNode = utils.editingHost.querySelector("[data-bar=right]"); 136 137 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 138 139 test(() => { 140 assert_equals( 141 leftNode.getAttribute("data-foo"), 142 "left", 143 `The left node should keep having class=left (isConnected=${leftNode.isConnected}, ${t.name})` 144 ); 145 }); 146 test(() => { 147 assert_false( 148 leftNode.hasAttribute("data-bar"), 149 `The left node shouldn't have data-bar attribute (isConnected=${leftNode.isConnected}, ${t.name})` 150 ); 151 }); 152 test(() => { 153 assert_equals( 154 rightNode.getAttribute("data-bar"), 155 "right", 156 `The right node should keep having class=right (isConnected=${rightNode.isConnected}, ${t.name})` 157 ); 158 }); 159 test(() => { 160 assert_false( 161 rightNode.hasAttribute("data-foo"), 162 `The right node shouldn't have data-foo attribute (isConnected=${leftNode.isConnected}, ${t.name})` 163 ); 164 }); 165 assert_equals( 166 leftNode.isConnected ^ rightNode.isConnected, 167 1, 168 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 169 ); 170 }, "Joining <div data-foo=\"left\"> and <div data-bar=\"right\">"); 171 172 // Same tests for list-item elements because they may be handled in a different 173 // path. 174 promise_test(async t => { 175 utils.setupEditingHost( 176 `<ul><li id="left">abc${caretForForwardDelete}</li><li id="right">${caretForBackSpace}def</li></ul>` 177 ); 178 const leftNode = document.getElementById("left"); 179 const rightNode = document.getElementById("right"); 180 181 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 182 183 test(() => { 184 assert_equals( 185 leftNode.getAttribute("id"), 186 "left", 187 `The left node should keep having id=left (isConnected=${leftNode.isConnected}, ${t.name})` 188 ); 189 }); 190 test(() => { 191 assert_equals( 192 rightNode.getAttribute("id"), 193 "right", 194 `The right node should keep having id=right (isConnected=${rightNode.isConnected}, ${t.name})` 195 ); 196 }); 197 assert_equals( 198 leftNode.isConnected ^ rightNode.isConnected, 199 1, 200 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 201 ); 202 }, "Joining <li id=\"left\"> and <li id=\"right\">"); 203 204 promise_test(async t => { 205 utils.setupEditingHost( 206 `<ul><li class="left">abc${caretForForwardDelete}</li><li class="right">${caretForBackSpace}def</li></ul>` 207 ); 208 const leftNode = utils.editingHost.querySelector(".left"); 209 const rightNode = utils.editingHost.querySelector(".right"); 210 211 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 212 213 test(() => { 214 assert_equals( 215 leftNode.getAttribute("class"), 216 "left", 217 `The left node should keep having class=left (isConnected=${leftNode.isConnected}, ${t.name})` 218 ); 219 }); 220 test(() => { 221 assert_equals( 222 rightNode.getAttribute("class"), 223 "right", 224 `The right node should keep having class=right (isConnected=${rightNode.isConnected}, ${t.name})` 225 ); 226 }); 227 assert_equals( 228 leftNode.isConnected ^ rightNode.isConnected, 229 1, 230 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 231 ); 232 }, "Joining <li class=\"left\"> and <li class=\"right\">"); 233 234 promise_test(async t => { 235 utils.setupEditingHost( 236 `<ul><li style="font-size:0.8rem">abc${caretForForwardDelete}</li><li style="font-weight:bold">${caretForBackSpace}def</li></ul>` 237 ); 238 const leftNode = utils.editingHost.querySelector("li[style]"); 239 const rightNode = leftNode.nextSibling; 240 241 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 242 243 // style attribute values shouldn't be touched in this but case, but it's 244 // okay if the values are not merged. 245 test(() => { 246 assert_true( 247 leftNode.getAttribute("style").includes("font-size"), 248 `The left node should keep having style attribute containing font-size (style="${leftNode.getAttribute("style")}", ${t.name})` 249 ); 250 assert_false( 251 leftNode.getAttribute("style").includes("font-weight"), 252 `The left node should have font-weight in its style attribute (style="${leftNode.getAttribute("style")}", ${t.name})` 253 ); 254 }); 255 test(() => { 256 assert_true( 257 rightNode.getAttribute("style").includes("font-weight"), 258 `The right node should keep having style attribute containing font-size (style="${rightNode.getAttribute("style")}", ${t.name})` 259 ); 260 assert_false( 261 rightNode.getAttribute("style").includes("font-style"), 262 `The right node should have font-size in its style attribute (style="${rightNode.getAttribute("style")}", ${t.name})` 263 ); 264 }); 265 assert_equals( 266 leftNode.isConnected ^ rightNode.isConnected, 267 1, 268 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 269 ); 270 }, "Joining <li style=\"font-size:0.8rem\"> and <li style=\"font-weight:bold\">"); 271 272 promise_test(async t => { 273 utils.setupEditingHost( 274 `<ul><li data-foo="left">abc${caretForForwardDelete}</li><li data-bar="right">${caretForBackSpace}def</li></ul>` 275 ); 276 const leftNode = utils.editingHost.querySelector("[data-foo=left]"); 277 const rightNode = utils.editingHost.querySelector("[data-bar=right]"); 278 279 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 280 281 test(() => { 282 assert_equals( 283 leftNode.getAttribute("data-foo"), 284 "left", 285 `The left node should keep having class=left (isConnected=${leftNode.isConnected}, ${t.name})` 286 ); 287 }); 288 test(() => { 289 assert_false( 290 leftNode.hasAttribute("data-bar"), 291 `The left node shouldn't have data-bar attribute (isConnected=${leftNode.isConnected}, ${t.name})` 292 ); 293 }); 294 test(() => { 295 assert_equals( 296 rightNode.getAttribute("data-bar"), 297 "right", 298 `The right node should keep having class=right (isConnected=${rightNode.isConnected}, ${t.name})` 299 ); 300 }); 301 test(() => { 302 assert_false( 303 rightNode.hasAttribute("data-foo"), 304 `The right node shouldn't have data-foo attribute (isConnected=${leftNode.isConnected}, ${t.name})` 305 ); 306 }); 307 assert_equals( 308 leftNode.isConnected ^ rightNode.isConnected, 309 1, 310 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 311 ); 312 }, "Joining <li data-foo=\"left\"> and <li data-bar=\"right\">"); 313 314 // Same tests for <dt> elements because they may be handled in a different 315 // path. 316 promise_test(async t => { 317 utils.setupEditingHost( 318 `<dl><dt id="left">abc${caretForForwardDelete}</dt><dt id="right">${caretForBackSpace}def</dt></dl>` 319 ); 320 const leftNode = document.getElementById("left"); 321 const rightNode = document.getElementById("right"); 322 323 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 324 325 test(() => { 326 assert_equals( 327 leftNode.getAttribute("id"), 328 "left", 329 `The left node should keep having id=left (isConnected=${leftNode.isConnected}, ${t.name})` 330 ); 331 }); 332 test(() => { 333 assert_equals( 334 rightNode.getAttribute("id"), 335 "right", 336 `The right node should keep having id=right (isConnected=${rightNode.isConnected}, ${t.name})` 337 ); 338 }); 339 assert_equals( 340 leftNode.isConnected ^ rightNode.isConnected, 341 1, 342 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 343 ); 344 }, "Joining <dt id=\"left\"> and <dt id=\"right\">"); 345 346 promise_test(async t => { 347 utils.setupEditingHost( 348 `<dl><dt class="left">abc${caretForForwardDelete}</dt><dt class="right">${caretForBackSpace}def</dt></dl>` 349 ); 350 const leftNode = utils.editingHost.querySelector(".left"); 351 const rightNode = utils.editingHost.querySelector(".right"); 352 353 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 354 355 test(() => { 356 assert_equals( 357 leftNode.getAttribute("class"), 358 "left", 359 `The left node should keep having class=left (isConnected=${leftNode.isConnected}, ${t.name})` 360 ); 361 }); 362 test(() => { 363 assert_equals( 364 rightNode.getAttribute("class"), 365 "right", 366 `The right node should keep having class=right (isConnected=${rightNode.isConnected}, ${t.name})` 367 ); 368 }); 369 assert_equals( 370 leftNode.isConnected ^ rightNode.isConnected, 371 1, 372 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 373 ); 374 }, "Joining <dt class=\"left\"> and <dt class=\"right\">"); 375 376 promise_test(async t => { 377 utils.setupEditingHost( 378 `<dl><dt style="font-size:0.8rem">abc${caretForForwardDelete}</dt><dt style="font-weight:bold">${caretForBackSpace}def</dt></dl>` 379 ); 380 const leftNode = utils.editingHost.querySelector("dt[style]"); 381 const rightNode = leftNode.nextSibling; 382 383 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 384 385 // style attribute values shouldn't be touched in this but case, but it's 386 // okay if the values are not merged. 387 test(() => { 388 assert_true( 389 leftNode.getAttribute("style").includes("font-size"), 390 `The left node should keep having style attribute containing font-size (style="${leftNode.getAttribute("style")}", ${t.name})` 391 ); 392 assert_false( 393 leftNode.getAttribute("style").includes("font-weight"), 394 `The left node should have font-weight in its style attribute (style="${leftNode.getAttribute("style")}", ${t.name})` 395 ); 396 }); 397 test(() => { 398 assert_true( 399 rightNode.getAttribute("style").includes("font-weight"), 400 `The right node should keep having style attribute containing font-size (style="${rightNode.getAttribute("style")}", ${t.name})` 401 ); 402 assert_false( 403 rightNode.getAttribute("style").includes("font-style"), 404 `The right node should have font-size in its style attribute (style="${rightNode.getAttribute("style")}", ${t.name})` 405 ); 406 }); 407 assert_equals( 408 leftNode.isConnected ^ rightNode.isConnected, 409 1, 410 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 411 ); 412 }, "Joining <dt style=\"font-size:0.8rem\"> and <dt style=\"font-weight:bold\">"); 413 414 promise_test(async t => { 415 utils.setupEditingHost( 416 `<dl><dt data-foo="left">abc${caretForForwardDelete}</dt><dt data-bar="right">${caretForBackSpace}def</dt></dl>` 417 ); 418 const leftNode = utils.editingHost.querySelector("[data-foo=left]"); 419 const rightNode = utils.editingHost.querySelector("[data-bar=right]"); 420 421 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 422 423 test(() => { 424 assert_equals( 425 leftNode.getAttribute("data-foo"), 426 "left", 427 `The left node should keep having class=left (isConnected=${leftNode.isConnected}, ${t.name})` 428 ); 429 }); 430 test(() => { 431 assert_false( 432 leftNode.hasAttribute("data-bar"), 433 `The left node shouldn't have data-bar attribute (isConnected=${leftNode.isConnected}, ${t.name})` 434 ); 435 }); 436 test(() => { 437 assert_equals( 438 rightNode.getAttribute("data-bar"), 439 "right", 440 `The right node should keep having class=right (isConnected=${rightNode.isConnected}, ${t.name})` 441 ); 442 }); 443 test(() => { 444 assert_false( 445 rightNode.hasAttribute("data-foo"), 446 `The right node shouldn't have data-foo attribute (isConnected=${leftNode.isConnected}, ${t.name})` 447 ); 448 }); 449 assert_equals( 450 leftNode.isConnected ^ rightNode.isConnected, 451 1, 452 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 453 ); 454 }, "Joining <dt data-foo=\"left\"> and <dt data-bar=\"right\">"); 455 456 // Same tests for <dd> elements because they may be handled in a different 457 // path. 458 promise_test(async t => { 459 utils.setupEditingHost( 460 `<dl><dd id="left">abc${caretForForwardDelete}</dd><dd id="right">${caretForBackSpace}def</dd></dl>` 461 ); 462 const leftNode = document.getElementById("left"); 463 const rightNode = document.getElementById("right"); 464 465 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 466 467 test(() => { 468 assert_equals( 469 leftNode.getAttribute("id"), 470 "left", 471 `The left node should keep having id=left (isConnected=${leftNode.isConnected}, ${t.name})` 472 ); 473 }); 474 test(() => { 475 assert_equals( 476 rightNode.getAttribute("id"), 477 "right", 478 `The right node should keep having id=right (isConnected=${rightNode.isConnected}, ${t.name})` 479 ); 480 }); 481 assert_equals( 482 leftNode.isConnected ^ rightNode.isConnected, 483 1, 484 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 485 ); 486 }, "Joining <dd id=\"left\"> and <dd id=\"right\">"); 487 488 promise_test(async t => { 489 utils.setupEditingHost( 490 `<dl><dd class="left">abc${caretForForwardDelete}</dd><dd class="right">${caretForBackSpace}def</dd></dl>` 491 ); 492 const leftNode = utils.editingHost.querySelector(".left"); 493 const rightNode = utils.editingHost.querySelector(".right"); 494 495 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 496 497 test(() => { 498 assert_equals( 499 leftNode.getAttribute("class"), 500 "left", 501 `The left node should keep having class=left (isConnected=${leftNode.isConnected}, ${t.name})` 502 ); 503 }); 504 test(() => { 505 assert_equals( 506 rightNode.getAttribute("class"), 507 "right", 508 `The right node should keep having class=right (isConnected=${rightNode.isConnected}, ${t.name})` 509 ); 510 }); 511 assert_equals( 512 leftNode.isConnected ^ rightNode.isConnected, 513 1, 514 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 515 ); 516 }, "Joining <dd class=\"left\"> and <dd class=\"right\">"); 517 518 promise_test(async t => { 519 utils.setupEditingHost( 520 `<dl><dd style="font-size:0.8rem">abc${caretForForwardDelete}</dd><dd style="font-weight:bold">${caretForBackSpace}def</dd></dl>` 521 ); 522 const leftNode = utils.editingHost.querySelector("dd[style]"); 523 const rightNode = leftNode.nextSibling; 524 525 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 526 527 // style attribute values shouldn't be touched in this but case, but it's 528 // okay if the values are not merged. 529 test(() => { 530 assert_true( 531 leftNode.getAttribute("style").includes("font-size"), 532 `The left node should keep having style attribute containing font-size (style="${leftNode.getAttribute("style")}", ${t.name})` 533 ); 534 assert_false( 535 leftNode.getAttribute("style").includes("font-weight"), 536 `The left node should have font-weight in its style attribute (style="${leftNode.getAttribute("style")}", ${t.name})` 537 ); 538 }); 539 test(() => { 540 assert_true( 541 rightNode.getAttribute("style").includes("font-weight"), 542 `The right node should keep having style attribute containing font-size (style="${rightNode.getAttribute("style")}", ${t.name})` 543 ); 544 assert_false( 545 rightNode.getAttribute("style").includes("font-style"), 546 `The right node should have font-size in its style attribute (style="${rightNode.getAttribute("style")}", ${t.name})` 547 ); 548 }); 549 assert_equals( 550 leftNode.isConnected ^ rightNode.isConnected, 551 1, 552 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 553 ); 554 }, "Joining <dd style=\"font-size:0.8rem\"> and <dd style=\"font-weight:bold\">"); 555 556 promise_test(async t => { 557 utils.setupEditingHost( 558 `<dl><dd data-foo="left">abc${caretForForwardDelete}</dd><dd data-bar="right">${caretForBackSpace}def</dd></dl>` 559 ); 560 const leftNode = utils.editingHost.querySelector("[data-foo=left]"); 561 const rightNode = utils.editingHost.querySelector("[data-bar=right]"); 562 563 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 564 565 test(() => { 566 assert_equals( 567 leftNode.getAttribute("data-foo"), 568 "left", 569 `The left node should keep having class=left (isConnected=${leftNode.isConnected}, ${t.name})` 570 ); 571 }); 572 test(() => { 573 assert_false( 574 leftNode.hasAttribute("data-bar"), 575 `The left node shouldn't have data-bar attribute (isConnected=${leftNode.isConnected}, ${t.name})` 576 ); 577 }); 578 test(() => { 579 assert_equals( 580 rightNode.getAttribute("data-bar"), 581 "right", 582 `The right node should keep having class=right (isConnected=${rightNode.isConnected}, ${t.name})` 583 ); 584 }); 585 test(() => { 586 assert_false( 587 rightNode.hasAttribute("data-foo"), 588 `The right node shouldn't have data-foo attribute (isConnected=${leftNode.isConnected}, ${t.name})` 589 ); 590 }); 591 assert_equals( 592 leftNode.isConnected ^ rightNode.isConnected, 593 1, 594 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 595 ); 596 }, "Joining <dd data-foo=\"left\"> and <dd data-bar=\"right\">"); 597 598 // Same tests for <dt> and <dd> because they may be handled in a different 599 // path. 600 promise_test(async t => { 601 utils.setupEditingHost( 602 `<dl><dt id="left">abc${caretForForwardDelete}</dt><dd id="right">${caretForBackSpace}def</dd></dl>` 603 ); 604 const leftNode = document.getElementById("left"); 605 const rightNode = document.getElementById("right"); 606 607 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 608 609 test(() => { 610 assert_equals( 611 leftNode.getAttribute("id"), 612 "left", 613 `The left node should keep having id=left (isConnected=${leftNode.isConnected}, ${t.name})` 614 ); 615 }); 616 test(() => { 617 assert_equals( 618 rightNode.getAttribute("id"), 619 "right", 620 `The right node should keep having id=right (isConnected=${rightNode.isConnected}, ${t.name})` 621 ); 622 }); 623 assert_equals( 624 leftNode.isConnected ^ rightNode.isConnected, 625 1, 626 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 627 ); 628 }, "Joining <dt id=\"left\"> and <dd id=\"right\">"); 629 630 promise_test(async t => { 631 utils.setupEditingHost( 632 `<dl><dt class="left">abc${caretForForwardDelete}</dt><dd class="right">${caretForBackSpace}def</dd></dl>` 633 ); 634 const leftNode = utils.editingHost.querySelector(".left"); 635 const rightNode = utils.editingHost.querySelector(".right"); 636 637 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 638 639 test(() => { 640 assert_equals( 641 leftNode.getAttribute("class"), 642 "left", 643 `The left node should keep having class=left (isConnected=${leftNode.isConnected}, ${t.name})` 644 ); 645 }); 646 test(() => { 647 assert_equals( 648 rightNode.getAttribute("class"), 649 "right", 650 `The right node should keep having class=right (isConnected=${rightNode.isConnected}, ${t.name})` 651 ); 652 }); 653 assert_equals( 654 leftNode.isConnected ^ rightNode.isConnected, 655 1, 656 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 657 ); 658 }, "Joining <dt class=\"left\"> and <dd class=\"right\">"); 659 660 promise_test(async t => { 661 utils.setupEditingHost( 662 `<dl><dt style="font-size:0.8rem">abc${caretForForwardDelete}</dt><dd style="font-weight:bold">${caretForBackSpace}def</dd></dl>` 663 ); 664 const leftNode = utils.editingHost.querySelector("dt[style]"); 665 const rightNode = utils.editingHost.querySelector("dd[style]"); 666 667 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 668 669 // style attribute values shouldn't be touched in this but case, but it's 670 // okay if the values are not merged. 671 test(() => { 672 assert_true( 673 leftNode.getAttribute("style").includes("font-size"), 674 `The left node should keep having style attribute containing font-size (style="${leftNode.getAttribute("style")}", ${t.name})` 675 ); 676 assert_false( 677 leftNode.getAttribute("style").includes("font-weight"), 678 `The left node should have font-weight in its style attribute (style="${leftNode.getAttribute("style")}", ${t.name})` 679 ); 680 }); 681 test(() => { 682 assert_true( 683 rightNode.getAttribute("style").includes("font-weight"), 684 `The right node should keep having style attribute containing font-size (style="${rightNode.getAttribute("style")}", ${t.name})` 685 ); 686 assert_false( 687 rightNode.getAttribute("style").includes("font-style"), 688 `The right node should have font-size in its style attribute (style="${rightNode.getAttribute("style")}", ${t.name})` 689 ); 690 }); 691 assert_equals( 692 leftNode.isConnected ^ rightNode.isConnected, 693 1, 694 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 695 ); 696 }, "Joining <dt style=\"font-size:0.8rem\"> and <dd style=\"font-weight:bold\">"); 697 698 promise_test(async t => { 699 utils.setupEditingHost( 700 `<dl><dt data-foo="left">abc${caretForForwardDelete}</dt><dd data-bar="right">${caretForBackSpace}def</dd></dl>` 701 ); 702 const leftNode = utils.editingHost.querySelector("[data-foo=left]"); 703 const rightNode = utils.editingHost.querySelector("[data-bar=right]"); 704 705 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 706 707 test(() => { 708 assert_equals( 709 leftNode.getAttribute("data-foo"), 710 "left", 711 `The left node should keep having class=left (isConnected=${leftNode.isConnected}, ${t.name})` 712 ); 713 }); 714 test(() => { 715 assert_false( 716 leftNode.hasAttribute("data-bar"), 717 `The left node shouldn't have data-bar attribute (isConnected=${leftNode.isConnected}, ${t.name})` 718 ); 719 }); 720 test(() => { 721 assert_equals( 722 rightNode.getAttribute("data-bar"), 723 "right", 724 `The right node should keep having class=right (isConnected=${rightNode.isConnected}, ${t.name})` 725 ); 726 }); 727 test(() => { 728 assert_false( 729 rightNode.hasAttribute("data-foo"), 730 `The right node shouldn't have data-foo attribute (isConnected=${leftNode.isConnected}, ${t.name})` 731 ); 732 }); 733 assert_equals( 734 leftNode.isConnected ^ rightNode.isConnected, 735 1, 736 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 737 ); 738 }, "Joining <dt data-foo=\"left\"> and <dd data-bar=\"right\">"); 739 740 // Same tests for <dd> and <dt> because they may be handled in a different 741 // path. 742 promise_test(async t => { 743 utils.setupEditingHost( 744 `<dl><dd id="left">abc${caretForForwardDelete}</dd><dt id="right">${caretForBackSpace}def</dt></dl>` 745 ); 746 const leftNode = document.getElementById("left"); 747 const rightNode = document.getElementById("right"); 748 749 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 750 751 test(() => { 752 assert_equals( 753 leftNode.getAttribute("id"), 754 "left", 755 `The left node should keep having id=left (isConnected=${leftNode.isConnected}, ${t.name})` 756 ); 757 }); 758 test(() => { 759 assert_equals( 760 rightNode.getAttribute("id"), 761 "right", 762 `The right node should keep having id=right (isConnected=${rightNode.isConnected}, ${t.name})` 763 ); 764 }); 765 assert_equals( 766 leftNode.isConnected ^ rightNode.isConnected, 767 1, 768 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 769 ); 770 }, "Joining <dd id=\"left\"> and <dt id=\"right\">"); 771 772 promise_test(async t => { 773 utils.setupEditingHost( 774 `<dl><dd class="left">abc${caretForForwardDelete}</dd><dt class="right">${caretForBackSpace}def</dt></dl>` 775 ); 776 const leftNode = utils.editingHost.querySelector(".left"); 777 const rightNode = utils.editingHost.querySelector(".right"); 778 779 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 780 781 test(() => { 782 assert_equals( 783 leftNode.getAttribute("class"), 784 "left", 785 `The left node should keep having class=left (isConnected=${leftNode.isConnected}, ${t.name})` 786 ); 787 }); 788 test(() => { 789 assert_equals( 790 rightNode.getAttribute("class"), 791 "right", 792 `The right node should keep having class=right (isConnected=${rightNode.isConnected}, ${t.name})` 793 ); 794 }); 795 assert_equals( 796 leftNode.isConnected ^ rightNode.isConnected, 797 1, 798 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 799 ); 800 }, "Joining <dd class=\"left\"> and <dt class=\"right\">"); 801 802 promise_test(async t => { 803 utils.setupEditingHost( 804 `<dl><dd style="font-size:0.8rem">abc${caretForForwardDelete}</dd><dt style="font-weight:bold">${caretForBackSpace}def</dt></dl>` 805 ); 806 const leftNode = utils.editingHost.querySelector("dd[style]"); 807 const rightNode = utils.editingHost.querySelector("dt[style]"); 808 809 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 810 811 // style attribute values shouldn't be touched in this but case, but it's 812 // okay if the values are not merged. 813 test(() => { 814 assert_true( 815 leftNode.getAttribute("style").includes("font-size"), 816 `The left node should keep having style attribute containing font-size (style="${leftNode.getAttribute("style")}", ${t.name})` 817 ); 818 assert_false( 819 leftNode.getAttribute("style").includes("font-weight"), 820 `The left node should have font-weight in its style attribute (style="${leftNode.getAttribute("style")}", ${t.name})` 821 ); 822 }); 823 test(() => { 824 assert_true( 825 rightNode.getAttribute("style").includes("font-weight"), 826 `The right node should keep having style attribute containing font-size (style="${rightNode.getAttribute("style")}", ${t.name})` 827 ); 828 assert_false( 829 rightNode.getAttribute("style").includes("font-style"), 830 `The right node should have font-size in its style attribute (style="${rightNode.getAttribute("style")}", ${t.name})` 831 ); 832 }); 833 assert_equals( 834 leftNode.isConnected ^ rightNode.isConnected, 835 1, 836 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 837 ); 838 }, "Joining <dd style=\"font-size:0.8rem\"> and <dt style=\"font-weight:bold\">"); 839 840 promise_test(async t => { 841 utils.setupEditingHost( 842 `<dl><dd data-foo="left">abc${caretForForwardDelete}</dd><dt data-bar="right">${caretForBackSpace}def</dt></dl>` 843 ); 844 const leftNode = utils.editingHost.querySelector("[data-foo=left]"); 845 const rightNode = utils.editingHost.querySelector("[data-bar=right]"); 846 847 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 848 849 test(() => { 850 assert_equals( 851 leftNode.getAttribute("data-foo"), 852 "left", 853 `The left node should keep having class=left (isConnected=${leftNode.isConnected}, ${t.name})` 854 ); 855 }); 856 test(() => { 857 assert_false( 858 leftNode.hasAttribute("data-bar"), 859 `The left node shouldn't have data-bar attribute (isConnected=${leftNode.isConnected}, ${t.name})` 860 ); 861 }); 862 test(() => { 863 assert_equals( 864 rightNode.getAttribute("data-bar"), 865 "right", 866 `The right node should keep having class=right (isConnected=${rightNode.isConnected}, ${t.name})` 867 ); 868 }); 869 test(() => { 870 assert_false( 871 rightNode.hasAttribute("data-foo"), 872 `The right node shouldn't have data-foo attribute (isConnected=${leftNode.isConnected}, ${t.name})` 873 ); 874 }); 875 assert_equals( 876 leftNode.isConnected ^ rightNode.isConnected, 877 1, 878 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 879 ); 880 }, "Joining <dd data-foo=\"left\"> and <dt data-bar=\"right\">"); 881 882 // Same tests for <h3> and <div> because they may be handled in a different 883 // path. 884 promise_test(async t => { 885 utils.setupEditingHost( 886 `<h3 id="left">abc${caretForForwardDelete}</h3><div id="right">${caretForBackSpace}def</div>` 887 ); 888 const leftNode = document.getElementById("left"); 889 const rightNode = document.getElementById("right"); 890 891 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 892 893 test(() => { 894 assert_equals( 895 leftNode.getAttribute("id"), 896 "left", 897 `The left node should keep having id=left (isConnected=${leftNode.isConnected}, ${t.name})` 898 ); 899 }); 900 test(() => { 901 assert_equals( 902 rightNode.getAttribute("id"), 903 "right", 904 `The right node should keep having id=right (isConnected=${rightNode.isConnected}, ${t.name})` 905 ); 906 }); 907 assert_equals( 908 leftNode.isConnected ^ rightNode.isConnected, 909 1, 910 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 911 ); 912 }, "Joining <h3 id=\"left\"> and <div id=\"right\">"); 913 914 promise_test(async t => { 915 utils.setupEditingHost( 916 `<h3 class="left">abc${caretForForwardDelete}</h3><div class="right">${caretForBackSpace}def</div>` 917 ); 918 const leftNode = utils.editingHost.querySelector(".left"); 919 const rightNode = utils.editingHost.querySelector(".right"); 920 921 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 922 923 test(() => { 924 assert_equals( 925 leftNode.getAttribute("class"), 926 "left", 927 `The left node should keep having class=left (isConnected=${leftNode.isConnected}, ${t.name})` 928 ); 929 }); 930 test(() => { 931 assert_equals( 932 rightNode.getAttribute("class"), 933 "right", 934 `The right node should keep having class=right (isConnected=${rightNode.isConnected}, ${t.name})` 935 ); 936 }); 937 assert_equals( 938 leftNode.isConnected ^ rightNode.isConnected, 939 1, 940 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 941 ); 942 }, "Joining <h3 class=\"left\"> and <div class=\"right\">"); 943 944 promise_test(async t => { 945 utils.setupEditingHost( 946 `<h3 style="font-size:0.8rem">abc${caretForForwardDelete}</h3><div style="font-weight:bold">${caretForBackSpace}def</div>` 947 ); 948 const leftNode = utils.editingHost.querySelector("h3[style]"); 949 const rightNode = utils.editingHost.querySelector("div[style]"); 950 951 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 952 953 // style attribute values shouldn't be touched in this but case, but it's 954 // okay if the values are not merged. 955 test(() => { 956 assert_true( 957 leftNode.getAttribute("style").includes("font-size"), 958 `The left node should keep having style attribute containing font-size (style="${leftNode.getAttribute("style")}", ${t.name})` 959 ); 960 assert_false( 961 leftNode.getAttribute("style").includes("font-weight"), 962 `The left node should have font-weight in its style attribute (style="${leftNode.getAttribute("style")}", ${t.name})` 963 ); 964 }); 965 test(() => { 966 assert_true( 967 rightNode.getAttribute("style").includes("font-weight"), 968 `The right node should keep having style attribute containing font-size (style="${rightNode.getAttribute("style")}", ${t.name})` 969 ); 970 assert_false( 971 rightNode.getAttribute("style").includes("font-style"), 972 `The right node should have font-size in its style attribute (style="${rightNode.getAttribute("style")}", ${t.name})` 973 ); 974 }); 975 assert_equals( 976 leftNode.isConnected ^ rightNode.isConnected, 977 1, 978 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 979 ); 980 }, "Joining <h3 style=\"font-size:0.8rem\"> and <div style=\"font-weight:bold\">"); 981 982 promise_test(async t => { 983 utils.setupEditingHost( 984 `<h3 data-foo="left">abc${caretForForwardDelete}</h3><div data-bar="right">${caretForBackSpace}def</div>` 985 ); 986 const leftNode = utils.editingHost.querySelector("[data-foo=left]"); 987 const rightNode = utils.editingHost.querySelector("[data-bar=right]"); 988 989 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 990 991 test(() => { 992 assert_equals( 993 leftNode.getAttribute("data-foo"), 994 "left", 995 `The left node should keep having class=left (isConnected=${leftNode.isConnected}, ${t.name})` 996 ); 997 }); 998 test(() => { 999 assert_false( 1000 leftNode.hasAttribute("data-bar"), 1001 `The left node shouldn't have data-bar attribute (isConnected=${leftNode.isConnected}, ${t.name})` 1002 ); 1003 }); 1004 test(() => { 1005 assert_equals( 1006 rightNode.getAttribute("data-bar"), 1007 "right", 1008 `The right node should keep having class=right (isConnected=${rightNode.isConnected}, ${t.name})` 1009 ); 1010 }); 1011 test(() => { 1012 assert_false( 1013 rightNode.hasAttribute("data-foo"), 1014 `The right node shouldn't have data-foo attribute (isConnected=${leftNode.isConnected}, ${t.name})` 1015 ); 1016 }); 1017 assert_equals( 1018 leftNode.isConnected ^ rightNode.isConnected, 1019 1, 1020 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 1021 ); 1022 }, "Joining <h3 data-foo=\"left\"> and <div data-bar=\"right\">"); 1023 1024 // Same tests for <div> and <h3> because they may be handled in a different 1025 // path. 1026 promise_test(async t => { 1027 utils.setupEditingHost( 1028 `<div id="left">abc${caretForForwardDelete}</div><h3 id="right">${caretForBackSpace}def</h3>` 1029 ); 1030 const leftNode = document.getElementById("left"); 1031 const rightNode = document.getElementById("right"); 1032 1033 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 1034 1035 test(() => { 1036 assert_equals( 1037 leftNode.getAttribute("id"), 1038 "left", 1039 `The left node should keep having id=left (isConnected=${leftNode.isConnected}, ${t.name})` 1040 ); 1041 }); 1042 test(() => { 1043 assert_equals( 1044 rightNode.getAttribute("id"), 1045 "right", 1046 `The right node should keep having id=right (isConnected=${rightNode.isConnected}, ${t.name})` 1047 ); 1048 }); 1049 assert_equals( 1050 leftNode.isConnected ^ rightNode.isConnected, 1051 1, 1052 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 1053 ); 1054 }, "Joining <div id=\"left\"> and <h3 id=\"right\">"); 1055 1056 promise_test(async t => { 1057 utils.setupEditingHost( 1058 `<div class="left">abc${caretForForwardDelete}</div><h3 class="right">${caretForBackSpace}def</h3>` 1059 ); 1060 const leftNode = utils.editingHost.querySelector(".left"); 1061 const rightNode = utils.editingHost.querySelector(".right"); 1062 1063 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 1064 1065 test(() => { 1066 assert_equals( 1067 leftNode.getAttribute("class"), 1068 "left", 1069 `The left node should keep having class=left (isConnected=${leftNode.isConnected}, ${t.name})` 1070 ); 1071 }); 1072 test(() => { 1073 assert_equals( 1074 rightNode.getAttribute("class"), 1075 "right", 1076 `The right node should keep having class=right (isConnected=${rightNode.isConnected}, ${t.name})` 1077 ); 1078 }); 1079 assert_equals( 1080 leftNode.isConnected ^ rightNode.isConnected, 1081 1, 1082 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 1083 ); 1084 }, "Joining <div class=\"left\"> and <h3 class=\"right\">"); 1085 1086 promise_test(async t => { 1087 utils.setupEditingHost( 1088 `<div style="font-size:0.8rem">abc${caretForForwardDelete}</div><h3 style="font-weight:bold">${caretForBackSpace}def</h3>` 1089 ); 1090 const leftNode = utils.editingHost.querySelector("div[style]"); 1091 const rightNode = utils.editingHost.querySelector("h3[style]"); 1092 1093 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 1094 1095 // style attribute values shouldn't be touched in this but case, but it's 1096 // okay if the values are not merged. 1097 test(() => { 1098 assert_true( 1099 leftNode.getAttribute("style").includes("font-size"), 1100 `The left node should keep having style attribute containing font-size (style="${leftNode.getAttribute("style")}", ${t.name})` 1101 ); 1102 assert_false( 1103 leftNode.getAttribute("style").includes("font-weight"), 1104 `The left node should have font-weight in its style attribute (style="${leftNode.getAttribute("style")}", ${t.name})` 1105 ); 1106 }); 1107 test(() => { 1108 assert_true( 1109 rightNode.getAttribute("style").includes("font-weight"), 1110 `The right node should keep having style attribute containing font-size (style="${rightNode.getAttribute("style")}", ${t.name})` 1111 ); 1112 assert_false( 1113 rightNode.getAttribute("style").includes("font-style"), 1114 `The right node should have font-size in its style attribute (style="${rightNode.getAttribute("style")}", ${t.name})` 1115 ); 1116 }); 1117 assert_equals( 1118 leftNode.isConnected ^ rightNode.isConnected, 1119 1, 1120 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 1121 ); 1122 }, "Joining <div style=\"font-size:0.8rem\"> and <h3 style=\"font-weight:bold\">"); 1123 1124 promise_test(async t => { 1125 utils.setupEditingHost( 1126 `<div data-foo="left">abc${caretForForwardDelete}</div><h3 data-bar="right">${caretForBackSpace}def</h3>` 1127 ); 1128 const leftNode = utils.editingHost.querySelector("[data-foo=left]"); 1129 const rightNode = utils.editingHost.querySelector("[data-bar=right]"); 1130 1131 await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey()); 1132 1133 test(() => { 1134 assert_equals( 1135 leftNode.getAttribute("data-foo"), 1136 "left", 1137 `The left node should keep having class=left (isConnected=${leftNode.isConnected}, ${t.name})` 1138 ); 1139 }); 1140 test(() => { 1141 assert_false( 1142 leftNode.hasAttribute("data-bar"), 1143 `The left node shouldn't have data-bar attribute (isConnected=${leftNode.isConnected}, ${t.name})` 1144 ); 1145 }); 1146 test(() => { 1147 assert_equals( 1148 rightNode.getAttribute("data-bar"), 1149 "right", 1150 `The right node should keep having class=right (isConnected=${rightNode.isConnected}, ${t.name})` 1151 ); 1152 }); 1153 test(() => { 1154 assert_false( 1155 rightNode.hasAttribute("data-foo"), 1156 `The right node shouldn't have data-foo attribute (isConnected=${leftNode.isConnected}, ${t.name})` 1157 ); 1158 }); 1159 assert_equals( 1160 leftNode.isConnected ^ rightNode.isConnected, 1161 1, 1162 `One should stay in the document and the other should be disconnected (${utils.editingHost.innerHTML}, ${t.name})` 1163 ); 1164 }, "Joining <div data-foo=\"left\"> and <h3 data-bar=\"right\">"); 1165 1166 1167 </script>