cloning-attributes-at-splitting-element.tentative.html (17242B)
1 <!doctype html> 2 <meta chareset="utf-8"> 3 <meta name="timeout" content="long"> 4 <title>Cloning attributes at splitting an element in contenteditable</title> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 <script src="/resources/testdriver.js"></script> 8 <script src="/resources/testdriver-vendor.js"></script> 9 <script src="/resources/testdriver-actions.js"></script> 10 <script src="../include/editor-test-utils.js"></script> 11 <div contenteditable></div> 12 <script> 13 "use strict"; 14 15 document.execCommand("defaultParagraphSeparator", false, "div"); 16 const utils = 17 new EditorTestUtils(document.querySelector("div[contenteditable]")); 18 19 // DO NOT USE multi-line comment in this file, then, you can comment out 20 // unnecessary tests when you need to attach the browser with a debugger. 21 22 // When an element is being split, all attributes except id attribute should be 23 // cloned to the new element. 24 promise_test(async t => { 25 utils.setupEditingHost(`<div id="splittee">abc[]def</div>`); 26 const splittee = document.getElementById("splittee"); 27 await utils.sendEnterKey(); 28 test(() => { 29 assert_equals( 30 document.getElementById("splittee"), 31 splittee, 32 `The element instance returned by Document.getElementById shouldn't be changed after splitting the element (${t.name})` 33 ); 34 }); 35 test(() => { 36 assert_equals( 37 document.querySelectorAll("[id=splittee]").length, 38 1, 39 `The new element created by splitting an element shouldn't have same id attribute value (${t.name})` 40 ); 41 }); 42 }, "Splitting <div id=\"splittee\">"); 43 44 promise_test(async t => { 45 utils.setupEditingHost(`<div class="splittee">abc[]def</div>`); 46 await utils.sendEnterKey(); 47 const leftNode = utils.editingHost.querySelector("div"); 48 const rightNode = utils.editingHost.querySelector("div + div"); 49 test(() => { 50 assert_equals( 51 leftNode.getAttribute("class"), 52 "splittee", 53 `The left element should keep having the class attribute (${t.name})` 54 ); 55 }); 56 test(() => { 57 assert_equals( 58 rightNode.getAttribute("class"), 59 "splittee", 60 `The right element should keep having the class attribute (${t.name})` 61 ); 62 }); 63 }, "Splitting <div class=\"splittee\">"); 64 65 promise_test(async t => { 66 utils.setupEditingHost(`<div data-foo="1" data-bar="2">abc[]def</div>`); 67 await utils.sendEnterKey(); 68 const leftNode = utils.editingHost.querySelector("div"); 69 const rightNode = utils.editingHost.querySelector("div + div"); 70 test(() => { 71 assert_equals( 72 leftNode.getAttribute("data-foo"), 73 "1", 74 `The left element should keep having the data-foo attribute (${t.name})` 75 ); 76 assert_equals( 77 leftNode.getAttribute("data-bar"), 78 "2", 79 `The left element should keep having the data-bar attribute (${t.name})` 80 ); 81 }); 82 test(() => { 83 assert_equals( 84 rightNode.getAttribute("data-foo"), 85 "1", 86 `The right element should keep having the data-foo attribute (${t.name})` 87 ); 88 assert_equals( 89 rightNode.getAttribute("data-bar"), 90 "2", 91 `The right element should keep having the data-bar attribute (${t.name})` 92 ); 93 }); 94 }, "Splitting <div data-foo=\"1\" data-bar=\"2\">"); 95 96 // Same tests for list items since browsers may use different path to handle 97 // splitting a list item. 98 promise_test(async t => { 99 utils.setupEditingHost(`<ul><li id="splittee">abc[]def</li></ul>`); 100 const splittee = document.getElementById("splittee"); 101 await utils.sendEnterKey(); 102 test(() => { 103 assert_equals( 104 document.getElementById("splittee"), 105 splittee, 106 `The element instance returned by Document.getElementById shouldn't be changed after splitting the element (${t.name})` 107 ); 108 }); 109 test(() => { 110 assert_equals( 111 document.querySelectorAll("[id=splittee]").length, 112 1, 113 `The new element created by splitting an element shouldn't have same id attribute value (${t.name})` 114 ); 115 }); 116 }, "Splitting <li id=\"splittee\">"); 117 118 promise_test(async t => { 119 utils.setupEditingHost(`<ul><li class="splittee">abc[]def</li></ul>`); 120 await utils.sendEnterKey(); 121 const leftNode = utils.editingHost.querySelector("li"); 122 const rightNode = utils.editingHost.querySelector("li + li"); 123 test(() => { 124 assert_equals( 125 leftNode.getAttribute("class"), 126 "splittee", 127 `The left element should keep having the class attribute (${t.name})` 128 ); 129 }); 130 test(() => { 131 assert_equals( 132 rightNode.getAttribute("class"), 133 "splittee", 134 `The right element should keep having the class attribute (${t.name})` 135 ); 136 }); 137 }, "Splitting <li class=\"splittee\">"); 138 139 promise_test(async t => { 140 utils.setupEditingHost(`<ul><li data-foo="1" data-bar="2">abc[]def</li></ul>`); 141 await utils.sendEnterKey(); 142 const leftNode = utils.editingHost.querySelector("li"); 143 const rightNode = utils.editingHost.querySelector("li + li"); 144 test(() => { 145 assert_equals( 146 leftNode.getAttribute("data-foo"), 147 "1", 148 `The left element should keep having the data-foo attribute (${t.name})` 149 ); 150 assert_equals( 151 leftNode.getAttribute("data-bar"), 152 "2", 153 `The left element should keep having the data-bar attribute (${t.name})` 154 ); 155 }); 156 test(() => { 157 assert_equals( 158 rightNode.getAttribute("data-foo"), 159 "1", 160 `The right element should keep having the data-foo attribute (${t.name})` 161 ); 162 assert_equals( 163 rightNode.getAttribute("data-bar"), 164 "2", 165 `The right element should keep having the data-bar attribute (${t.name})` 166 ); 167 }); 168 }, "Splitting <li data-foo=\"1\" data-bar=\"2\">"); 169 170 // Same tests for heading since browsers may use different path to handle 171 // splitting a heading element. 172 promise_test(async t => { 173 utils.setupEditingHost(`<h3 id="p">abc[]def</h3>`); 174 const splittee = document.getElementById("splittee"); 175 await utils.sendEnterKey(); 176 test(() => { 177 assert_equals( 178 document.getElementById("splittee"), 179 splittee, 180 `The element instance returned by Document.getElementById shouldn't be changed after splitting the element (${t.name})` 181 ); 182 }); 183 test(() => { 184 assert_equals( 185 document.querySelectorAll("[id=p]").length, 186 1, 187 `The new element created by splitting an element shouldn't have same id attribute value (${t.name})` 188 ); 189 }); 190 }, "Splitting <h3 id=\"p\">"); 191 192 promise_test(async t => { 193 utils.setupEditingHost(`<h3 class="splittee">abc[]def</h3>`); 194 await utils.sendEnterKey(); 195 const leftNode = utils.editingHost.querySelector("h3"); 196 const rightNode = leftNode.nextSibling; 197 test(() => { 198 assert_equals( 199 leftNode.getAttribute("class"), 200 "splittee", 201 `The left element should keep having the class attribute (${t.name})` 202 ); 203 }); 204 test(() => { 205 assert_equals( 206 rightNode.getAttribute("class"), 207 "splittee", 208 `The right element should keep having the class attribute (${t.name})` 209 ); 210 }); 211 }, "Splitting <h3 class=\"splittee\">"); 212 213 promise_test(async t => { 214 utils.setupEditingHost(`<h3 data-foo="1" data-bar="2">abc[]def</h3>`); 215 await utils.sendEnterKey(); 216 const leftNode = utils.editingHost.querySelector("h3"); 217 const rightNode = leftNode.nextSibling; 218 test(() => { 219 assert_equals( 220 leftNode.getAttribute("data-foo"), 221 "1", 222 `The left element should keep having the data-foo attribute (${t.name})` 223 ); 224 assert_equals( 225 leftNode.getAttribute("data-bar"), 226 "2", 227 `The left element should keep having the data-bar attribute (${t.name})` 228 ); 229 }); 230 test(() => { 231 assert_equals( 232 rightNode.getAttribute("data-foo"), 233 "1", 234 `The right element should keep having the data-foo attribute (${t.name})` 235 ); 236 assert_equals( 237 rightNode.getAttribute("data-bar"), 238 "2", 239 `The right element should keep having the data-bar attribute (${t.name})` 240 ); 241 }); 242 }, "Splitting <h3 data-foo=\"1\" data-bar=\"2\">"); 243 244 // Same tests for <dt> since browsers may use different path to handle 245 // splitting a <dt>. 246 promise_test(async t => { 247 utils.setupEditingHost(`<dl><dt id="splittee">abc[]def</dt></dl>`); 248 const splittee = document.getElementById("splittee"); 249 await utils.sendEnterKey(); 250 test(() => { 251 assert_equals( 252 document.getElementById("splittee"), 253 splittee, 254 `The element instance returned by Document.getElementById shouldn't be changed after splitting the element (${t.name})` 255 ); 256 }); 257 test(() => { 258 assert_equals( 259 document.querySelectorAll("[id=splittee]").length, 260 1, 261 `The new element created by splitting an element shouldn't have same id attribute value (${t.name})` 262 ); 263 }); 264 }, "Splitting <dt id=\"splittee\">"); 265 266 promise_test(async t => { 267 utils.setupEditingHost(`<dl><dt class="splittee">abc[]def</dt></dl>`); 268 await utils.sendEnterKey(); 269 const leftNode = utils.editingHost.querySelector("dt"); 270 const rightNode = leftNode.nextSibling; 271 test(() => { 272 assert_equals( 273 leftNode.getAttribute("class"), 274 "splittee", 275 `The left element should keep having the class attribute (${t.name})` 276 ); 277 }); 278 test(() => { 279 assert_equals( 280 rightNode.getAttribute("class"), 281 "splittee", 282 `The right element should keep having the class attribute (${t.name})` 283 ); 284 }); 285 }, "Splitting <dt class=\"splittee\">"); 286 287 promise_test(async t => { 288 utils.setupEditingHost(`<dl><dt data-foo="1" data-bar="2">abc[]def</dt></dl>`); 289 await utils.sendEnterKey(); 290 const leftNode = utils.editingHost.querySelector("dt"); 291 const rightNode = leftNode.nextSibling; 292 test(() => { 293 assert_equals( 294 leftNode.getAttribute("data-foo"), 295 "1", 296 `The left element should keep having the data-foo attribute (${t.name})` 297 ); 298 assert_equals( 299 leftNode.getAttribute("data-bar"), 300 "2", 301 `The left element should keep having the data-bar attribute (${t.name})` 302 ); 303 }); 304 test(() => { 305 assert_equals( 306 rightNode.getAttribute("data-foo"), 307 "1", 308 `The right element should keep having the data-foo attribute (${t.name})` 309 ); 310 assert_equals( 311 rightNode.getAttribute("data-bar"), 312 "2", 313 `The right element should keep having the data-bar attribute (${t.name})` 314 ); 315 }); 316 }, "Splitting <dt data-foo=\"1\" data-bar=\"2\">"); 317 318 // Same tests for <dd> since browsers may use different path to handle 319 // splitting a <dd>. 320 promise_test(async t => { 321 utils.setupEditingHost(`<dl><dd id="splittee">abc[]def</dd></dl>`); 322 const splittee = document.getElementById("splittee"); 323 await utils.sendEnterKey(); 324 test(() => { 325 assert_equals( 326 document.getElementById("splittee"), 327 splittee, 328 `The element instance returned by Document.getElementById shouldn't be changed after splitting the element (${t.name})` 329 ); 330 }); 331 test(() => { 332 assert_equals( 333 document.querySelectorAll("[id=splittee]").length, 334 1, 335 `The new element created by splitting an element shouldn't have same id attribute value (${t.name})` 336 ); 337 }); 338 }, "Splitting <dd id=\"splittee\">"); 339 340 promise_test(async t => { 341 utils.setupEditingHost(`<dl><dd class="splittee">abc[]def</dd></dl>`); 342 await utils.sendEnterKey(); 343 const leftNode = utils.editingHost.querySelector("dd"); 344 const rightNode = leftNode.nextSibling; 345 test(() => { 346 assert_equals( 347 leftNode.getAttribute("class"), 348 "splittee", 349 `The left element should keep having the class attribute (${t.name})` 350 ); 351 }); 352 test(() => { 353 assert_equals( 354 rightNode.getAttribute("class"), 355 "splittee", 356 `The right element should keep having the class attribute (${t.name})` 357 ); 358 }); 359 }, "Splitting <dd class=\"splittee\">"); 360 361 promise_test(async t => { 362 utils.setupEditingHost(`<dl><dd data-foo="1" data-bar="2">abc[]def</dd></dl>`); 363 await utils.sendEnterKey(); 364 const leftNode = utils.editingHost.querySelector("dd"); 365 const rightNode = leftNode.nextSibling; 366 test(() => { 367 assert_equals( 368 leftNode.getAttribute("data-foo"), 369 "1", 370 `The left element should keep having the data-foo attribute (${t.name})` 371 ); 372 assert_equals( 373 leftNode.getAttribute("data-bar"), 374 "2", 375 `The left element should keep having the data-bar attribute (${t.name})` 376 ); 377 }); 378 test(() => { 379 assert_equals( 380 rightNode.getAttribute("data-foo"), 381 "1", 382 `The right element should keep having the data-foo attribute (${t.name})` 383 ); 384 assert_equals( 385 rightNode.getAttribute("data-bar"), 386 "2", 387 `The right element should keep having the data-bar attribute (${t.name})` 388 ); 389 }); 390 }, "Splitting <dd data-foo=\"1\" data-bar=\"2\">"); 391 392 // Same tests for inline elements. 393 promise_test(async t => { 394 utils.setupEditingHost(`<div id="splittee-parent"><span id="splittee">abc[]def</span></div>`); 395 const splittee = document.getElementById("splittee"); 396 const splitteeParent = document.getElementById("splittee-parent"); 397 await utils.sendEnterKey(); 398 test(() => { 399 assert_equals( 400 document.getElementById("splittee"), 401 splittee, 402 `The element instance returned by Document.getElementById shouldn't be changed after splitting the element (${t.name})` 403 ); 404 }); 405 test(() => { 406 assert_equals( 407 document.getElementById("splittee-parent"), 408 splitteeParent, 409 `The element instance returned by Document.getElementById shouldn't be changed after splitting the element (splittee-parent) (${t.name})` 410 ); 411 }); 412 test(() => { 413 assert_equals( 414 document.querySelectorAll("[id=splittee]").length, 415 1, 416 `The new element created by splitting an element shouldn't have same id attribute value (${t.name})` 417 ); 418 }); 419 test(() => { 420 assert_equals( 421 document.querySelectorAll("[id=splittee-parent]").length, 422 1, 423 `The new element created by splitting an element shouldn't have same id attribute value (splittee-parent) (${t.name})` 424 ); 425 }); 426 }, "Splitting <div id=\"splittee-parent\"> and <span id=\"splittee\">"); 427 428 promise_test(async t => { 429 utils.setupEditingHost(`<div class="splittee-parent"><span class="splittee">abc[]def</span></div>`); 430 await utils.sendEnterKey(); 431 const leftParent = utils.editingHost.querySelector("div"); 432 const leftNode = leftParent.querySelector("span"); 433 const rightParent = utils.editingHost.querySelector("div + div"); 434 const rightNode = rightParent.querySelector("span"); 435 test(() => { 436 assert_equals( 437 leftNode.getAttribute("class"), 438 "splittee", 439 `The left element should keep having the class attribute (${t.name})` 440 ); 441 }); 442 test(() => { 443 assert_equals( 444 leftParent.getAttribute("class"), 445 "splittee-parent", 446 `The left element should keep having the class attribute (splittee-parent) (${t.name})` 447 ); 448 }); 449 test(() => { 450 assert_equals( 451 rightNode.getAttribute("class"), 452 "splittee", 453 `The right element should keep having the class attribute (${t.name})` 454 ); 455 }); 456 test(() => { 457 assert_equals( 458 rightParent.getAttribute("class"), 459 "splittee-parent", 460 `The right element should keep having the class attribute (splittee-parent) (${t.name})` 461 ); 462 }); 463 }, "Splitting <div class=\"splittee-parent\"> and <span class=\"splittee\">"); 464 465 promise_test(async t => { 466 utils.setupEditingHost(`<div data-foo="1" data-bar="2"><span data-foo="3" data-bar="4">abc[]def</span></div>`); 467 await utils.sendEnterKey(); 468 const leftParent = utils.editingHost.querySelector("div"); 469 const leftNode = leftParent.querySelector("span"); 470 const rightParent = utils.editingHost.querySelector("div + div"); 471 const rightNode = rightParent.querySelector("span"); 472 test(() => { 473 assert_equals( 474 leftNode.getAttribute("data-foo"), 475 "3", 476 `The left element should keep having the data-foo attribute (${t.name})` 477 ); 478 assert_equals( 479 leftNode.getAttribute("data-bar"), 480 "4", 481 `The left element should keep having the data-bar attribute (${t.name})` 482 ); 483 }); 484 test(() => { 485 assert_equals( 486 leftParent.getAttribute("data-foo"), 487 "1", 488 `The left element should keep having the data-foo attribute (splittee-parent) (${t.name})` 489 ); 490 assert_equals( 491 leftParent.getAttribute("data-bar"), 492 "2", 493 `The left element should keep having the data-bar attribute (splittee-parent) (${t.name})` 494 ); 495 }); 496 test(() => { 497 assert_equals( 498 rightNode.getAttribute("data-foo"), 499 "3", 500 `The right element should keep having the data-foo attribute (${t.name})` 501 ); 502 assert_equals( 503 rightNode.getAttribute("data-bar"), 504 "4", 505 `The right element should keep having the data-bar attribute (${t.name})` 506 ); 507 }); 508 test(() => { 509 assert_equals( 510 rightParent.getAttribute("data-foo"), 511 "1", 512 `The right element should keep having the data-foo attribute (splittee-parent) (${t.name})` 513 ); 514 assert_equals( 515 rightParent.getAttribute("data-bar"), 516 "2", 517 `The right element should keep having the data-bar attribute (splittee-parent) (${t.name})` 518 ); 519 }); 520 }, "Splitting <div data-foo=\"1\" data-bar=\"2\"> and <span data-foo=\"3\" data-bar=\"4\">"); 521 522 </script>