browser_panelUINotifications.js (16593B)
1 "use strict"; 2 3 const { AppMenuNotifications } = ChromeUtils.importESModule( 4 "resource://gre/modules/AppMenuNotifications.sys.mjs" 5 ); 6 7 /** 8 * Tests that when we click on the main call-to-action of the doorhanger, the provided 9 * action is called, and the doorhanger removed. 10 */ 11 add_task(async function testMainActionCalled() { 12 let options = { 13 gBrowser: window.gBrowser, 14 url: "about:blank", 15 }; 16 17 await BrowserTestUtils.withNewTab(options, function () { 18 is( 19 PanelUI.notificationPanel.state, 20 "closed", 21 "update-manual doorhanger is closed." 22 ); 23 let mainActionCalled = false; 24 let mainAction = { 25 callback: () => { 26 mainActionCalled = true; 27 }, 28 }; 29 AppMenuNotifications.showNotification("update-manual", mainAction); 30 31 isnot( 32 PanelUI.notificationPanel.state, 33 "closed", 34 "update-manual doorhanger is showing." 35 ); 36 let notifications = [...PanelUI.notificationPanel.children].filter( 37 n => !n.hidden 38 ); 39 is( 40 notifications.length, 41 1, 42 "PanelUI doorhanger is only displaying one notification." 43 ); 44 let doorhanger = notifications[0]; 45 is( 46 doorhanger.id, 47 "appMenu-update-manual-notification", 48 "PanelUI is displaying the update-manual notification." 49 ); 50 51 let button = doorhanger.button; 52 button.click(); 53 54 ok(mainActionCalled, "Main action callback was called"); 55 is( 56 PanelUI.notificationPanel.state, 57 "closed", 58 "update-manual doorhanger is closed." 59 ); 60 is( 61 PanelUI.menuButton.hasAttribute("badge-status"), 62 false, 63 "Should not have a badge status" 64 ); 65 }); 66 }); 67 68 /** 69 * This tests that when we click the secondary action for a notification, 70 * it will display the badge for that notification on the PanelUI menu button. 71 * Once we click on this button, we should see an item in the menu which will 72 * call our main action. 73 */ 74 add_task(async function testSecondaryActionWorkflow() { 75 let options = { 76 gBrowser: window.gBrowser, 77 url: "about:blank", 78 }; 79 80 await BrowserTestUtils.withNewTab(options, async function () { 81 is( 82 PanelUI.notificationPanel.state, 83 "closed", 84 "update-manual doorhanger is closed." 85 ); 86 87 let mainActionCalled = false; 88 let mainAction = { 89 callback: () => { 90 mainActionCalled = true; 91 }, 92 }; 93 AppMenuNotifications.showNotification("update-manual", mainAction); 94 95 isnot( 96 PanelUI.notificationPanel.state, 97 "closed", 98 "update-manual doorhanger is showing." 99 ); 100 let notifications = [...PanelUI.notificationPanel.children].filter( 101 n => !n.hidden 102 ); 103 is( 104 notifications.length, 105 1, 106 "PanelUI doorhanger is only displaying one notification." 107 ); 108 let doorhanger = notifications[0]; 109 is( 110 doorhanger.id, 111 "appMenu-update-manual-notification", 112 "PanelUI is displaying the update-manual notification." 113 ); 114 115 let secondaryActionButton = doorhanger.secondaryButton; 116 secondaryActionButton.click(); 117 118 is( 119 PanelUI.notificationPanel.state, 120 "closed", 121 "update-manual doorhanger is closed." 122 ); 123 124 is( 125 PanelUI.menuButton.getAttribute("badge-status"), 126 "update-manual", 127 "Badge is displaying on PanelUI button." 128 ); 129 130 await gCUITestUtils.openMainMenu(); 131 is( 132 PanelUI.menuButton.getAttribute("badge-status"), 133 "update-manual", 134 "Badge is displaying on PanelUI button." 135 ); 136 let menuItem = PanelUI.mainView.querySelector(".panel-banner-item"); 137 is( 138 menuItem.getAttribute("data-l10n-id"), 139 "appmenuitem-banner-update-manual", 140 "Showing correct label" 141 ); 142 is(menuItem.hidden, false, "update-manual menu item is showing."); 143 144 await gCUITestUtils.hideMainMenu(); 145 is( 146 PanelUI.menuButton.getAttribute("badge-status"), 147 "update-manual", 148 "Badge is shown on PanelUI button." 149 ); 150 151 await gCUITestUtils.openMainMenu(); 152 menuItem.click(); 153 ok(mainActionCalled, "Main action callback was called"); 154 155 AppMenuNotifications.removeNotification(/.*/); 156 }); 157 }); 158 159 /** 160 * This tests that the PanelUI update downloading badge and banner 161 * notification are correctly displayed and that clicking the banner 162 * item calls the main action. 163 */ 164 add_task(async function testDownloadingBadge() { 165 let options = { 166 gBrowser: window.gBrowser, 167 url: "about:blank", 168 }; 169 170 await BrowserTestUtils.withNewTab(options, async function () { 171 let mainActionCalled = false; 172 let mainAction = { 173 callback: () => { 174 mainActionCalled = true; 175 }, 176 }; 177 // The downloading notification is always displayed in a dismissed state. 178 AppMenuNotifications.showNotification( 179 "update-downloading", 180 mainAction, 181 undefined, 182 { dismissed: true } 183 ); 184 is(PanelUI.notificationPanel.state, "closed", "doorhanger is closed."); 185 186 is( 187 PanelUI.menuButton.getAttribute("badge-status"), 188 "update-downloading", 189 "Downloading badge is displaying on PanelUI button." 190 ); 191 192 await gCUITestUtils.openMainMenu(); 193 is( 194 PanelUI.menuButton.getAttribute("badge-status"), 195 "update-downloading", 196 "Downloading badge is displaying on PanelUI button." 197 ); 198 let menuItem = PanelUI.mainView.querySelector(".panel-banner-item"); 199 is( 200 menuItem.getAttribute("data-l10n-id"), 201 "appmenuitem-banner-update-downloading", 202 "Showing correct label (downloading)" 203 ); 204 is(menuItem.hidden, false, "update-downloading menu item is showing."); 205 206 await gCUITestUtils.hideMainMenu(); 207 is( 208 PanelUI.menuButton.getAttribute("badge-status"), 209 "update-downloading", 210 "Downloading badge is shown on PanelUI button." 211 ); 212 213 await gCUITestUtils.openMainMenu(); 214 menuItem.click(); 215 ok(mainActionCalled, "Main action callback was called"); 216 217 AppMenuNotifications.removeNotification(/.*/); 218 }); 219 }); 220 221 /** 222 * We want to ensure a few things with this: 223 * - Adding a doorhanger will make a badge disappear 224 * - once the notification for the doorhanger is resolved (removed, not just dismissed), 225 * then we display any other badges that are remaining. 226 */ 227 add_task(async function testInteractionWithBadges() { 228 await BrowserTestUtils.withNewTab("about:blank", async function () { 229 // Remove the fxa toolbar button from the navbar to ensure the notification 230 // is displayed on the app menu button. 231 let { CustomizableUI } = ChromeUtils.importESModule( 232 "moz-src:///browser/components/customizableui/CustomizableUI.sys.mjs" 233 ); 234 CustomizableUI.removeWidgetFromArea("fxa-toolbar-menu-button"); 235 236 AppMenuNotifications.showBadgeOnlyNotification("fxa-needs-authentication"); 237 is( 238 PanelUI.menuButton.getAttribute("badge-status"), 239 "fxa-needs-authentication", 240 "Fxa badge is shown on PanelUI button." 241 ); 242 is( 243 PanelUI.notificationPanel.state, 244 "closed", 245 "update-manual doorhanger is closed." 246 ); 247 248 let mainActionCalled = false; 249 let mainAction = { 250 callback: () => { 251 mainActionCalled = true; 252 }, 253 }; 254 AppMenuNotifications.showNotification("update-manual", mainAction); 255 256 isnot( 257 PanelUI.menuButton.getAttribute("badge-status"), 258 "fxa-needs-authentication", 259 "Fxa badge is hidden on PanelUI button." 260 ); 261 isnot( 262 PanelUI.notificationPanel.state, 263 "closed", 264 "update-manual doorhanger is showing." 265 ); 266 let notifications = [...PanelUI.notificationPanel.children].filter( 267 n => !n.hidden 268 ); 269 is( 270 notifications.length, 271 1, 272 "PanelUI doorhanger is only displaying one notification." 273 ); 274 let doorhanger = notifications[0]; 275 is( 276 doorhanger.id, 277 "appMenu-update-manual-notification", 278 "PanelUI is displaying the update-manual notification." 279 ); 280 281 let secondaryActionButton = doorhanger.secondaryButton; 282 secondaryActionButton.click(); 283 284 is( 285 PanelUI.notificationPanel.state, 286 "closed", 287 "update-manual doorhanger is closed." 288 ); 289 290 is( 291 PanelUI.menuButton.getAttribute("badge-status"), 292 "update-manual", 293 "Badge is displaying on PanelUI button." 294 ); 295 296 await gCUITestUtils.openMainMenu(); 297 is( 298 PanelUI.menuButton.getAttribute("badge-status"), 299 "update-manual", 300 "Badge is displaying on PanelUI button." 301 ); 302 let menuItem = PanelUI.mainView.querySelector(".panel-banner-item"); 303 is( 304 menuItem.getAttribute("data-l10n-id"), 305 "appmenuitem-banner-update-manual", 306 "Showing correct label" 307 ); 308 is(menuItem.hidden, false, "update-manual menu item is showing."); 309 310 menuItem.click(); 311 ok(mainActionCalled, "Main action callback was called"); 312 313 is( 314 PanelUI.menuButton.getAttribute("badge-status"), 315 "fxa-needs-authentication", 316 "Fxa badge is shown on PanelUI button." 317 ); 318 AppMenuNotifications.removeNotification(/.*/); 319 is( 320 PanelUI.menuButton.hasAttribute("badge-status"), 321 false, 322 "Should not have a badge status" 323 ); 324 }); 325 }); 326 327 /** 328 * This tests that adding a badge will not dismiss any existing doorhangers. 329 */ 330 add_task(async function testAddingBadgeWhileDoorhangerIsShowing() { 331 await BrowserTestUtils.withNewTab("about:blank", function () { 332 is( 333 PanelUI.notificationPanel.state, 334 "closed", 335 "update-manual doorhanger is closed." 336 ); 337 let mainActionCalled = false; 338 let mainAction = { 339 callback: () => { 340 mainActionCalled = true; 341 }, 342 }; 343 AppMenuNotifications.showNotification("update-manual", mainAction); 344 AppMenuNotifications.showBadgeOnlyNotification("fxa-needs-authentication"); 345 346 isnot( 347 PanelUI.menuButton.getAttribute("badge-status"), 348 "fxa-needs-authentication", 349 "Fxa badge is hidden on PanelUI button." 350 ); 351 isnot( 352 PanelUI.notificationPanel.state, 353 "closed", 354 "update-manual doorhanger is showing." 355 ); 356 let notifications = [...PanelUI.notificationPanel.children].filter( 357 n => !n.hidden 358 ); 359 is( 360 notifications.length, 361 1, 362 "PanelUI doorhanger is only displaying one notification." 363 ); 364 let doorhanger = notifications[0]; 365 is( 366 doorhanger.id, 367 "appMenu-update-manual-notification", 368 "PanelUI is displaying the update-manual notification." 369 ); 370 371 let mainActionButton = doorhanger.button; 372 mainActionButton.click(); 373 374 ok(mainActionCalled, "Main action callback was called"); 375 is( 376 PanelUI.notificationPanel.state, 377 "closed", 378 "update-manual doorhanger is closed." 379 ); 380 is( 381 PanelUI.menuButton.getAttribute("badge-status"), 382 "fxa-needs-authentication", 383 "Fxa badge is shown on PanelUI button." 384 ); 385 AppMenuNotifications.removeNotification(/.*/); 386 is( 387 PanelUI.menuButton.hasAttribute("badge-status"), 388 false, 389 "Should not have a badge status" 390 ); 391 }); 392 }); 393 394 /** 395 * Tests that badges operate like a stack. 396 */ 397 add_task(async function testMultipleBadges() { 398 await BrowserTestUtils.withNewTab("about:blank", async function (browser) { 399 let doc = browser.ownerDocument; 400 let menuButton = doc.getElementById("PanelUI-menu-button"); 401 402 is( 403 menuButton.hasAttribute("badge-status"), 404 false, 405 "Should not have a badge status" 406 ); 407 is( 408 menuButton.hasAttribute("badge"), 409 false, 410 "Should not have the badge attribute set" 411 ); 412 413 AppMenuNotifications.showBadgeOnlyNotification("fxa-needs-authentication"); 414 is( 415 menuButton.getAttribute("badge-status"), 416 "fxa-needs-authentication", 417 "Should have fxa-needs-authentication badge status" 418 ); 419 420 AppMenuNotifications.showBadgeOnlyNotification("update-succeeded"); 421 is( 422 menuButton.getAttribute("badge-status"), 423 "update-succeeded", 424 "Should have update-succeeded badge status (update > fxa)" 425 ); 426 427 AppMenuNotifications.showBadgeOnlyNotification("update-failed"); 428 is( 429 menuButton.getAttribute("badge-status"), 430 "update-failed", 431 "Should have update-failed badge status" 432 ); 433 434 AppMenuNotifications.removeNotification(/^update-/); 435 is( 436 menuButton.getAttribute("badge-status"), 437 "fxa-needs-authentication", 438 "Should have fxa-needs-authentication badge status" 439 ); 440 441 AppMenuNotifications.removeNotification(/^fxa-/); 442 is( 443 menuButton.hasAttribute("badge-status"), 444 false, 445 "Should not have a badge status" 446 ); 447 448 await gCUITestUtils.openMainMenu(); 449 is( 450 menuButton.hasAttribute("badge-status"), 451 false, 452 "Should not have a badge status (Hamburger menu opened)" 453 ); 454 await gCUITestUtils.hideMainMenu(); 455 456 AppMenuNotifications.showBadgeOnlyNotification("fxa-needs-authentication"); 457 AppMenuNotifications.showBadgeOnlyNotification("update-succeeded"); 458 AppMenuNotifications.removeNotification(/.*/); 459 is( 460 menuButton.hasAttribute("badge-status"), 461 false, 462 "Should not have a badge status" 463 ); 464 }); 465 }); 466 467 /** 468 * Tests that non-badges also operate like a stack. 469 */ 470 add_task(async function testMultipleNonBadges() { 471 await BrowserTestUtils.withNewTab("about:blank", async function () { 472 is( 473 PanelUI.notificationPanel.state, 474 "closed", 475 "update-manual doorhanger is closed." 476 ); 477 478 let updateManualAction = { 479 called: false, 480 callback: () => { 481 updateManualAction.called = true; 482 }, 483 }; 484 let updateRestartAction = { 485 called: false, 486 callback: () => { 487 updateRestartAction.called = true; 488 }, 489 }; 490 491 AppMenuNotifications.showNotification("update-manual", updateManualAction); 492 493 let notifications; 494 let doorhanger; 495 496 isnot(PanelUI.notificationPanel.state, "closed", "Doorhanger is showing."); 497 notifications = [...PanelUI.notificationPanel.children].filter( 498 n => !n.hidden 499 ); 500 is( 501 notifications.length, 502 1, 503 "PanelUI doorhanger is only displaying one notification." 504 ); 505 doorhanger = notifications[0]; 506 is( 507 doorhanger.id, 508 "appMenu-update-manual-notification", 509 "PanelUI is displaying the update-manual notification." 510 ); 511 512 AppMenuNotifications.showNotification( 513 "update-restart", 514 updateRestartAction 515 ); 516 517 isnot(PanelUI.notificationPanel.state, "closed", "Doorhanger is showing."); 518 notifications = [...PanelUI.notificationPanel.children].filter( 519 n => !n.hidden 520 ); 521 is( 522 notifications.length, 523 1, 524 "PanelUI doorhanger is only displaying one notification." 525 ); 526 doorhanger = notifications[0]; 527 is( 528 doorhanger.id, 529 "appMenu-update-restart-notification", 530 "PanelUI is displaying the update-restart notification." 531 ); 532 533 let secondaryActionButton = doorhanger.secondaryButton; 534 secondaryActionButton.click(); 535 536 is( 537 PanelUI.notificationPanel.state, 538 "closed", 539 "update-manual doorhanger is closed." 540 ); 541 is( 542 PanelUI.menuButton.getAttribute("badge-status"), 543 "update-restart", 544 "update-restart badge is displaying on PanelUI button." 545 ); 546 547 await gCUITestUtils.openMainMenu(); 548 is( 549 PanelUI.menuButton.getAttribute("badge-status"), 550 "update-restart", 551 "update-restart badge is displaying on PanelUI button." 552 ); 553 let menuItem = PanelUI.mainView.querySelector(".panel-banner-item"); 554 is( 555 menuItem.getAttribute("data-l10n-id"), 556 "appmenuitem-banner-update-restart", 557 "Showing correct label" 558 ); 559 is(menuItem.hidden, false, "update-restart menu item is showing."); 560 561 menuItem.click(); 562 ok( 563 updateRestartAction.called, 564 "update-restart main action callback was called" 565 ); 566 567 is( 568 PanelUI.notificationPanel.state, 569 "closed", 570 "update-manual doorhanger is closed." 571 ); 572 is( 573 PanelUI.menuButton.getAttribute("badge-status"), 574 "update-manual", 575 "update-manual badge is displaying on PanelUI button." 576 ); 577 578 await gCUITestUtils.openMainMenu(); 579 is( 580 PanelUI.menuButton.getAttribute("badge-status"), 581 "update-manual", 582 "update-manual badge is displaying on PanelUI button." 583 ); 584 is( 585 menuItem.getAttribute("data-l10n-id"), 586 "appmenuitem-banner-update-manual", 587 "Showing correct label" 588 ); 589 is(menuItem.hidden, false, "update-manual menu item is showing."); 590 591 menuItem.click(); 592 ok( 593 updateManualAction.called, 594 "update-manual main action callback was called" 595 ); 596 }); 597 });