forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			501 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			501 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/* This Source Code Form is subject to the terms of the Mozilla Public
 | 
						|
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
						|
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
						|
 | 
						|
function test() {
 | 
						|
  waitForExplicitFinish();
 | 
						|
 | 
						|
  ok(PopupNotifications, "PopupNotifications object exists");
 | 
						|
  ok(PopupNotifications.panel, "PopupNotifications panel exists");
 | 
						|
 | 
						|
  setup();
 | 
						|
}
 | 
						|
 | 
						|
var gNotification;
 | 
						|
 | 
						|
var tests = [
 | 
						|
  // panel updates should fire the showing and shown callbacks again.
 | 
						|
  {
 | 
						|
    id: "Test#1",
 | 
						|
    run() {
 | 
						|
      this.notifyObj = new BasicNotification(this.id);
 | 
						|
      this.notification = showNotification(this.notifyObj);
 | 
						|
    },
 | 
						|
    onShown(popup) {
 | 
						|
      checkPopup(popup, this.notifyObj);
 | 
						|
 | 
						|
      this.notifyObj.showingCallbackTriggered = false;
 | 
						|
      this.notifyObj.shownCallbackTriggered = false;
 | 
						|
 | 
						|
      // Force an update of the panel. This is typically called
 | 
						|
      // automatically when receiving 'activate' or 'TabSelect' events,
 | 
						|
      // but from a setTimeout, which is inconvenient for the test.
 | 
						|
      PopupNotifications._update();
 | 
						|
 | 
						|
      checkPopup(popup, this.notifyObj);
 | 
						|
 | 
						|
      this.notification.remove();
 | 
						|
    },
 | 
						|
    onHidden() {},
 | 
						|
  },
 | 
						|
  // A first dismissed notification shouldn't stop _update from showing a second notification
 | 
						|
  {
 | 
						|
    id: "Test#2",
 | 
						|
    run() {
 | 
						|
      this.notifyObj1 = new BasicNotification(this.id);
 | 
						|
      this.notifyObj1.id += "_1";
 | 
						|
      this.notifyObj1.anchorID = "default-notification-icon";
 | 
						|
      this.notifyObj1.options.dismissed = true;
 | 
						|
      this.notification1 = showNotification(this.notifyObj1);
 | 
						|
 | 
						|
      this.notifyObj2 = new BasicNotification(this.id);
 | 
						|
      this.notifyObj2.id += "_2";
 | 
						|
      this.notifyObj2.anchorID = "geo-notification-icon";
 | 
						|
      this.notifyObj2.options.dismissed = true;
 | 
						|
      this.notification2 = showNotification(this.notifyObj2);
 | 
						|
 | 
						|
      this.notification2.dismissed = false;
 | 
						|
      PopupNotifications._update();
 | 
						|
    },
 | 
						|
    onShown(popup) {
 | 
						|
      checkPopup(popup, this.notifyObj2);
 | 
						|
      this.notification1.remove();
 | 
						|
      this.notification2.remove();
 | 
						|
    },
 | 
						|
    onHidden(popup) {},
 | 
						|
  },
 | 
						|
  // The anchor icon should be shown for notifications in background windows.
 | 
						|
  {
 | 
						|
    id: "Test#3",
 | 
						|
    async run() {
 | 
						|
      let notifyObj = new BasicNotification(this.id);
 | 
						|
      notifyObj.options.dismissed = true;
 | 
						|
 | 
						|
      let win = await BrowserTestUtils.openNewBrowserWindow();
 | 
						|
 | 
						|
      // Open the notification in the original window, now in the background.
 | 
						|
      let notification = showNotification(notifyObj);
 | 
						|
      let anchor = document.getElementById("default-notification-icon");
 | 
						|
      is(anchor.getAttribute("showing"), "true", "the anchor is shown");
 | 
						|
      notification.remove();
 | 
						|
 | 
						|
      await BrowserTestUtils.closeWindow(win);
 | 
						|
      await waitForWindowReadyForPopupNotifications(window);
 | 
						|
 | 
						|
      goNext();
 | 
						|
    },
 | 
						|
  },
 | 
						|
  // Test that persistent doesn't allow the notification to persist after
 | 
						|
  // navigation.
 | 
						|
  {
 | 
						|
    id: "Test#4",
 | 
						|
    async run() {
 | 
						|
      this.oldSelectedTab = gBrowser.selectedTab;
 | 
						|
      await BrowserTestUtils.openNewForegroundTab(
 | 
						|
        gBrowser,
 | 
						|
        // eslint-disable-next-line @microsoft/sdl/no-insecure-url
 | 
						|
        "http://example.com/"
 | 
						|
      );
 | 
						|
      this.notifyObj = new BasicNotification(this.id);
 | 
						|
      this.notifyObj.addOptions({
 | 
						|
        persistent: true,
 | 
						|
      });
 | 
						|
      this.notification = showNotification(this.notifyObj);
 | 
						|
    },
 | 
						|
    async onShown(popup) {
 | 
						|
      this.complete = false;
 | 
						|
 | 
						|
      // eslint-disable-next-line @microsoft/sdl/no-insecure-url
 | 
						|
      await promiseTabLoadEvent(gBrowser.selectedTab, "http://example.org/");
 | 
						|
      // eslint-disable-next-line @microsoft/sdl/no-insecure-url
 | 
						|
      await promiseTabLoadEvent(gBrowser.selectedTab, "http://example.com/");
 | 
						|
 | 
						|
      // This code should not be executed.
 | 
						|
      ok(false, "Should have removed the notification after navigation");
 | 
						|
      // Properly dismiss and cleanup in case the unthinkable happens.
 | 
						|
      this.complete = true;
 | 
						|
      triggerSecondaryCommand(popup, 0);
 | 
						|
    },
 | 
						|
    onHidden(popup) {
 | 
						|
      ok(
 | 
						|
        !this.complete,
 | 
						|
        "Should have hidden the notification after navigation"
 | 
						|
      );
 | 
						|
      this.notification.remove();
 | 
						|
      gBrowser.removeTab(gBrowser.selectedTab);
 | 
						|
      gBrowser.selectedTab = this.oldSelectedTab;
 | 
						|
    },
 | 
						|
  },
 | 
						|
  // Test that persistent allows the notification to persist until explicitly
 | 
						|
  // dismissed.
 | 
						|
  {
 | 
						|
    id: "Test#5",
 | 
						|
    async run() {
 | 
						|
      this.oldSelectedTab = gBrowser.selectedTab;
 | 
						|
      await BrowserTestUtils.openNewForegroundTab(
 | 
						|
        gBrowser,
 | 
						|
        // eslint-disable-next-line @microsoft/sdl/no-insecure-url
 | 
						|
        "http://example.com/"
 | 
						|
      );
 | 
						|
      this.notifyObj = new BasicNotification(this.id);
 | 
						|
      this.notifyObj.addOptions({
 | 
						|
        persistent: true,
 | 
						|
      });
 | 
						|
      this.notification = showNotification(this.notifyObj);
 | 
						|
    },
 | 
						|
    async onShown(popup) {
 | 
						|
      this.complete = false;
 | 
						|
 | 
						|
      // Notification should persist after attempt to dismiss by clicking on the
 | 
						|
      // content area.
 | 
						|
      let browser = gBrowser.selectedBrowser;
 | 
						|
      await BrowserTestUtils.synthesizeMouseAtCenter("body", {}, browser);
 | 
						|
 | 
						|
      // Notification should be hidden after dismissal via Don't Allow.
 | 
						|
      this.complete = true;
 | 
						|
      triggerSecondaryCommand(popup, 0);
 | 
						|
    },
 | 
						|
    onHidden(popup) {
 | 
						|
      ok(
 | 
						|
        this.complete,
 | 
						|
        "Should have hidden the notification after clicking Not Now"
 | 
						|
      );
 | 
						|
      this.notification.remove();
 | 
						|
      gBrowser.removeTab(gBrowser.selectedTab);
 | 
						|
      gBrowser.selectedTab = this.oldSelectedTab;
 | 
						|
    },
 | 
						|
  },
 | 
						|
  // Test that persistent panels are still open after switching to another tab
 | 
						|
  // and back.
 | 
						|
  {
 | 
						|
    id: "Test#6a",
 | 
						|
    run() {
 | 
						|
      this.notifyObj = new BasicNotification(this.id);
 | 
						|
      this.notifyObj.options.persistent = true;
 | 
						|
      gNotification = showNotification(this.notifyObj);
 | 
						|
    },
 | 
						|
    async onShown(popup) {
 | 
						|
      this.oldSelectedTab = gBrowser.selectedTab;
 | 
						|
      await BrowserTestUtils.openNewForegroundTab(
 | 
						|
        gBrowser,
 | 
						|
        // eslint-disable-next-line @microsoft/sdl/no-insecure-url
 | 
						|
        "http://example.com/"
 | 
						|
      );
 | 
						|
    },
 | 
						|
    onHidden(popup) {
 | 
						|
      ok(true, "Should have hidden the notification after tab switch");
 | 
						|
      gBrowser.removeTab(gBrowser.selectedTab);
 | 
						|
      gBrowser.selectedTab = this.oldSelectedTab;
 | 
						|
    },
 | 
						|
  },
 | 
						|
  // Second part of the previous test that compensates for the limitation in
 | 
						|
  // runNextTest that expects a single onShown/onHidden invocation per test.
 | 
						|
  {
 | 
						|
    id: "Test#6b",
 | 
						|
    run() {
 | 
						|
      let id =
 | 
						|
        PopupNotifications.panel.firstElementChild.getAttribute("popupid");
 | 
						|
      ok(
 | 
						|
        id.endsWith("Test#6a"),
 | 
						|
        "Should have found the notification from Test6a"
 | 
						|
      );
 | 
						|
      ok(
 | 
						|
        PopupNotifications.isPanelOpen,
 | 
						|
        "Should have shown the popup again after getting back to the tab"
 | 
						|
      );
 | 
						|
      gNotification.remove();
 | 
						|
      gNotification = null;
 | 
						|
      goNext();
 | 
						|
    },
 | 
						|
  },
 | 
						|
  // Test that persistent panels are still open after switching to another
 | 
						|
  // window and back.
 | 
						|
  {
 | 
						|
    id: "Test#7",
 | 
						|
    async run() {
 | 
						|
      this.oldSelectedTab = gBrowser.selectedTab;
 | 
						|
      await BrowserTestUtils.openNewForegroundTab(
 | 
						|
        gBrowser,
 | 
						|
        // eslint-disable-next-line @microsoft/sdl/no-insecure-url
 | 
						|
        "http://example.com/"
 | 
						|
      );
 | 
						|
      let firstTab = gBrowser.selectedTab;
 | 
						|
 | 
						|
      await BrowserTestUtils.openNewForegroundTab(
 | 
						|
        gBrowser,
 | 
						|
        // eslint-disable-next-line @microsoft/sdl/no-insecure-url
 | 
						|
        "http://example.com/"
 | 
						|
      );
 | 
						|
 | 
						|
      let shown = waitForNotificationPanel();
 | 
						|
      let notifyObj = new BasicNotification(this.id);
 | 
						|
      notifyObj.options.persistent = true;
 | 
						|
      this.notification = showNotification(notifyObj);
 | 
						|
      await shown;
 | 
						|
 | 
						|
      ok(
 | 
						|
        notifyObj.shownCallbackTriggered,
 | 
						|
        "Should have triggered the shown event"
 | 
						|
      );
 | 
						|
      ok(
 | 
						|
        notifyObj.showingCallbackTriggered,
 | 
						|
        "Should have triggered the showing event"
 | 
						|
      );
 | 
						|
      // Reset to false so that we can ensure these are not fired a second time.
 | 
						|
      notifyObj.shownCallbackTriggered = false;
 | 
						|
      notifyObj.showingCallbackTriggered = false;
 | 
						|
      let timeShown = this.notification.timeShown;
 | 
						|
 | 
						|
      let promiseWin = BrowserTestUtils.waitForNewWindow();
 | 
						|
      gBrowser.replaceTabWithWindow(firstTab);
 | 
						|
      let win = await promiseWin;
 | 
						|
 | 
						|
      let anchor = win.document.getElementById("default-notification-icon");
 | 
						|
      win.PopupNotifications._reshowNotifications(anchor);
 | 
						|
      ok(
 | 
						|
        !win.PopupNotifications.panel.children.length,
 | 
						|
        "no notification displayed in new window"
 | 
						|
      );
 | 
						|
 | 
						|
      await BrowserTestUtils.closeWindow(win);
 | 
						|
      await waitForWindowReadyForPopupNotifications(window);
 | 
						|
 | 
						|
      let id =
 | 
						|
        PopupNotifications.panel.firstElementChild.getAttribute("popupid");
 | 
						|
      ok(
 | 
						|
        id.endsWith("Test#7"),
 | 
						|
        "Should have found the notification from Test7"
 | 
						|
      );
 | 
						|
      ok(
 | 
						|
        PopupNotifications.isPanelOpen,
 | 
						|
        "Should have kept the popup on the first window"
 | 
						|
      );
 | 
						|
      ok(
 | 
						|
        !notifyObj.dismissalCallbackTriggered,
 | 
						|
        "Should not have triggered a dismissed event"
 | 
						|
      );
 | 
						|
      ok(
 | 
						|
        !notifyObj.shownCallbackTriggered,
 | 
						|
        "Should not have triggered a second shown event"
 | 
						|
      );
 | 
						|
      ok(
 | 
						|
        !notifyObj.showingCallbackTriggered,
 | 
						|
        "Should not have triggered a second showing event"
 | 
						|
      );
 | 
						|
      ok(
 | 
						|
        this.notification.timeShown > timeShown,
 | 
						|
        "should have updated timeShown to restart the security delay"
 | 
						|
      );
 | 
						|
 | 
						|
      this.notification.remove();
 | 
						|
      gBrowser.removeTab(gBrowser.selectedTab);
 | 
						|
      gBrowser.selectedTab = this.oldSelectedTab;
 | 
						|
 | 
						|
      goNext();
 | 
						|
    },
 | 
						|
  },
 | 
						|
  // Test that only the first persistent notification is shown on update
 | 
						|
  {
 | 
						|
    id: "Test#8",
 | 
						|
    run() {
 | 
						|
      this.notifyObj1 = new BasicNotification(this.id);
 | 
						|
      this.notifyObj1.id += "_1";
 | 
						|
      this.notifyObj1.anchorID = "default-notification-icon";
 | 
						|
      this.notifyObj1.options.persistent = true;
 | 
						|
      this.notification1 = showNotification(this.notifyObj1);
 | 
						|
 | 
						|
      this.notifyObj2 = new BasicNotification(this.id);
 | 
						|
      this.notifyObj2.id += "_2";
 | 
						|
      this.notifyObj2.anchorID = "geo-notification-icon";
 | 
						|
      this.notifyObj2.options.persistent = true;
 | 
						|
      this.notification2 = showNotification(this.notifyObj2);
 | 
						|
 | 
						|
      PopupNotifications._update();
 | 
						|
    },
 | 
						|
    onShown(popup) {
 | 
						|
      checkPopup(popup, this.notifyObj1);
 | 
						|
      this.notification1.remove();
 | 
						|
      this.notification2.remove();
 | 
						|
    },
 | 
						|
    onHidden(popup) {},
 | 
						|
  },
 | 
						|
  // Test that persistent notifications are shown stacked by anchor on update
 | 
						|
  {
 | 
						|
    id: "Test#9",
 | 
						|
    run() {
 | 
						|
      this.notifyObj1 = new BasicNotification(this.id);
 | 
						|
      this.notifyObj1.id += "_1";
 | 
						|
      this.notifyObj1.anchorID = "default-notification-icon";
 | 
						|
      this.notifyObj1.options.persistent = true;
 | 
						|
      this.notification1 = showNotification(this.notifyObj1);
 | 
						|
 | 
						|
      this.notifyObj2 = new BasicNotification(this.id);
 | 
						|
      this.notifyObj2.id += "_2";
 | 
						|
      this.notifyObj2.anchorID = "geo-notification-icon";
 | 
						|
      this.notifyObj2.options.persistent = true;
 | 
						|
      this.notification2 = showNotification(this.notifyObj2);
 | 
						|
 | 
						|
      this.notifyObj3 = new BasicNotification(this.id);
 | 
						|
      this.notifyObj3.id += "_3";
 | 
						|
      this.notifyObj3.anchorID = "default-notification-icon";
 | 
						|
      this.notifyObj3.options.persistent = true;
 | 
						|
      this.notification3 = showNotification(this.notifyObj3);
 | 
						|
 | 
						|
      PopupNotifications._update();
 | 
						|
    },
 | 
						|
    onShown(popup) {
 | 
						|
      let notifications = popup.children;
 | 
						|
      is(notifications.length, 2, "two notifications displayed");
 | 
						|
      let [notification1, notification2] = notifications;
 | 
						|
      is(
 | 
						|
        notification1.id,
 | 
						|
        this.notifyObj1.id + "-notification",
 | 
						|
        "id 1 matches"
 | 
						|
      );
 | 
						|
      is(
 | 
						|
        notification2.id,
 | 
						|
        this.notifyObj3.id + "-notification",
 | 
						|
        "id 2 matches"
 | 
						|
      );
 | 
						|
 | 
						|
      this.notification1.remove();
 | 
						|
      this.notification2.remove();
 | 
						|
      this.notification3.remove();
 | 
						|
    },
 | 
						|
    onHidden(popup) {},
 | 
						|
  },
 | 
						|
  // Test that on closebutton click, only the persistent notification
 | 
						|
  // that contained the closebutton loses its persistent status.
 | 
						|
  {
 | 
						|
    id: "Test#10",
 | 
						|
    run() {
 | 
						|
      this.notifyObj1 = new BasicNotification(this.id);
 | 
						|
      this.notifyObj1.id += "_1";
 | 
						|
      this.notifyObj1.anchorID = "geo-notification-icon";
 | 
						|
      this.notifyObj1.options.persistent = true;
 | 
						|
      this.notifyObj1.options.hideClose = false;
 | 
						|
      this.notification1 = showNotification(this.notifyObj1);
 | 
						|
 | 
						|
      this.notifyObj2 = new BasicNotification(this.id);
 | 
						|
      this.notifyObj2.id += "_2";
 | 
						|
      this.notifyObj2.anchorID = "geo-notification-icon";
 | 
						|
      this.notifyObj2.options.persistent = true;
 | 
						|
      this.notifyObj2.options.hideClose = false;
 | 
						|
      this.notification2 = showNotification(this.notifyObj2);
 | 
						|
 | 
						|
      this.notifyObj3 = new BasicNotification(this.id);
 | 
						|
      this.notifyObj3.id += "_3";
 | 
						|
      this.notifyObj3.anchorID = "geo-notification-icon";
 | 
						|
      this.notifyObj3.options.persistent = true;
 | 
						|
      this.notifyObj3.options.hideClose = false;
 | 
						|
      this.notification3 = showNotification(this.notifyObj3);
 | 
						|
 | 
						|
      PopupNotifications._update();
 | 
						|
    },
 | 
						|
    onShown(popup) {
 | 
						|
      let notifications = popup.children;
 | 
						|
      is(notifications.length, 3, "three notifications displayed");
 | 
						|
      EventUtils.synthesizeMouseAtCenter(notifications[1].closebutton, {});
 | 
						|
    },
 | 
						|
    onHidden(popup) {
 | 
						|
      let notifications = popup.children;
 | 
						|
      is(notifications.length, 2, "two notifications displayed");
 | 
						|
 | 
						|
      ok(this.notification1.options.persistent, "notification 1 is persistent");
 | 
						|
      ok(
 | 
						|
        !this.notification2.options.persistent,
 | 
						|
        "notification 2 is not persistent"
 | 
						|
      );
 | 
						|
      ok(this.notification3.options.persistent, "notification 3 is persistent");
 | 
						|
 | 
						|
      this.notification1.remove();
 | 
						|
      this.notification2.remove();
 | 
						|
      this.notification3.remove();
 | 
						|
    },
 | 
						|
  },
 | 
						|
  // Test clicking the anchor icon.
 | 
						|
  // Clicking the anchor of an already visible persistent notification should
 | 
						|
  // focus the main action button, but not cause additional showing/shown event
 | 
						|
  // callback calls.
 | 
						|
  // Clicking the anchor of a dismissed notification should show it, even when
 | 
						|
  // the currently displayed notification is a persistent one.
 | 
						|
  {
 | 
						|
    id: "Test#11",
 | 
						|
    async run() {
 | 
						|
      await SpecialPowers.pushPrefEnv({ set: [["accessibility.tabfocus", 7]] });
 | 
						|
 | 
						|
      function clickAnchor(notifyObj) {
 | 
						|
        let anchor = document.getElementById(notifyObj.anchorID);
 | 
						|
        EventUtils.synthesizeMouseAtCenter(anchor, {});
 | 
						|
      }
 | 
						|
 | 
						|
      let popup = PopupNotifications.panel;
 | 
						|
 | 
						|
      let notifyObj1 = new BasicNotification(this.id);
 | 
						|
      notifyObj1.id += "_1";
 | 
						|
      notifyObj1.anchorID = "default-notification-icon";
 | 
						|
      notifyObj1.options.persistent = true;
 | 
						|
      let shown = waitForNotificationPanel();
 | 
						|
      let notification1 = showNotification(notifyObj1);
 | 
						|
      await shown;
 | 
						|
      checkPopup(popup, notifyObj1);
 | 
						|
      ok(
 | 
						|
        !notifyObj1.dismissalCallbackTriggered,
 | 
						|
        "Should not have dismissed the notification"
 | 
						|
      );
 | 
						|
      notifyObj1.shownCallbackTriggered = false;
 | 
						|
      notifyObj1.showingCallbackTriggered = false;
 | 
						|
 | 
						|
      // Click the anchor. This should focus the closebutton
 | 
						|
      // (because it's the first focusable element), but not
 | 
						|
      // call event callbacks on the notification object.
 | 
						|
      clickAnchor(notifyObj1);
 | 
						|
      is(document.activeElement, popup.children[0].closebutton);
 | 
						|
      ok(
 | 
						|
        !notifyObj1.dismissalCallbackTriggered,
 | 
						|
        "Should not have dismissed the notification"
 | 
						|
      );
 | 
						|
      ok(
 | 
						|
        !notifyObj1.shownCallbackTriggered,
 | 
						|
        "Should have triggered the shown event again"
 | 
						|
      );
 | 
						|
      ok(
 | 
						|
        !notifyObj1.showingCallbackTriggered,
 | 
						|
        "Should have triggered the showing event again"
 | 
						|
      );
 | 
						|
 | 
						|
      // Add another notification.
 | 
						|
      let notifyObj2 = new BasicNotification(this.id);
 | 
						|
      notifyObj2.id += "_2";
 | 
						|
      notifyObj2.anchorID = "geo-notification-icon";
 | 
						|
      notifyObj2.options.dismissed = true;
 | 
						|
      let notification2 = showNotification(notifyObj2);
 | 
						|
 | 
						|
      // Click the anchor of the second notification, this should dismiss the
 | 
						|
      // first notification.
 | 
						|
      shown = waitForNotificationPanel();
 | 
						|
      clickAnchor(notifyObj2);
 | 
						|
      await shown;
 | 
						|
      checkPopup(popup, notifyObj2);
 | 
						|
      ok(
 | 
						|
        notifyObj1.dismissalCallbackTriggered,
 | 
						|
        "Should have dismissed the first notification"
 | 
						|
      );
 | 
						|
 | 
						|
      // Click the anchor of the first notification, it should be shown again.
 | 
						|
      shown = waitForNotificationPanel();
 | 
						|
      clickAnchor(notifyObj1);
 | 
						|
      await shown;
 | 
						|
      checkPopup(popup, notifyObj1);
 | 
						|
      ok(
 | 
						|
        notifyObj2.dismissalCallbackTriggered,
 | 
						|
        "Should have dismissed the second notification"
 | 
						|
      );
 | 
						|
 | 
						|
      // Cleanup.
 | 
						|
      notification1.remove();
 | 
						|
      notification2.remove();
 | 
						|
      goNext();
 | 
						|
    },
 | 
						|
  },
 | 
						|
];
 |