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