browser_976792_insertNodeInWindow.js (17337B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 "use strict"; 6 7 const kToolbarName = "test-insertNodeInWindow-placements-toolbar"; 8 const kTestWidgetPrefix = "test-widget-for-insertNodeInWindow-placements-"; 9 10 /* 11 Tries to replicate the situation of having a placement list like this: 12 13 exists-1,trying-to-insert-this,doesn't-exist,exists-2 14 */ 15 add_task(async function () { 16 let testWidgetExists = [true, false, false, true]; 17 let widgetIds = []; 18 for (let i = 0; i < testWidgetExists.length; i++) { 19 let id = kTestWidgetPrefix + i; 20 widgetIds.push(id); 21 if (testWidgetExists[i]) { 22 let spec = { 23 id, 24 type: "button", 25 removable: true, 26 label: "test", 27 tooltiptext: "" + i, 28 }; 29 CustomizableUI.createWidget(spec); 30 } 31 } 32 33 let toolbarNode = createToolbarWithPlacements(kToolbarName, widgetIds); 34 assertAreaPlacements(kToolbarName, widgetIds); 35 36 let btnId = kTestWidgetPrefix + 1; 37 let btn = createDummyXULButton(btnId, "test"); 38 CustomizableUI.ensureWidgetPlacedInWindow(btnId, window); 39 40 is( 41 btn.parentNode.id, 42 kToolbarName, 43 "New XUL widget should be placed inside new toolbar" 44 ); 45 46 is( 47 btn.previousElementSibling.id, 48 toolbarNode.firstElementChild.id, 49 "insertNodeInWindow should have placed new XUL widget in correct place in DOM according to placements" 50 ); 51 52 widgetIds.forEach(id => CustomizableUI.destroyWidget(id)); 53 btn.remove(); 54 removeCustomToolbars(); 55 await resetCustomization(); 56 }); 57 58 /* 59 Tests nodes get placed inside the toolbar's overflow as expected. Replicates a 60 situation similar to: 61 62 exists-1,exists-2,overflow-1,trying-to-insert-this,overflow-2 63 */ 64 add_task(async function () { 65 let navbar = document.getElementById(CustomizableUI.AREA_NAVBAR); 66 67 let widgetIds = []; 68 for (let i = 0; i < 5; i++) { 69 let id = kTestWidgetPrefix + i; 70 widgetIds.push(id); 71 let spec = { 72 id, 73 type: "button", 74 removable: true, 75 label: "insertNodeInWindow test", 76 tooltiptext: "" + i, 77 }; 78 CustomizableUI.createWidget(spec); 79 CustomizableUI.addWidgetToArea(id, "nav-bar"); 80 } 81 82 for (let id of widgetIds) { 83 document.getElementById(id).style.minWidth = "200px"; 84 } 85 86 let originalWindowWidth = window.outerWidth; 87 window.resizeTo(kForceOverflowWidthPx, window.outerHeight); 88 await TestUtils.waitForCondition( 89 () => 90 navbar.hasAttribute("overflowing") && 91 !navbar.querySelector("#" + widgetIds[0]) 92 ); 93 94 let testWidgetId = kTestWidgetPrefix + 3; 95 96 CustomizableUI.destroyWidget(testWidgetId); 97 98 let btn = createDummyXULButton(testWidgetId, "test"); 99 CustomizableUI.ensureWidgetPlacedInWindow(testWidgetId, window); 100 101 ok( 102 navbar.overflowable.isInOverflowList(btn), 103 "New XUL widget should be placed inside overflow of toolbar" 104 ); 105 is( 106 btn.previousElementSibling.id, 107 kTestWidgetPrefix + 2, 108 "insertNodeInWindow should have placed new XUL widget in correct place in DOM according to placements" 109 ); 110 is( 111 btn.nextElementSibling.id, 112 kTestWidgetPrefix + 4, 113 "insertNodeInWindow should have placed new XUL widget in correct place in DOM according to placements" 114 ); 115 116 window.resizeTo(originalWindowWidth, window.outerHeight); 117 118 widgetIds.forEach(id => CustomizableUI.destroyWidget(id)); 119 CustomizableUI.removeWidgetFromArea(btn.id, kToolbarName); 120 btn.remove(); 121 await resetCustomization(); 122 await TestUtils.waitForCondition(() => !navbar.hasAttribute("overflowing")); 123 }); 124 125 /* 126 Tests nodes get placed inside the toolbar's overflow as expected. Replicates a 127 placements situation similar to: 128 129 exists-1,exists-2,overflow-1,doesn't-exist,trying-to-insert-this,overflow-2 130 */ 131 add_task(async function () { 132 let navbar = document.getElementById(CustomizableUI.AREA_NAVBAR); 133 134 let widgetIds = []; 135 for (let i = 0; i < 5; i++) { 136 let id = kTestWidgetPrefix + i; 137 widgetIds.push(id); 138 let spec = { 139 id, 140 type: "button", 141 removable: true, 142 label: "insertNodeInWindow test", 143 tooltiptext: "" + i, 144 }; 145 CustomizableUI.createWidget(spec); 146 CustomizableUI.addWidgetToArea(id, "nav-bar"); 147 } 148 149 for (let id of widgetIds) { 150 document.getElementById(id).style.minWidth = "200px"; 151 } 152 153 let originalWindowWidth = window.outerWidth; 154 window.resizeTo(kForceOverflowWidthPx, window.outerHeight); 155 await TestUtils.waitForCondition( 156 () => 157 navbar.hasAttribute("overflowing") && 158 !navbar.querySelector("#" + widgetIds[0]) 159 ); 160 161 let testWidgetId = kTestWidgetPrefix + 3; 162 163 CustomizableUI.destroyWidget(kTestWidgetPrefix + 2); 164 CustomizableUI.destroyWidget(testWidgetId); 165 166 let btn = createDummyXULButton(testWidgetId, "test"); 167 CustomizableUI.ensureWidgetPlacedInWindow(testWidgetId, window); 168 169 ok( 170 navbar.overflowable.isInOverflowList(btn), 171 "New XUL widget should be placed inside overflow of toolbar" 172 ); 173 is( 174 btn.previousElementSibling.id, 175 kTestWidgetPrefix + 1, 176 "insertNodeInWindow should have placed new XUL widget in correct place in DOM according to placements" 177 ); 178 is( 179 btn.nextElementSibling.id, 180 kTestWidgetPrefix + 4, 181 "insertNodeInWindow should have placed new XUL widget in correct place in DOM according to placements" 182 ); 183 184 window.resizeTo(originalWindowWidth, window.outerHeight); 185 186 widgetIds.forEach(id => CustomizableUI.destroyWidget(id)); 187 CustomizableUI.removeWidgetFromArea(btn.id, kToolbarName); 188 btn.remove(); 189 await resetCustomization(); 190 await TestUtils.waitForCondition(() => !navbar.hasAttribute("overflowing")); 191 }); 192 193 /* 194 Tests nodes get placed inside the toolbar's overflow as expected. Replicates a 195 placements situation similar to: 196 197 exists-1,exists-2,overflow-1,doesn't-exist,trying-to-insert-this,doesn't-exist 198 */ 199 add_task(async function () { 200 let navbar = document.getElementById(CustomizableUI.AREA_NAVBAR); 201 202 let widgetIds = []; 203 for (let i = 0; i < 5; i++) { 204 let id = kTestWidgetPrefix + i; 205 widgetIds.push(id); 206 let spec = { 207 id, 208 type: "button", 209 removable: true, 210 label: "insertNodeInWindow test", 211 tooltiptext: "" + i, 212 }; 213 CustomizableUI.createWidget(spec); 214 CustomizableUI.addWidgetToArea(id, "nav-bar"); 215 } 216 217 for (let id of widgetIds) { 218 document.getElementById(id).style.minWidth = "200px"; 219 } 220 221 let originalWindowWidth = window.outerWidth; 222 window.resizeTo(kForceOverflowWidthPx, window.outerHeight); 223 await TestUtils.waitForCondition( 224 () => 225 navbar.hasAttribute("overflowing") && 226 !navbar.querySelector("#" + widgetIds[0]) 227 ); 228 229 let testWidgetId = kTestWidgetPrefix + 3; 230 231 CustomizableUI.destroyWidget(kTestWidgetPrefix + 2); 232 CustomizableUI.destroyWidget(testWidgetId); 233 CustomizableUI.destroyWidget(kTestWidgetPrefix + 4); 234 235 let btn = createDummyXULButton(testWidgetId, "test"); 236 CustomizableUI.ensureWidgetPlacedInWindow(testWidgetId, window); 237 238 ok( 239 navbar.overflowable.isInOverflowList(btn), 240 "New XUL widget should be placed inside overflow of toolbar" 241 ); 242 is( 243 btn.previousElementSibling.id, 244 kTestWidgetPrefix + 1, 245 "insertNodeInWindow should have placed new XUL widget in correct place in DOM according to placements" 246 ); 247 is( 248 btn.nextElementSibling, 249 null, 250 "insertNodeInWindow should have placed new XUL widget in correct place in DOM according to placements" 251 ); 252 253 window.resizeTo(originalWindowWidth, window.outerHeight); 254 255 widgetIds.forEach(id => CustomizableUI.destroyWidget(id)); 256 CustomizableUI.removeWidgetFromArea(btn.id, kToolbarName); 257 btn.remove(); 258 await resetCustomization(); 259 await TestUtils.waitForCondition(() => !navbar.hasAttribute("overflowing")); 260 }); 261 262 /* 263 Tests nodes get placed inside the toolbar's overflow as expected. Replicates a 264 placements situation similar to: 265 266 exists-1,exists-2,overflow-1,can't-overflow,trying-to-insert-this,overflow-2 267 */ 268 add_task(async function () { 269 let navbar = document.getElementById(CustomizableUI.AREA_NAVBAR); 270 271 let widgetIds = []; 272 for (let i = 5; i >= 0; i--) { 273 let id = kTestWidgetPrefix + i; 274 widgetIds.push(id); 275 let spec = { 276 id, 277 type: "button", 278 removable: true, 279 label: "insertNodeInWindow test", 280 tooltiptext: "" + i, 281 }; 282 CustomizableUI.createWidget(spec); 283 CustomizableUI.addWidgetToArea(id, "nav-bar", 0); 284 } 285 286 for (let i = 10; i < 15; i++) { 287 let id = kTestWidgetPrefix + i; 288 widgetIds.push(id); 289 let spec = { 290 id, 291 type: "button", 292 removable: true, 293 label: "insertNodeInWindow test", 294 tooltiptext: "" + i, 295 }; 296 CustomizableUI.createWidget(spec); 297 CustomizableUI.addWidgetToArea(id, "nav-bar"); 298 } 299 300 for (let id of widgetIds) { 301 document.getElementById(id).style.minWidth = "200px"; 302 } 303 304 let originalWindowWidth = window.outerWidth; 305 window.resizeTo(kForceOverflowWidthPx, window.outerHeight); 306 // Wait for all the widgets to overflow. We can't just wait for the 307 // `overflowing` attribute because we leave time for layout flushes 308 // inbetween, so it's possible for the timeout to run before the 309 // navbar has "settled" 310 await TestUtils.waitForCondition(() => { 311 return ( 312 navbar.hasAttribute("overflowing") && 313 CustomizableUI.getCustomizationTarget( 314 navbar 315 ).lastElementChild.getAttribute("overflows") == "false" 316 ); 317 }); 318 319 // Find last widget that doesn't allow overflowing 320 let nonOverflowing = 321 CustomizableUI.getCustomizationTarget(navbar).lastElementChild; 322 is( 323 nonOverflowing.getAttribute("overflows"), 324 "false", 325 "Last child is expected to not allow overflowing" 326 ); 327 isnot( 328 nonOverflowing.getAttribute("skipintoolbarset"), 329 "true", 330 "Last child is expected to not be skipintoolbarset" 331 ); 332 333 let testWidgetId = kTestWidgetPrefix + 10; 334 CustomizableUI.destroyWidget(testWidgetId); 335 336 let btn = createDummyXULButton(testWidgetId, "test"); 337 CustomizableUI.ensureWidgetPlacedInWindow(testWidgetId, window); 338 339 ok( 340 navbar.overflowable.isInOverflowList(btn), 341 "New XUL widget should be placed inside overflow of toolbar" 342 ); 343 is( 344 btn.nextElementSibling.id, 345 kTestWidgetPrefix + 11, 346 "insertNodeInWindow should have placed new XUL widget in correct place in DOM according to placements" 347 ); 348 349 window.resizeTo(originalWindowWidth, window.outerHeight); 350 351 widgetIds.forEach(id => CustomizableUI.destroyWidget(id)); 352 CustomizableUI.removeWidgetFromArea(btn.id, kToolbarName); 353 btn.remove(); 354 await resetCustomization(); 355 await TestUtils.waitForCondition(() => !navbar.hasAttribute("overflowing")); 356 }); 357 358 /* 359 Tests nodes get placed inside the toolbar's overflow as expected. Replicates a 360 placements situation similar to: 361 362 exists-1,exists-2,overflow-1,trying-to-insert-this,can't-overflow,overflow-2 363 */ 364 add_task(async function () { 365 let widgetIds = []; 366 let missingId = 2; 367 let nonOverflowableId = 3; 368 for (let i = 0; i < 5; i++) { 369 let id = kTestWidgetPrefix + i; 370 widgetIds.push(id); 371 if (i != missingId) { 372 // Setting min-width to make the overflow state not depend on styling of the button and/or 373 // screen width 374 let spec = { 375 id, 376 type: "button", 377 removable: true, 378 label: "test", 379 tooltiptext: "" + i, 380 onCreated(node) { 381 node.style.minWidth = "200px"; 382 if (id == kTestWidgetPrefix + nonOverflowableId) { 383 node.setAttribute("overflows", false); 384 } 385 }, 386 }; 387 info("Creating: " + id); 388 CustomizableUI.createWidget(spec); 389 } 390 } 391 392 let toolbarNode = createOverflowableToolbarWithPlacements( 393 kToolbarName, 394 widgetIds 395 ); 396 assertAreaPlacements(kToolbarName, widgetIds); 397 ok( 398 !toolbarNode.hasAttribute("overflowing"), 399 "Toolbar shouldn't overflow to start with." 400 ); 401 402 let originalWindowWidth = window.outerWidth; 403 window.resizeTo(kForceOverflowWidthPx, window.outerHeight); 404 await TestUtils.waitForCondition( 405 () => 406 toolbarNode.hasAttribute("overflowing") && 407 !toolbarNode.querySelector("#" + widgetIds[1]) 408 ); 409 ok( 410 toolbarNode.hasAttribute("overflowing"), 411 "Should have an overflowing toolbar." 412 ); 413 414 let btnId = kTestWidgetPrefix + missingId; 415 let btn = createDummyXULButton(btnId, "test"); 416 CustomizableUI.ensureWidgetPlacedInWindow(btnId, window); 417 418 is( 419 btn.parentNode.id, 420 kToolbarName + "-overflow-list", 421 "New XUL widget should be placed inside new toolbar's overflow" 422 ); 423 is( 424 btn.previousElementSibling.id, 425 kTestWidgetPrefix + 1, 426 "insertNodeInWindow should have placed new XUL widget in correct place in DOM according to placements" 427 ); 428 is( 429 btn.nextElementSibling.id, 430 kTestWidgetPrefix + 4, 431 "insertNodeInWindow should have placed new XUL widget in correct place in DOM according to placements" 432 ); 433 434 window.resizeTo(originalWindowWidth, window.outerHeight); 435 await TestUtils.waitForCondition( 436 () => !toolbarNode.hasAttribute("overflowing") 437 ); 438 439 btn.remove(); 440 widgetIds.forEach(id => CustomizableUI.destroyWidget(id)); 441 removeCustomToolbars(); 442 await resetCustomization(); 443 }); 444 445 /* 446 Tests nodes do *not* get placed in the toolbar's overflow. Replicates a 447 plcements situation similar to: 448 449 exists-1,trying-to-insert-this,exists-2,overflowed-1 450 */ 451 add_task(async function () { 452 let widgetIds = []; 453 let missingId = 1; 454 for (let i = 0; i < 5; i++) { 455 let id = kTestWidgetPrefix + i; 456 widgetIds.push(id); 457 if (i != missingId) { 458 // Setting min-width to make the overflow state not depend on styling of the button and/or 459 // screen width 460 let spec = { 461 id, 462 type: "button", 463 removable: true, 464 label: "test", 465 tooltiptext: "" + i, 466 onCreated(node) { 467 node.style.minWidth = "200px"; 468 }, 469 }; 470 info("Creating: " + id); 471 CustomizableUI.createWidget(spec); 472 } 473 } 474 475 let toolbarNode = createOverflowableToolbarWithPlacements( 476 kToolbarName, 477 widgetIds 478 ); 479 assertAreaPlacements(kToolbarName, widgetIds); 480 ok( 481 !toolbarNode.hasAttribute("overflowing"), 482 "Toolbar shouldn't overflow to start with." 483 ); 484 485 let originalWindowWidth = window.outerWidth; 486 window.resizeTo(kForceOverflowWidthPx, window.outerHeight); 487 await TestUtils.waitForCondition(() => 488 toolbarNode.hasAttribute("overflowing") 489 ); 490 ok( 491 toolbarNode.hasAttribute("overflowing"), 492 "Should have an overflowing toolbar." 493 ); 494 495 let btnId = kTestWidgetPrefix + missingId; 496 let btn = createDummyXULButton(btnId, "test"); 497 CustomizableUI.ensureWidgetPlacedInWindow(btnId, window); 498 499 is( 500 btn.parentNode.id, 501 kToolbarName + "-target", 502 "New XUL widget should be placed inside new toolbar" 503 ); 504 505 window.resizeTo(originalWindowWidth, window.outerHeight); 506 await TestUtils.waitForCondition( 507 () => !toolbarNode.hasAttribute("overflowing") 508 ); 509 510 btn.remove(); 511 widgetIds.forEach(id => CustomizableUI.destroyWidget(id)); 512 removeCustomToolbars(); 513 await resetCustomization(); 514 }); 515 516 /* 517 Tests inserting a node onto the end of an overflowing toolbar *doesn't* put it in 518 the overflow list when the widget disallows overflowing. ie: 519 520 exists-1,exists-2,overflows-1,trying-to-insert-this 521 522 Where trying-to-insert-this has overflows=false 523 */ 524 add_task(async function () { 525 let widgetIds = []; 526 let missingId = 3; 527 for (let i = 0; i < 5; i++) { 528 let id = kTestWidgetPrefix + i; 529 widgetIds.push(id); 530 if (i != missingId) { 531 // Setting min-width to make the overflow state not depend on styling of the button and/or 532 // screen width 533 let spec = { 534 id, 535 type: "button", 536 removable: true, 537 label: "test", 538 tooltiptext: "" + i, 539 onCreated(node) { 540 node.style.minWidth = "200px"; 541 }, 542 }; 543 info("Creating: " + id); 544 CustomizableUI.createWidget(spec); 545 } 546 } 547 548 let toolbarNode = createOverflowableToolbarWithPlacements( 549 kToolbarName, 550 widgetIds 551 ); 552 assertAreaPlacements(kToolbarName, widgetIds); 553 ok( 554 !toolbarNode.hasAttribute("overflowing"), 555 "Toolbar shouldn't overflow to start with." 556 ); 557 558 let originalWindowWidth = window.outerWidth; 559 window.resizeTo(kForceOverflowWidthPx, window.outerHeight); 560 await TestUtils.waitForCondition(() => 561 toolbarNode.hasAttribute("overflowing") 562 ); 563 ok( 564 toolbarNode.hasAttribute("overflowing"), 565 "Should have an overflowing toolbar." 566 ); 567 568 let btnId = kTestWidgetPrefix + missingId; 569 let btn = createDummyXULButton(btnId, "test"); 570 btn.setAttribute("overflows", false); 571 CustomizableUI.ensureWidgetPlacedInWindow(btnId, window); 572 573 is( 574 btn.parentNode.id, 575 kToolbarName + "-target", 576 "New XUL widget should be placed inside new toolbar" 577 ); 578 is( 579 btn.nextElementSibling, 580 null, 581 "insertNodeInWindow should have placed new XUL widget in correct place in DOM according to placements" 582 ); 583 584 window.resizeTo(originalWindowWidth, window.outerHeight); 585 await TestUtils.waitForCondition( 586 () => !toolbarNode.hasAttribute("overflowing") 587 ); 588 589 btn.remove(); 590 widgetIds.forEach(id => CustomizableUI.destroyWidget(id)); 591 removeCustomToolbars(); 592 await resetCustomization(); 593 }); 594 595 add_task(async function asyncCleanUp() { 596 await resetCustomization(); 597 });