Wed, 31 Dec 2014 06:09:35 +0100
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 | } |