browser/base/content/test/general/browser_popupNotification.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 function test() {
michael@0 6 waitForExplicitFinish();
michael@0 7
michael@0 8 ok(PopupNotifications, "PopupNotifications object exists");
michael@0 9 ok(PopupNotifications.panel, "PopupNotifications panel exists");
michael@0 10
michael@0 11 // Disable transitions as they slow the test down and we want to click the
michael@0 12 // mouse buttons in a predictable location.
michael@0 13 PopupNotifications.transitionsEnabled = false;
michael@0 14
michael@0 15 registerCleanupFunction(cleanUp);
michael@0 16
michael@0 17 runNextTest();
michael@0 18 }
michael@0 19
michael@0 20 function cleanUp() {
michael@0 21 for (var topic in gActiveObservers)
michael@0 22 Services.obs.removeObserver(gActiveObservers[topic], topic);
michael@0 23 for (var eventName in gActiveListeners)
michael@0 24 PopupNotifications.panel.removeEventListener(eventName, gActiveListeners[eventName], false);
michael@0 25 PopupNotifications.buttonDelay = PREF_SECURITY_DELAY_INITIAL;
michael@0 26 PopupNotifications.transitionsEnabled = true;
michael@0 27 }
michael@0 28
michael@0 29 const PREF_SECURITY_DELAY_INITIAL = Services.prefs.getIntPref("security.notification_enable_delay");
michael@0 30
michael@0 31 var gActiveListeners = {};
michael@0 32 var gActiveObservers = {};
michael@0 33 var gShownState = {};
michael@0 34
michael@0 35 function goNext() {
michael@0 36 if (++gTestIndex == tests.length)
michael@0 37 executeSoon(finish);
michael@0 38 else
michael@0 39 executeSoon(runNextTest);
michael@0 40 }
michael@0 41
michael@0 42 function runNextTest() {
michael@0 43 let nextTest = tests[gTestIndex];
michael@0 44
michael@0 45 function addObserver(topic) {
michael@0 46 function observer() {
michael@0 47 Services.obs.removeObserver(observer, "PopupNotifications-" + topic);
michael@0 48 delete gActiveObservers["PopupNotifications-" + topic];
michael@0 49
michael@0 50 info("[Test #" + gTestIndex + "] observer for " + topic + " called");
michael@0 51 nextTest[topic]();
michael@0 52 goNext();
michael@0 53 }
michael@0 54 Services.obs.addObserver(observer, "PopupNotifications-" + topic, false);
michael@0 55 gActiveObservers["PopupNotifications-" + topic] = observer;
michael@0 56 }
michael@0 57
michael@0 58 if (nextTest.backgroundShow) {
michael@0 59 addObserver("backgroundShow");
michael@0 60 } else if (nextTest.updateNotShowing) {
michael@0 61 addObserver("updateNotShowing");
michael@0 62 } else if (nextTest.onShown) {
michael@0 63 doOnPopupEvent("popupshowing", function () {
michael@0 64 info("[Test #" + gTestIndex + "] popup showing");
michael@0 65 });
michael@0 66 doOnPopupEvent("popupshown", function () {
michael@0 67 gShownState[gTestIndex] = true;
michael@0 68 info("[Test #" + gTestIndex + "] popup shown");
michael@0 69 nextTest.onShown(this);
michael@0 70 });
michael@0 71
michael@0 72 // We allow multiple onHidden functions to be defined in an array. They're
michael@0 73 // called in the order they appear.
michael@0 74 let onHiddenArray = nextTest.onHidden instanceof Array ?
michael@0 75 nextTest.onHidden :
michael@0 76 [nextTest.onHidden];
michael@0 77 doOnPopupEvent("popuphidden", function () {
michael@0 78 if (!gShownState[gTestIndex]) {
michael@0 79 // This is expected to happen for test 9, so let's not treat it as a failure.
michael@0 80 info("Popup from test " + gTestIndex + " was hidden before its popupshown fired");
michael@0 81 }
michael@0 82
michael@0 83 let onHidden = onHiddenArray.shift();
michael@0 84 info("[Test #" + gTestIndex + "] popup hidden (" + onHiddenArray.length + " hides remaining)");
michael@0 85 executeSoon(function () {
michael@0 86 onHidden.call(nextTest, this);
michael@0 87 if (!onHiddenArray.length)
michael@0 88 goNext();
michael@0 89 }.bind(this));
michael@0 90 }, onHiddenArray.length);
michael@0 91 info("[Test #" + gTestIndex + "] added listeners; panel state: " + PopupNotifications.isPanelOpen);
michael@0 92 }
michael@0 93
michael@0 94 info("[Test #" + gTestIndex + "] running test");
michael@0 95 nextTest.run();
michael@0 96 }
michael@0 97
michael@0 98 function doOnPopupEvent(eventName, callback, numExpected) {
michael@0 99 gActiveListeners[eventName] = function (event) {
michael@0 100 if (event.target != PopupNotifications.panel)
michael@0 101 return;
michael@0 102 if (typeof(numExpected) === "number")
michael@0 103 numExpected--;
michael@0 104 if (!numExpected) {
michael@0 105 PopupNotifications.panel.removeEventListener(eventName, gActiveListeners[eventName], false);
michael@0 106 delete gActiveListeners[eventName];
michael@0 107 }
michael@0 108
michael@0 109 callback.call(PopupNotifications.panel);
michael@0 110 }
michael@0 111 PopupNotifications.panel.addEventListener(eventName, gActiveListeners[eventName], false);
michael@0 112 }
michael@0 113
michael@0 114 var gTestIndex = 0;
michael@0 115 var gNewTab;
michael@0 116
michael@0 117 function basicNotification() {
michael@0 118 var self = this;
michael@0 119 this.browser = gBrowser.selectedBrowser;
michael@0 120 this.id = "test-notification-" + gTestIndex;
michael@0 121 this.message = "This is popup notification " + this.id + " from test " + gTestIndex;
michael@0 122 this.anchorID = null;
michael@0 123 this.mainAction = {
michael@0 124 label: "Main Action",
michael@0 125 accessKey: "M",
michael@0 126 callback: function () {
michael@0 127 self.mainActionClicked = true;
michael@0 128 }
michael@0 129 };
michael@0 130 this.secondaryActions = [
michael@0 131 {
michael@0 132 label: "Secondary Action",
michael@0 133 accessKey: "S",
michael@0 134 callback: function () {
michael@0 135 self.secondaryActionClicked = true;
michael@0 136 }
michael@0 137 }
michael@0 138 ];
michael@0 139 this.options = {
michael@0 140 eventCallback: function (eventName) {
michael@0 141 switch (eventName) {
michael@0 142 case "dismissed":
michael@0 143 self.dismissalCallbackTriggered = true;
michael@0 144 break;
michael@0 145 case "showing":
michael@0 146 self.showingCallbackTriggered = true;
michael@0 147 break;
michael@0 148 case "shown":
michael@0 149 self.shownCallbackTriggered = true;
michael@0 150 break;
michael@0 151 case "removed":
michael@0 152 self.removedCallbackTriggered = true;
michael@0 153 break;
michael@0 154 case "swapping":
michael@0 155 self.swappingCallbackTriggered = true;
michael@0 156 break;
michael@0 157 }
michael@0 158 }
michael@0 159 };
michael@0 160 }
michael@0 161
michael@0 162 basicNotification.prototype.addOptions = function(options) {
michael@0 163 for (let [name, value] in Iterator(options))
michael@0 164 this.options[name] = value;
michael@0 165 };
michael@0 166
michael@0 167 function errorNotification() {
michael@0 168 var self = this;
michael@0 169 this.mainAction.callback = function () {
michael@0 170 self.mainActionClicked = true;
michael@0 171 throw new Error("Oops!");
michael@0 172 };
michael@0 173 this.secondaryActions[0].callback = function () {
michael@0 174 self.secondaryActionClicked = true;
michael@0 175 throw new Error("Oops!");
michael@0 176 };
michael@0 177 }
michael@0 178
michael@0 179 errorNotification.prototype = new basicNotification();
michael@0 180 errorNotification.prototype.constructor = errorNotification;
michael@0 181
michael@0 182 var wrongBrowserNotificationObject = new basicNotification();
michael@0 183 var wrongBrowserNotification;
michael@0 184
michael@0 185 var tests = [
michael@0 186 { // Test #0
michael@0 187 run: function () {
michael@0 188 this.notifyObj = new basicNotification();
michael@0 189 showNotification(this.notifyObj);
michael@0 190 },
michael@0 191 onShown: function (popup) {
michael@0 192 checkPopup(popup, this.notifyObj);
michael@0 193 triggerMainCommand(popup);
michael@0 194 },
michael@0 195 onHidden: function (popup) {
michael@0 196 ok(this.notifyObj.mainActionClicked, "mainAction was clicked");
michael@0 197 ok(!this.notifyObj.dismissalCallbackTriggered, "dismissal callback wasn't triggered");
michael@0 198 ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
michael@0 199 }
michael@0 200 },
michael@0 201 { // Test #1
michael@0 202 run: function () {
michael@0 203 this.notifyObj = new basicNotification();
michael@0 204 showNotification(this.notifyObj);
michael@0 205 },
michael@0 206 onShown: function (popup) {
michael@0 207 checkPopup(popup, this.notifyObj);
michael@0 208 triggerSecondaryCommand(popup, 0);
michael@0 209 },
michael@0 210 onHidden: function (popup) {
michael@0 211 ok(this.notifyObj.secondaryActionClicked, "secondaryAction was clicked");
michael@0 212 ok(!this.notifyObj.dismissalCallbackTriggered, "dismissal callback wasn't triggered");
michael@0 213 ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
michael@0 214 }
michael@0 215 },
michael@0 216 { // Test #2
michael@0 217 run: function () {
michael@0 218 this.notifyObj = new basicNotification();
michael@0 219 this.notification = showNotification(this.notifyObj);
michael@0 220 },
michael@0 221 onShown: function (popup) {
michael@0 222 checkPopup(popup, this.notifyObj);
michael@0 223 dismissNotification(popup);
michael@0 224 },
michael@0 225 onHidden: function (popup) {
michael@0 226 ok(this.notifyObj.dismissalCallbackTriggered, "dismissal callback triggered");
michael@0 227 this.notification.remove();
michael@0 228 ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
michael@0 229 }
michael@0 230 },
michael@0 231 // test opening a notification for a background browser
michael@0 232 { // Test #3
michael@0 233 run: function () {
michael@0 234 gNewTab = gBrowser.addTab("about:blank");
michael@0 235 isnot(gBrowser.selectedTab, gNewTab, "new tab isn't selected");
michael@0 236 wrongBrowserNotificationObject.browser = gBrowser.getBrowserForTab(gNewTab);
michael@0 237 wrongBrowserNotification = showNotification(wrongBrowserNotificationObject);
michael@0 238 },
michael@0 239 backgroundShow: function () {
michael@0 240 is(PopupNotifications.isPanelOpen, false, "panel isn't open");
michael@0 241 ok(!wrongBrowserNotificationObject.mainActionClicked, "main action wasn't clicked");
michael@0 242 ok(!wrongBrowserNotificationObject.secondaryActionClicked, "secondary action wasn't clicked");
michael@0 243 ok(!wrongBrowserNotificationObject.dismissalCallbackTriggered, "dismissal callback wasn't called");
michael@0 244 }
michael@0 245 },
michael@0 246 // now select that browser and test to see that the notification appeared
michael@0 247 { // Test #4
michael@0 248 run: function () {
michael@0 249 this.oldSelectedTab = gBrowser.selectedTab;
michael@0 250 gBrowser.selectedTab = gNewTab;
michael@0 251 },
michael@0 252 onShown: function (popup) {
michael@0 253 checkPopup(popup, wrongBrowserNotificationObject);
michael@0 254 is(PopupNotifications.isPanelOpen, true, "isPanelOpen getter doesn't lie");
michael@0 255
michael@0 256 // switch back to the old browser
michael@0 257 gBrowser.selectedTab = this.oldSelectedTab;
michael@0 258 },
michael@0 259 onHidden: function (popup) {
michael@0 260 // actually remove the notification to prevent it from reappearing
michael@0 261 ok(wrongBrowserNotificationObject.dismissalCallbackTriggered, "dismissal callback triggered due to tab switch");
michael@0 262 wrongBrowserNotification.remove();
michael@0 263 ok(wrongBrowserNotificationObject.removedCallbackTriggered, "removed callback triggered");
michael@0 264 wrongBrowserNotification = null;
michael@0 265 }
michael@0 266 },
michael@0 267 // test that the removed notification isn't shown on browser re-select
michael@0 268 { // Test #5
michael@0 269 run: function () {
michael@0 270 gBrowser.selectedTab = gNewTab;
michael@0 271 },
michael@0 272 updateNotShowing: function () {
michael@0 273 is(PopupNotifications.isPanelOpen, false, "panel isn't open");
michael@0 274 gBrowser.removeTab(gNewTab);
michael@0 275 }
michael@0 276 },
michael@0 277 // Test that two notifications with the same ID result in a single displayed
michael@0 278 // notification.
michael@0 279 { // Test #6
michael@0 280 run: function () {
michael@0 281 this.notifyObj = new basicNotification();
michael@0 282 // Show the same notification twice
michael@0 283 this.notification1 = showNotification(this.notifyObj);
michael@0 284 this.notification2 = showNotification(this.notifyObj);
michael@0 285 },
michael@0 286 onShown: function (popup) {
michael@0 287 checkPopup(popup, this.notifyObj);
michael@0 288 this.notification2.remove();
michael@0 289 },
michael@0 290 onHidden: function (popup) {
michael@0 291 ok(!this.notifyObj.dismissalCallbackTriggered, "dismissal callback wasn't triggered");
michael@0 292 ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
michael@0 293 }
michael@0 294 },
michael@0 295 // Test that two notifications with different IDs are displayed
michael@0 296 { // Test #7
michael@0 297 run: function () {
michael@0 298 this.testNotif1 = new basicNotification();
michael@0 299 this.testNotif1.message += " 1";
michael@0 300 showNotification(this.testNotif1);
michael@0 301 this.testNotif2 = new basicNotification();
michael@0 302 this.testNotif2.message += " 2";
michael@0 303 this.testNotif2.id += "-2";
michael@0 304 showNotification(this.testNotif2);
michael@0 305 },
michael@0 306 onShown: function (popup) {
michael@0 307 is(popup.childNodes.length, 2, "two notifications are shown");
michael@0 308 // Trigger the main command for the first notification, and the secondary
michael@0 309 // for the second. Need to do mainCommand first since the secondaryCommand
michael@0 310 // triggering is async.
michael@0 311 triggerMainCommand(popup);
michael@0 312 is(popup.childNodes.length, 1, "only one notification left");
michael@0 313 triggerSecondaryCommand(popup, 0);
michael@0 314 },
michael@0 315 onHidden: function (popup) {
michael@0 316 ok(this.testNotif1.mainActionClicked, "main action #1 was clicked");
michael@0 317 ok(!this.testNotif1.secondaryActionClicked, "secondary action #1 wasn't clicked");
michael@0 318 ok(!this.testNotif1.dismissalCallbackTriggered, "dismissal callback #1 wasn't called");
michael@0 319
michael@0 320 ok(!this.testNotif2.mainActionClicked, "main action #2 wasn't clicked");
michael@0 321 ok(this.testNotif2.secondaryActionClicked, "secondary action #2 was clicked");
michael@0 322 ok(!this.testNotif2.dismissalCallbackTriggered, "dismissal callback #2 wasn't called");
michael@0 323 }
michael@0 324 },
michael@0 325 // Test notification without mainAction
michael@0 326 { // Test #8
michael@0 327 run: function () {
michael@0 328 this.notifyObj = new basicNotification();
michael@0 329 this.notifyObj.mainAction = null;
michael@0 330 this.notification = showNotification(this.notifyObj);
michael@0 331 },
michael@0 332 onShown: function (popup) {
michael@0 333 checkPopup(popup, this.notifyObj);
michael@0 334 dismissNotification(popup);
michael@0 335 },
michael@0 336 onHidden: function (popup) {
michael@0 337 this.notification.remove();
michael@0 338 }
michael@0 339 },
michael@0 340 // Test two notifications with different anchors
michael@0 341 { // Test #9
michael@0 342 run: function () {
michael@0 343 this.notifyObj = new basicNotification();
michael@0 344 this.firstNotification = showNotification(this.notifyObj);
michael@0 345 this.notifyObj2 = new basicNotification();
michael@0 346 this.notifyObj2.id += "-2";
michael@0 347 this.notifyObj2.anchorID = "addons-notification-icon";
michael@0 348 // Second showNotification() overrides the first
michael@0 349 this.secondNotification = showNotification(this.notifyObj2);
michael@0 350 },
michael@0 351 onShown: function (popup) {
michael@0 352 // This also checks that only one element is shown.
michael@0 353 checkPopup(popup, this.notifyObj2);
michael@0 354 is(document.getElementById("geo-notification-icon").boxObject.width, 0,
michael@0 355 "geo anchor shouldn't be visible");
michael@0 356 dismissNotification(popup);
michael@0 357 },
michael@0 358 onHidden: [
michael@0 359 // The second showing triggers a popuphidden event that we should ignore.
michael@0 360 function (popup) {},
michael@0 361 function (popup) {
michael@0 362 // Remove the notifications
michael@0 363 this.firstNotification.remove();
michael@0 364 this.secondNotification.remove();
michael@0 365 ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
michael@0 366 ok(this.notifyObj2.removedCallbackTriggered, "removed callback triggered");
michael@0 367 }
michael@0 368 ]
michael@0 369 },
michael@0 370 // Test optional params
michael@0 371 { // Test #10
michael@0 372 run: function () {
michael@0 373 this.notifyObj = new basicNotification();
michael@0 374 this.notifyObj.secondaryActions = undefined;
michael@0 375 this.notification = showNotification(this.notifyObj);
michael@0 376 },
michael@0 377 onShown: function (popup) {
michael@0 378 checkPopup(popup, this.notifyObj);
michael@0 379 dismissNotification(popup);
michael@0 380 },
michael@0 381 onHidden: function (popup) {
michael@0 382 ok(this.notifyObj.dismissalCallbackTriggered, "dismissal callback triggered");
michael@0 383 this.notification.remove();
michael@0 384 ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
michael@0 385 }
michael@0 386 },
michael@0 387 // Test that icons appear
michael@0 388 { // Test #11
michael@0 389 run: function () {
michael@0 390 this.notifyObj = new basicNotification();
michael@0 391 this.notifyObj.id = "geolocation";
michael@0 392 this.notifyObj.anchorID = "geo-notification-icon";
michael@0 393 this.notification = showNotification(this.notifyObj);
michael@0 394 },
michael@0 395 onShown: function (popup) {
michael@0 396 checkPopup(popup, this.notifyObj);
michael@0 397 isnot(document.getElementById("geo-notification-icon").boxObject.width, 0,
michael@0 398 "geo anchor should be visible");
michael@0 399 dismissNotification(popup);
michael@0 400 },
michael@0 401 onHidden: function (popup) {
michael@0 402 let icon = document.getElementById("geo-notification-icon");
michael@0 403 isnot(icon.boxObject.width, 0,
michael@0 404 "geo anchor should be visible after dismissal");
michael@0 405 this.notification.remove();
michael@0 406 is(icon.boxObject.width, 0,
michael@0 407 "geo anchor should not be visible after removal");
michael@0 408 }
michael@0 409 },
michael@0 410 // Test that persistence allows the notification to persist across reloads
michael@0 411 { // Test #12
michael@0 412 run: function () {
michael@0 413 this.oldSelectedTab = gBrowser.selectedTab;
michael@0 414 gBrowser.selectedTab = gBrowser.addTab("about:blank");
michael@0 415
michael@0 416 let self = this;
michael@0 417 loadURI("http://example.com/", function() {
michael@0 418 self.notifyObj = new basicNotification();
michael@0 419 self.notifyObj.addOptions({
michael@0 420 persistence: 2
michael@0 421 });
michael@0 422 self.notification = showNotification(self.notifyObj);
michael@0 423 });
michael@0 424 },
michael@0 425 onShown: function (popup) {
michael@0 426 this.complete = false;
michael@0 427
michael@0 428 let self = this;
michael@0 429 loadURI("http://example.org/", function() {
michael@0 430 loadURI("http://example.com/", function() {
michael@0 431
michael@0 432 // Next load will remove the notification
michael@0 433 self.complete = true;
michael@0 434
michael@0 435 loadURI("http://example.org/");
michael@0 436 });
michael@0 437 });
michael@0 438 },
michael@0 439 onHidden: function (popup) {
michael@0 440 ok(this.complete, "Should only have hidden the notification after 3 page loads");
michael@0 441 ok(this.notifyObj.removedCallbackTriggered, "removal callback triggered");
michael@0 442 gBrowser.removeTab(gBrowser.selectedTab);
michael@0 443 gBrowser.selectedTab = this.oldSelectedTab;
michael@0 444 }
michael@0 445 },
michael@0 446 // Test that a timeout allows the notification to persist across reloads
michael@0 447 { // Test #13
michael@0 448 run: function () {
michael@0 449 this.oldSelectedTab = gBrowser.selectedTab;
michael@0 450 gBrowser.selectedTab = gBrowser.addTab("about:blank");
michael@0 451
michael@0 452 let self = this;
michael@0 453 loadURI("http://example.com/", function() {
michael@0 454 self.notifyObj = new basicNotification();
michael@0 455 // Set a timeout of 10 minutes that should never be hit
michael@0 456 self.notifyObj.addOptions({
michael@0 457 timeout: Date.now() + 600000
michael@0 458 });
michael@0 459 self.notification = showNotification(self.notifyObj);
michael@0 460 });
michael@0 461 },
michael@0 462 onShown: function (popup) {
michael@0 463 this.complete = false;
michael@0 464
michael@0 465 let self = this;
michael@0 466 loadURI("http://example.org/", function() {
michael@0 467 loadURI("http://example.com/", function() {
michael@0 468
michael@0 469 // Next load will hide the notification
michael@0 470 self.notification.options.timeout = Date.now() - 1;
michael@0 471 self.complete = true;
michael@0 472
michael@0 473 loadURI("http://example.org/");
michael@0 474 });
michael@0 475 });
michael@0 476 },
michael@0 477 onHidden: function (popup) {
michael@0 478 ok(this.complete, "Should only have hidden the notification after the timeout was passed");
michael@0 479 this.notification.remove();
michael@0 480 gBrowser.removeTab(gBrowser.selectedTab);
michael@0 481 gBrowser.selectedTab = this.oldSelectedTab;
michael@0 482 }
michael@0 483 },
michael@0 484 // Test that setting persistWhileVisible allows a visible notification to
michael@0 485 // persist across location changes
michael@0 486 { // Test #14
michael@0 487 run: function () {
michael@0 488 this.oldSelectedTab = gBrowser.selectedTab;
michael@0 489 gBrowser.selectedTab = gBrowser.addTab("about:blank");
michael@0 490
michael@0 491 let self = this;
michael@0 492 loadURI("http://example.com/", function() {
michael@0 493 self.notifyObj = new basicNotification();
michael@0 494 self.notifyObj.addOptions({
michael@0 495 persistWhileVisible: true
michael@0 496 });
michael@0 497 self.notification = showNotification(self.notifyObj);
michael@0 498 });
michael@0 499 },
michael@0 500 onShown: function (popup) {
michael@0 501 this.complete = false;
michael@0 502
michael@0 503 let self = this;
michael@0 504 loadURI("http://example.org/", function() {
michael@0 505 loadURI("http://example.com/", function() {
michael@0 506
michael@0 507 // Notification should persist across location changes
michael@0 508 self.complete = true;
michael@0 509 dismissNotification(popup);
michael@0 510 });
michael@0 511 });
michael@0 512 },
michael@0 513 onHidden: function (popup) {
michael@0 514 ok(this.complete, "Should only have hidden the notification after it was dismissed");
michael@0 515 this.notification.remove();
michael@0 516 gBrowser.removeTab(gBrowser.selectedTab);
michael@0 517 gBrowser.selectedTab = this.oldSelectedTab;
michael@0 518 }
michael@0 519 },
michael@0 520 // Test that nested icon nodes correctly activate popups
michael@0 521 { // Test #15
michael@0 522 run: function() {
michael@0 523 // Add a temporary box as the anchor with a button
michael@0 524 this.box = document.createElement("box");
michael@0 525 PopupNotifications.iconBox.appendChild(this.box);
michael@0 526
michael@0 527 let button = document.createElement("button");
michael@0 528 button.setAttribute("label", "Please click me!");
michael@0 529 this.box.appendChild(button);
michael@0 530
michael@0 531 // The notification should open up on the box
michael@0 532 this.notifyObj = new basicNotification();
michael@0 533 this.notifyObj.anchorID = this.box.id = "nested-box";
michael@0 534 this.notifyObj.addOptions({dismissed: true});
michael@0 535 this.notification = showNotification(this.notifyObj);
michael@0 536
michael@0 537 // This test places a normal button in the notification area, which has
michael@0 538 // standard GTK styling and dimensions. Due to the clip-path, this button
michael@0 539 // gets clipped off, which makes it necessary to synthesize the mouse click
michael@0 540 // a little bit downward. To be safe, I adjusted the x-offset with the same
michael@0 541 // amount.
michael@0 542 EventUtils.synthesizeMouse(button, 4, 4, {});
michael@0 543 },
michael@0 544 onShown: function(popup) {
michael@0 545 checkPopup(popup, this.notifyObj);
michael@0 546 dismissNotification(popup);
michael@0 547 },
michael@0 548 onHidden: function(popup) {
michael@0 549 this.notification.remove();
michael@0 550 this.box.parentNode.removeChild(this.box);
michael@0 551 }
michael@0 552 },
michael@0 553 // Test that popupnotifications without popups have anchor icons shown
michael@0 554 { // Test #16
michael@0 555 run: function() {
michael@0 556 let notifyObj = new basicNotification();
michael@0 557 notifyObj.anchorID = "geo-notification-icon";
michael@0 558 notifyObj.addOptions({neverShow: true});
michael@0 559 showNotification(notifyObj);
michael@0 560 },
michael@0 561 updateNotShowing: function() {
michael@0 562 isnot(document.getElementById("geo-notification-icon").boxObject.width, 0,
michael@0 563 "geo anchor should be visible");
michael@0 564 }
michael@0 565 },
michael@0 566 // Test notification "Not Now" menu item
michael@0 567 { // Test #17
michael@0 568 run: function () {
michael@0 569 this.notifyObj = new basicNotification();
michael@0 570 this.notification = showNotification(this.notifyObj);
michael@0 571 },
michael@0 572 onShown: function (popup) {
michael@0 573 checkPopup(popup, this.notifyObj);
michael@0 574 triggerSecondaryCommand(popup, 1);
michael@0 575 },
michael@0 576 onHidden: function (popup) {
michael@0 577 ok(this.notifyObj.dismissalCallbackTriggered, "dismissal callback triggered");
michael@0 578 this.notification.remove();
michael@0 579 ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
michael@0 580 }
michael@0 581 },
michael@0 582 // Test notification close button
michael@0 583 { // Test #18
michael@0 584 run: function () {
michael@0 585 this.notifyObj = new basicNotification();
michael@0 586 this.notification = showNotification(this.notifyObj);
michael@0 587 },
michael@0 588 onShown: function (popup) {
michael@0 589 checkPopup(popup, this.notifyObj);
michael@0 590 let notification = popup.childNodes[0];
michael@0 591 EventUtils.synthesizeMouseAtCenter(notification.closebutton, {});
michael@0 592 },
michael@0 593 onHidden: function (popup) {
michael@0 594 ok(this.notifyObj.dismissalCallbackTriggered, "dismissal callback triggered");
michael@0 595 this.notification.remove();
michael@0 596 ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
michael@0 597 }
michael@0 598 },
michael@0 599 // Test notification when chrome is hidden
michael@0 600 { // Test #19
michael@0 601 run: function () {
michael@0 602 window.locationbar.visible = false;
michael@0 603 this.notifyObj = new basicNotification();
michael@0 604 this.notification = showNotification(this.notifyObj);
michael@0 605 window.locationbar.visible = true;
michael@0 606 },
michael@0 607 onShown: function (popup) {
michael@0 608 checkPopup(popup, this.notifyObj);
michael@0 609 is(popup.anchorNode.className, "tabbrowser-tab", "notification anchored to tab");
michael@0 610 dismissNotification(popup);
michael@0 611 },
michael@0 612 onHidden: function (popup) {
michael@0 613 ok(this.notifyObj.dismissalCallbackTriggered, "dismissal callback triggered");
michael@0 614 this.notification.remove();
michael@0 615 ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
michael@0 616 }
michael@0 617 },
michael@0 618 // Test notification is removed when dismissed if removeOnDismissal is true
michael@0 619 { // Test #20
michael@0 620 run: function () {
michael@0 621 this.notifyObj = new basicNotification();
michael@0 622 this.notifyObj.addOptions({
michael@0 623 removeOnDismissal: true
michael@0 624 });
michael@0 625 this.notification = showNotification(this.notifyObj);
michael@0 626 },
michael@0 627 onShown: function (popup) {
michael@0 628 checkPopup(popup, this.notifyObj);
michael@0 629 dismissNotification(popup);
michael@0 630 },
michael@0 631 onHidden: function (popup) {
michael@0 632 ok(!this.notifyObj.dismissalCallbackTriggered, "dismissal callback wasn't triggered");
michael@0 633 ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
michael@0 634 }
michael@0 635 },
michael@0 636 // Test multiple notification icons are shown
michael@0 637 { // Test #21
michael@0 638 run: function () {
michael@0 639 this.notifyObj1 = new basicNotification();
michael@0 640 this.notifyObj1.id += "_1";
michael@0 641 this.notifyObj1.anchorID = "default-notification-icon";
michael@0 642 this.notification1 = showNotification(this.notifyObj1);
michael@0 643
michael@0 644 this.notifyObj2 = new basicNotification();
michael@0 645 this.notifyObj2.id += "_2";
michael@0 646 this.notifyObj2.anchorID = "geo-notification-icon";
michael@0 647 this.notification2 = showNotification(this.notifyObj2);
michael@0 648 },
michael@0 649 onShown: function (popup) {
michael@0 650 checkPopup(popup, this.notifyObj2);
michael@0 651
michael@0 652 // check notifyObj1 anchor icon is showing
michael@0 653 isnot(document.getElementById("default-notification-icon").boxObject.width, 0,
michael@0 654 "default anchor should be visible");
michael@0 655 // check notifyObj2 anchor icon is showing
michael@0 656 isnot(document.getElementById("geo-notification-icon").boxObject.width, 0,
michael@0 657 "geo anchor should be visible");
michael@0 658
michael@0 659 dismissNotification(popup);
michael@0 660 },
michael@0 661 onHidden: [
michael@0 662 function (popup) {
michael@0 663 },
michael@0 664 function (popup) {
michael@0 665 this.notification1.remove();
michael@0 666 ok(this.notifyObj1.removedCallbackTriggered, "removed callback triggered");
michael@0 667
michael@0 668 this.notification2.remove();
michael@0 669 ok(this.notifyObj2.removedCallbackTriggered, "removed callback triggered");
michael@0 670 }
michael@0 671 ]
michael@0 672 },
michael@0 673 // Test that multiple notification icons are removed when switching tabs
michael@0 674 { // Test #22
michael@0 675 run: function () {
michael@0 676 // show the notification on old tab.
michael@0 677 this.notifyObjOld = new basicNotification();
michael@0 678 this.notifyObjOld.anchorID = "default-notification-icon";
michael@0 679 this.notificationOld = showNotification(this.notifyObjOld);
michael@0 680
michael@0 681 // switch tab
michael@0 682 this.oldSelectedTab = gBrowser.selectedTab;
michael@0 683 gBrowser.selectedTab = gBrowser.addTab("about:blank");
michael@0 684
michael@0 685 // show the notification on new tab.
michael@0 686 this.notifyObjNew = new basicNotification();
michael@0 687 this.notifyObjNew.anchorID = "geo-notification-icon";
michael@0 688 this.notificationNew = showNotification(this.notifyObjNew);
michael@0 689 },
michael@0 690 onShown: function (popup) {
michael@0 691 checkPopup(popup, this.notifyObjNew);
michael@0 692
michael@0 693 // check notifyObjOld anchor icon is removed
michael@0 694 is(document.getElementById("default-notification-icon").boxObject.width, 0,
michael@0 695 "default anchor shouldn't be visible");
michael@0 696 // check notifyObjNew anchor icon is showing
michael@0 697 isnot(document.getElementById("geo-notification-icon").boxObject.width, 0,
michael@0 698 "geo anchor should be visible");
michael@0 699
michael@0 700 dismissNotification(popup);
michael@0 701 },
michael@0 702 onHidden: [
michael@0 703 function (popup) {
michael@0 704 },
michael@0 705 function (popup) {
michael@0 706 this.notificationNew.remove();
michael@0 707 gBrowser.removeTab(gBrowser.selectedTab);
michael@0 708
michael@0 709 gBrowser.selectedTab = this.oldSelectedTab;
michael@0 710 this.notificationOld.remove();
michael@0 711 }
michael@0 712 ]
michael@0 713 },
michael@0 714 { // Test #23 - test security delay - too early
michael@0 715 run: function () {
michael@0 716 // Set the security delay to 100s
michael@0 717 PopupNotifications.buttonDelay = 100000;
michael@0 718
michael@0 719 this.notifyObj = new basicNotification();
michael@0 720 showNotification(this.notifyObj);
michael@0 721 },
michael@0 722 onShown: function (popup) {
michael@0 723 checkPopup(popup, this.notifyObj);
michael@0 724 triggerMainCommand(popup);
michael@0 725
michael@0 726 // Wait to see if the main command worked
michael@0 727 executeSoon(function delayedDismissal() {
michael@0 728 dismissNotification(popup);
michael@0 729 });
michael@0 730
michael@0 731 },
michael@0 732 onHidden: function (popup) {
michael@0 733 ok(!this.notifyObj.mainActionClicked, "mainAction was not clicked because it was too soon");
michael@0 734 ok(this.notifyObj.dismissalCallbackTriggered, "dismissal callback was triggered");
michael@0 735 }
michael@0 736 },
michael@0 737 { // Test #24 - test security delay - after delay
michael@0 738 run: function () {
michael@0 739 // Set the security delay to 10ms
michael@0 740 PopupNotifications.buttonDelay = 10;
michael@0 741
michael@0 742 this.notifyObj = new basicNotification();
michael@0 743 showNotification(this.notifyObj);
michael@0 744 },
michael@0 745 onShown: function (popup) {
michael@0 746 checkPopup(popup, this.notifyObj);
michael@0 747
michael@0 748 // Wait until after the delay to trigger the main action
michael@0 749 setTimeout(function delayedDismissal() {
michael@0 750 triggerMainCommand(popup);
michael@0 751 }, 500);
michael@0 752
michael@0 753 },
michael@0 754 onHidden: function (popup) {
michael@0 755 ok(this.notifyObj.mainActionClicked, "mainAction was clicked after the delay");
michael@0 756 ok(!this.notifyObj.dismissalCallbackTriggered, "dismissal callback was not triggered");
michael@0 757 PopupNotifications.buttonDelay = PREF_SECURITY_DELAY_INITIAL;
michael@0 758 }
michael@0 759 },
michael@0 760 { // Test #25 - reload removes notification
michael@0 761 run: function () {
michael@0 762 loadURI("http://example.com/", function() {
michael@0 763 let notifyObj = new basicNotification();
michael@0 764 notifyObj.options.eventCallback = function (eventName) {
michael@0 765 if (eventName == "removed") {
michael@0 766 ok(true, "Notification removed in background tab after reloading");
michael@0 767 executeSoon(function () {
michael@0 768 goNext();
michael@0 769 });
michael@0 770 }
michael@0 771 };
michael@0 772 showNotification(notifyObj);
michael@0 773 executeSoon(function () {
michael@0 774 gBrowser.selectedBrowser.reload();
michael@0 775 });
michael@0 776 });
michael@0 777 }
michael@0 778 },
michael@0 779 { // Test #26 - location change in background tab removes notification
michael@0 780 run: function () {
michael@0 781 let oldSelectedTab = gBrowser.selectedTab;
michael@0 782 let newTab = gBrowser.addTab("about:blank");
michael@0 783 gBrowser.selectedTab = newTab;
michael@0 784
michael@0 785 loadURI("http://example.com/", function() {
michael@0 786 gBrowser.selectedTab = oldSelectedTab;
michael@0 787 let browser = gBrowser.getBrowserForTab(newTab);
michael@0 788
michael@0 789 let notifyObj = new basicNotification();
michael@0 790 notifyObj.browser = browser;
michael@0 791 notifyObj.options.eventCallback = function (eventName) {
michael@0 792 if (eventName == "removed") {
michael@0 793 ok(true, "Notification removed in background tab after reloading");
michael@0 794 executeSoon(function () {
michael@0 795 gBrowser.removeTab(newTab);
michael@0 796 goNext();
michael@0 797 });
michael@0 798 }
michael@0 799 };
michael@0 800 showNotification(notifyObj);
michael@0 801 executeSoon(function () {
michael@0 802 browser.reload();
michael@0 803 });
michael@0 804 });
michael@0 805 }
michael@0 806 },
michael@0 807 { // Test #27 - Popup notification anchor shouldn't disappear when a notification with the same ID is re-added in a background tab
michael@0 808 run: function () {
michael@0 809 loadURI("http://example.com/", function () {
michael@0 810 let originalTab = gBrowser.selectedTab;
michael@0 811 let bgTab = gBrowser.addTab("about:blank");
michael@0 812 gBrowser.selectedTab = bgTab;
michael@0 813 loadURI("http://example.com/", function () {
michael@0 814 let anchor = document.createElement("box");
michael@0 815 anchor.id = "test26-anchor";
michael@0 816 anchor.className = "notification-anchor-icon";
michael@0 817 PopupNotifications.iconBox.appendChild(anchor);
michael@0 818
michael@0 819 gBrowser.selectedTab = originalTab;
michael@0 820
michael@0 821 let fgNotifyObj = new basicNotification();
michael@0 822 fgNotifyObj.anchorID = anchor.id;
michael@0 823 fgNotifyObj.options.dismissed = true;
michael@0 824 let fgNotification = showNotification(fgNotifyObj);
michael@0 825
michael@0 826 let bgNotifyObj = new basicNotification();
michael@0 827 bgNotifyObj.anchorID = anchor.id;
michael@0 828 bgNotifyObj.browser = gBrowser.getBrowserForTab(bgTab);
michael@0 829 // show the notification in the background tab ...
michael@0 830 let bgNotification = showNotification(bgNotifyObj);
michael@0 831 // ... and re-show it
michael@0 832 bgNotification = showNotification(bgNotifyObj);
michael@0 833
michael@0 834 ok(fgNotification.id, "notification has id");
michael@0 835 is(fgNotification.id, bgNotification.id, "notification ids are the same");
michael@0 836 is(anchor.getAttribute("showing"), "true", "anchor still showing");
michael@0 837
michael@0 838 fgNotification.remove();
michael@0 839 gBrowser.removeTab(bgTab);
michael@0 840 goNext();
michael@0 841 });
michael@0 842 });
michael@0 843 }
michael@0 844 },
michael@0 845 { // Test #28 - location change in an embedded frame should not remove a notification
michael@0 846 run: function () {
michael@0 847 loadURI("data:text/html;charset=utf8,<iframe id='iframe' src='http://example.com/'>", function () {
michael@0 848 this.notifyObj = new basicNotification();
michael@0 849 this.notifyObj.options.eventCallback = function (eventName) {
michael@0 850 if (eventName == "removed") {
michael@0 851 ok(false, "Test 28: Notification removed from browser when subframe navigated");
michael@0 852 }
michael@0 853 };
michael@0 854 showNotification(this.notifyObj);
michael@0 855 }.bind(this));
michael@0 856 },
michael@0 857 onShown: function (popup) {
michael@0 858 let self = this;
michael@0 859 let progressListener = {
michael@0 860 onLocationChange: function onLocationChange(aBrowser) {
michael@0 861 if (aBrowser != gBrowser.selectedBrowser) {
michael@0 862 return;
michael@0 863 }
michael@0 864 let notification = PopupNotifications.getNotification(self.notifyObj.id,
michael@0 865 self.notifyObj.browser);
michael@0 866 ok(notification != null, "Test 28: Notification remained when subframe navigated");
michael@0 867 self.notifyObj.options.eventCallback = undefined;
michael@0 868
michael@0 869 notification.remove();
michael@0 870 gBrowser.removeTabsProgressListener(progressListener);
michael@0 871 },
michael@0 872 };
michael@0 873
michael@0 874 info("Test 28: Adding progress listener and performing navigation");
michael@0 875 gBrowser.addTabsProgressListener(progressListener);
michael@0 876 content.document.getElementById("iframe")
michael@0 877 .setAttribute("src", "http://example.org/");
michael@0 878 },
michael@0 879 onHidden: function () {}
michael@0 880 },
michael@0 881 { // Test #29 - Popup Notifications should catch exceptions from callbacks
michael@0 882 run: function () {
michael@0 883 let callbackCount = 0;
michael@0 884 this.testNotif1 = new basicNotification();
michael@0 885 this.testNotif1.message += " 1";
michael@0 886 this.notification1 = showNotification(this.testNotif1);
michael@0 887 this.testNotif1.options.eventCallback = function (eventName) {
michael@0 888 info("notifyObj1.options.eventCallback: " + eventName);
michael@0 889 if (eventName == "dismissed") {
michael@0 890 throw new Error("Oops 1!");
michael@0 891 if (++callbackCount == 2) {
michael@0 892 executeSoon(goNext);
michael@0 893 }
michael@0 894 }
michael@0 895 };
michael@0 896
michael@0 897 this.testNotif2 = new basicNotification();
michael@0 898 this.testNotif2.message += " 2";
michael@0 899 this.testNotif2.id += "-2";
michael@0 900 this.testNotif2.options.eventCallback = function (eventName) {
michael@0 901 info("notifyObj2.options.eventCallback: " + eventName);
michael@0 902 if (eventName == "dismissed") {
michael@0 903 throw new Error("Oops 2!");
michael@0 904 if (++callbackCount == 2) {
michael@0 905 executeSoon(goNext);
michael@0 906 }
michael@0 907 }
michael@0 908 };
michael@0 909 this.notification2 = showNotification(this.testNotif2);
michael@0 910 },
michael@0 911 onShown: function (popup) {
michael@0 912 is(popup.childNodes.length, 2, "two notifications are shown");
michael@0 913 dismissNotification(popup);
michael@0 914 },
michael@0 915 onHidden: function () {
michael@0 916 this.notification1.remove();
michael@0 917 this.notification2.remove();
michael@0 918 }
michael@0 919 },
michael@0 920 { // Test #30 - Popup Notifications main actions should catch exceptions from callbacks
michael@0 921 run: function () {
michael@0 922 this.testNotif = new errorNotification();
michael@0 923 showNotification(this.testNotif);
michael@0 924 },
michael@0 925 onShown: function (popup) {
michael@0 926 checkPopup(popup, this.testNotif);
michael@0 927 triggerMainCommand(popup);
michael@0 928 },
michael@0 929 onHidden: function (popup) {
michael@0 930 ok(this.testNotif.mainActionClicked, "main action has been triggered");
michael@0 931 }
michael@0 932 },
michael@0 933 { // Test #31 - Popup Notifications secondary actions should catch exceptions from callbacks
michael@0 934 run: function () {
michael@0 935 this.testNotif = new errorNotification();
michael@0 936 showNotification(this.testNotif);
michael@0 937 },
michael@0 938 onShown: function (popup) {
michael@0 939 checkPopup(popup, this.testNotif);
michael@0 940 triggerSecondaryCommand(popup, 0);
michael@0 941 },
michael@0 942 onHidden: function (popup) {
michael@0 943 ok(this.testNotif.secondaryActionClicked, "secondary action has been triggered");
michael@0 944 }
michael@0 945 },
michael@0 946 { // Test #32 - Existing popup notification shouldn't disappear when adding a dismissed notification
michael@0 947 run: function () {
michael@0 948 this.notifyObj1 = new basicNotification();
michael@0 949 this.notifyObj1.id += "_1";
michael@0 950 this.notifyObj1.anchorID = "default-notification-icon";
michael@0 951 this.notification1 = showNotification(this.notifyObj1);
michael@0 952 },
michael@0 953 onShown: function (popup) {
michael@0 954 // Now show a dismissed notification, and check that it doesn't clobber
michael@0 955 // the showing one.
michael@0 956 this.notifyObj2 = new basicNotification();
michael@0 957 this.notifyObj2.id += "_2";
michael@0 958 this.notifyObj2.anchorID = "geo-notification-icon";
michael@0 959 this.notifyObj2.options.dismissed = true;
michael@0 960 this.notification2 = showNotification(this.notifyObj2);
michael@0 961
michael@0 962 checkPopup(popup, this.notifyObj1);
michael@0 963
michael@0 964 // check that both anchor icons are showing
michael@0 965 is(document.getElementById("default-notification-icon").getAttribute("showing"), "true",
michael@0 966 "notification1 anchor should be visible");
michael@0 967 is(document.getElementById("geo-notification-icon").getAttribute("showing"), "true",
michael@0 968 "notification2 anchor should be visible");
michael@0 969
michael@0 970 dismissNotification(popup);
michael@0 971 },
michael@0 972 onHidden: function(popup) {
michael@0 973 this.notification1.remove();
michael@0 974 this.notification2.remove();
michael@0 975 }
michael@0 976 },
michael@0 977 { // Test #33 - Showing should be able to modify the popup data
michael@0 978 run: function() {
michael@0 979 this.notifyObj = new basicNotification();
michael@0 980 var normalCallback = this.notifyObj.options.eventCallback;
michael@0 981 this.notifyObj.options.eventCallback = function (eventName) {
michael@0 982 if (eventName == "showing") {
michael@0 983 this.mainAction.label = "Alternate Label";
michael@0 984 }
michael@0 985 normalCallback.call(this, eventName);
michael@0 986 };
michael@0 987 showNotification(this.notifyObj);
michael@0 988 },
michael@0 989 onShown: function(popup) {
michael@0 990 // checkPopup checks for the matching label. Note that this assumes that
michael@0 991 // this.notifyObj.mainAction is the same as notification.mainAction,
michael@0 992 // which could be a problem if we ever decided to deep-copy.
michael@0 993 checkPopup(popup, this.notifyObj);
michael@0 994 triggerMainCommand(popup);
michael@0 995 },
michael@0 996 onHidden: function() { }
michael@0 997 },
michael@0 998 { // Test #34 - Moving a tab to a new window should remove non-swappable
michael@0 999 // notifications.
michael@0 1000 run: function() {
michael@0 1001 gBrowser.selectedTab = gBrowser.addTab("about:blank");
michael@0 1002 let notifyObj = new basicNotification();
michael@0 1003 showNotification(notifyObj);
michael@0 1004 let win = gBrowser.replaceTabWithWindow(gBrowser.selectedTab);
michael@0 1005 whenDelayedStartupFinished(win, function() {
michael@0 1006 let [tab] = win.gBrowser.tabs;
michael@0 1007 let anchor = win.document.getElementById("default-notification-icon");
michael@0 1008 win.PopupNotifications._reshowNotifications(anchor);
michael@0 1009 ok(win.PopupNotifications.panel.childNodes.length == 0,
michael@0 1010 "no notification displayed in new window");
michael@0 1011 ok(notifyObj.swappingCallbackTriggered, "the swapping callback was triggered");
michael@0 1012 ok(notifyObj.removedCallbackTriggered, "the removed callback was triggered");
michael@0 1013 win.close();
michael@0 1014 goNext();
michael@0 1015 });
michael@0 1016 }
michael@0 1017 },
michael@0 1018 { // Test #35 - Moving a tab to a new window should preserve swappable notifications.
michael@0 1019 run: function() {
michael@0 1020 gBrowser.selectedTab = gBrowser.addTab("about:blank");
michael@0 1021 let notifyObj = new basicNotification();
michael@0 1022 let originalCallback = notifyObj.options.eventCallback;
michael@0 1023 notifyObj.options.eventCallback = function (eventName) {
michael@0 1024 originalCallback(eventName);
michael@0 1025 return eventName == "swapping";
michael@0 1026 };
michael@0 1027
michael@0 1028 showNotification(notifyObj);
michael@0 1029 let win = gBrowser.replaceTabWithWindow(gBrowser.selectedTab);
michael@0 1030 whenDelayedStartupFinished(win, function() {
michael@0 1031 let [tab] = win.gBrowser.tabs;
michael@0 1032 let anchor = win.document.getElementById("default-notification-icon");
michael@0 1033 win.PopupNotifications._reshowNotifications(anchor);
michael@0 1034 checkPopup(win.PopupNotifications.panel, notifyObj);
michael@0 1035 ok(notifyObj.swappingCallbackTriggered, "the swapping callback was triggered");
michael@0 1036 win.close();
michael@0 1037 goNext();
michael@0 1038 });
michael@0 1039 }
michael@0 1040 },
michael@0 1041 { // Test #36 - the hideNotNow option
michael@0 1042 run: function () {
michael@0 1043 this.notifyObj = new basicNotification();
michael@0 1044 this.notifyObj.options.hideNotNow = true;
michael@0 1045 this.notifyObj.mainAction.dismiss = true;
michael@0 1046 this.notification = showNotification(this.notifyObj);
michael@0 1047 },
michael@0 1048 onShown: function (popup) {
michael@0 1049 // checkPopup verifies that the Not Now item is hidden, and that no separator is added.
michael@0 1050 checkPopup(popup, this.notifyObj);
michael@0 1051 triggerMainCommand(popup);
michael@0 1052 },
michael@0 1053 onHidden: function (popup) {
michael@0 1054 this.notification.remove();
michael@0 1055 }
michael@0 1056 },
michael@0 1057 { // Test #37 - the main action callback can keep the notification.
michael@0 1058 run: function () {
michael@0 1059 this.notifyObj = new basicNotification();
michael@0 1060 this.notifyObj.mainAction.dismiss = true;
michael@0 1061 this.notification = showNotification(this.notifyObj);
michael@0 1062 },
michael@0 1063 onShown: function (popup) {
michael@0 1064 checkPopup(popup, this.notifyObj);
michael@0 1065 triggerMainCommand(popup);
michael@0 1066 },
michael@0 1067 onHidden: function (popup) {
michael@0 1068 ok(this.notifyObj.dismissalCallbackTriggered, "dismissal callback was triggered");
michael@0 1069 ok(!this.notifyObj.removedCallbackTriggered, "removed callback wasn't triggered");
michael@0 1070 this.notification.remove();
michael@0 1071 }
michael@0 1072 },
michael@0 1073 { // Test #38 - a secondary action callback can keep the notification.
michael@0 1074 run: function () {
michael@0 1075 this.notifyObj = new basicNotification();
michael@0 1076 this.notifyObj.secondaryActions[0].dismiss = true;
michael@0 1077 this.notification = showNotification(this.notifyObj);
michael@0 1078 },
michael@0 1079 onShown: function (popup) {
michael@0 1080 checkPopup(popup, this.notifyObj);
michael@0 1081 triggerSecondaryCommand(popup, 0);
michael@0 1082 },
michael@0 1083 onHidden: function (popup) {
michael@0 1084 ok(this.notifyObj.dismissalCallbackTriggered, "dismissal callback was triggered");
michael@0 1085 ok(!this.notifyObj.removedCallbackTriggered, "removed callback wasn't triggered");
michael@0 1086 this.notification.remove();
michael@0 1087 }
michael@0 1088 },
michael@0 1089 { // Test #39 - returning true in the showing callback should dismiss the notification.
michael@0 1090 run: function() {
michael@0 1091 let notifyObj = new basicNotification();
michael@0 1092 let originalCallback = notifyObj.options.eventCallback;
michael@0 1093 notifyObj.options.eventCallback = function (eventName) {
michael@0 1094 originalCallback(eventName);
michael@0 1095 return eventName == "showing";
michael@0 1096 };
michael@0 1097
michael@0 1098 let notification = showNotification(notifyObj);
michael@0 1099 ok(notifyObj.showingCallbackTriggered, "the showing callback was triggered");
michael@0 1100 ok(!notifyObj.shownCallbackTriggered, "the shown callback wasn't triggered");
michael@0 1101 notification.remove();
michael@0 1102 goNext();
michael@0 1103 }
michael@0 1104 }
michael@0 1105 ];
michael@0 1106
michael@0 1107 function showNotification(notifyObj) {
michael@0 1108 return PopupNotifications.show(notifyObj.browser,
michael@0 1109 notifyObj.id,
michael@0 1110 notifyObj.message,
michael@0 1111 notifyObj.anchorID,
michael@0 1112 notifyObj.mainAction,
michael@0 1113 notifyObj.secondaryActions,
michael@0 1114 notifyObj.options);
michael@0 1115 }
michael@0 1116
michael@0 1117 function checkPopup(popup, notificationObj) {
michael@0 1118 info("[Test #" + gTestIndex + "] checking popup");
michael@0 1119
michael@0 1120 ok(notificationObj.showingCallbackTriggered, "showing callback was triggered");
michael@0 1121 ok(notificationObj.shownCallbackTriggered, "shown callback was triggered");
michael@0 1122
michael@0 1123 let notifications = popup.childNodes;
michael@0 1124 is(notifications.length, 1, "one notification displayed");
michael@0 1125 let notification = notifications[0];
michael@0 1126 if (!notification)
michael@0 1127 return;
michael@0 1128 let icon = document.getAnonymousElementByAttribute(notification, "class", "popup-notification-icon");
michael@0 1129 if (notificationObj.id == "geolocation") {
michael@0 1130 isnot(icon.boxObject.width, 0, "icon for geo displayed");
michael@0 1131 is(popup.anchorNode.className, "notification-anchor-icon", "notification anchored to icon");
michael@0 1132 }
michael@0 1133 is(notification.getAttribute("label"), notificationObj.message, "message matches");
michael@0 1134 is(notification.id, notificationObj.id + "-notification", "id matches");
michael@0 1135 if (notificationObj.mainAction) {
michael@0 1136 is(notification.getAttribute("buttonlabel"), notificationObj.mainAction.label, "main action label matches");
michael@0 1137 is(notification.getAttribute("buttonaccesskey"), notificationObj.mainAction.accessKey, "main action accesskey matches");
michael@0 1138 }
michael@0 1139 let actualSecondaryActions = Array.filter(notification.childNodes,
michael@0 1140 function (child) child.nodeName == "menuitem");
michael@0 1141 let secondaryActions = notificationObj.secondaryActions || [];
michael@0 1142 let actualSecondaryActionsCount = actualSecondaryActions.length;
michael@0 1143 if (notificationObj.options.hideNotNow) {
michael@0 1144 is(notification.getAttribute("hidenotnow"), "true", "Not Now item hidden");
michael@0 1145 if (secondaryActions.length)
michael@0 1146 is(notification.lastChild.tagName, "menuitem", "no menuseparator");
michael@0 1147 }
michael@0 1148 else if (secondaryActions.length) {
michael@0 1149 is(notification.lastChild.tagName, "menuseparator", "menuseparator exists");
michael@0 1150 }
michael@0 1151 is(actualSecondaryActionsCount, secondaryActions.length, actualSecondaryActions.length + " secondary actions");
michael@0 1152 secondaryActions.forEach(function (a, i) {
michael@0 1153 is(actualSecondaryActions[i].getAttribute("label"), a.label, "label for secondary action " + i + " matches");
michael@0 1154 is(actualSecondaryActions[i].getAttribute("accesskey"), a.accessKey, "accessKey for secondary action " + i + " matches");
michael@0 1155 });
michael@0 1156 }
michael@0 1157
michael@0 1158 function triggerMainCommand(popup) {
michael@0 1159 info("[Test #" + gTestIndex + "] triggering main command");
michael@0 1160 let notifications = popup.childNodes;
michael@0 1161 ok(notifications.length > 0, "at least one notification displayed");
michael@0 1162 let notification = notifications[0];
michael@0 1163
michael@0 1164 // 20, 10 so that the inner button is hit
michael@0 1165 EventUtils.synthesizeMouse(notification.button, 20, 10, {});
michael@0 1166 }
michael@0 1167
michael@0 1168 function triggerSecondaryCommand(popup, index) {
michael@0 1169 info("[Test #" + gTestIndex + "] triggering secondary command");
michael@0 1170 let notifications = popup.childNodes;
michael@0 1171 ok(notifications.length > 0, "at least one notification displayed");
michael@0 1172 let notification = notifications[0];
michael@0 1173
michael@0 1174 // Cancel the arrow panel slide-in transition (bug 767133) such that
michael@0 1175 // it won't interfere with us interacting with the dropdown.
michael@0 1176 document.getAnonymousNodes(popup)[0].style.transition = "none";
michael@0 1177
michael@0 1178 notification.button.focus();
michael@0 1179
michael@0 1180 popup.addEventListener("popupshown", function () {
michael@0 1181 popup.removeEventListener("popupshown", arguments.callee, false);
michael@0 1182
michael@0 1183 // Press down until the desired command is selected
michael@0 1184 for (let i = 0; i <= index; i++)
michael@0 1185 EventUtils.synthesizeKey("VK_DOWN", {});
michael@0 1186
michael@0 1187 // Activate
michael@0 1188 EventUtils.synthesizeKey("VK_RETURN", {});
michael@0 1189 }, false);
michael@0 1190
michael@0 1191 // One down event to open the popup
michael@0 1192 EventUtils.synthesizeKey("VK_DOWN", { altKey: !navigator.platform.contains("Mac") });
michael@0 1193 }
michael@0 1194
michael@0 1195 function loadURI(uri, callback) {
michael@0 1196 if (callback) {
michael@0 1197 gBrowser.addEventListener("load", function() {
michael@0 1198 // Ignore the about:blank load
michael@0 1199 if (gBrowser.currentURI.spec == "about:blank")
michael@0 1200 return;
michael@0 1201
michael@0 1202 gBrowser.removeEventListener("load", arguments.callee, true);
michael@0 1203
michael@0 1204 callback();
michael@0 1205 }, true);
michael@0 1206 }
michael@0 1207 gBrowser.loadURI(uri);
michael@0 1208 }
michael@0 1209
michael@0 1210 function dismissNotification(popup) {
michael@0 1211 info("[Test #" + gTestIndex + "] dismissing notification");
michael@0 1212 executeSoon(function () {
michael@0 1213 EventUtils.synthesizeKey("VK_ESCAPE", {});
michael@0 1214 });
michael@0 1215 }

mercurial