diff options
Diffstat (limited to 'dom/tests/mochitest/notification')
14 files changed, 1008 insertions, 0 deletions
diff --git a/dom/tests/mochitest/notification/MockServices.js b/dom/tests/mochitest/notification/MockServices.js new file mode 100644 index 000000000..f809b2438 --- /dev/null +++ b/dom/tests/mochitest/notification/MockServices.js @@ -0,0 +1,117 @@ +var MockServices = (function () { + "use strict"; + + const MOCK_ALERTS_CID = SpecialPowers.wrap(SpecialPowers.Components) + .ID("{48068bc2-40ab-4904-8afd-4cdfb3a385f3}"); + const ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/alerts-service;1"; + + const MOCK_SYSTEM_ALERTS_CID = SpecialPowers.wrap(SpecialPowers.Components) + .ID("{e86d888c-e41b-4b78-9104-2f2742a532de}"); + const SYSTEM_ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/system-alerts-service;1"; + + var registrar = SpecialPowers.wrap(SpecialPowers.Components).manager + .QueryInterface(SpecialPowers.Ci.nsIComponentRegistrar); + + var activeAlertNotifications = Object.create(null); + + var activeAppNotifications = Object.create(null); + + window.addEventListener('mock-notification-close-event', function(e) { + for (var alertName in activeAlertNotifications) { + var notif = activeAlertNotifications[alertName]; + if (notif.title === e.detail.title) { + notif.listener.observe(null, "alertfinished", null); + delete activeAlertNotifications[alertName]; + delete activeAppNotifications[alertName]; + return; + } + } + }); + + var mockAlertsService = { + showPersistentNotification: function(persistentData, alert, alertListener) { + this.showAlert(alert, alertListener); + }, + + showAlert: function(alert, alertListener) { + var listener = SpecialPowers.wrap(alertListener); + activeAlertNotifications[alert.name] = { + listener: listener, + cookie: alert.cookie, + title: alert.title + }; + + // fake async alert show event + if (listener) { + setTimeout(function () { + listener.observe(null, "alertshow", alert.cookie); + }, 100); + setTimeout(function () { + listener.observe(null, "alertclickcallback", alert.cookie); + }, 100); + } + }, + + showAlertNotification: function(imageUrl, title, text, textClickable, + cookie, alertListener, name) { + this.showAlert({ + name: name, + cookie: cookie, + title: title + }, alertListener); + }, + + closeAlert: function(name) { + var alertNotification = activeAlertNotifications[name]; + if (alertNotification) { + if (alertNotification.listener) { + alertNotification.listener.observe(null, "alertfinished", alertNotification.cookie); + } + delete activeAlertNotifications[name]; + } + + var appNotification = activeAppNotifications[name]; + if (appNotification) { + delete activeAppNotifications[name]; + } + }, + + QueryInterface: function(aIID) { + if (SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsISupports) || + SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsIAlertsService)) { + return this; + } + throw SpecialPowers.Components.results.NS_ERROR_NO_INTERFACE; + }, + + createInstance: function(aOuter, aIID) { + if (aOuter != null) { + throw SpecialPowers.Components.results.NS_ERROR_NO_AGGREGATION; + } + return this.QueryInterface(aIID); + } + }; + mockAlertsService = SpecialPowers.wrapCallbackObject(mockAlertsService); + + // MockServices API + return { + register: function () { + registrar.registerFactory(MOCK_ALERTS_CID, "alerts service", + ALERTS_SERVICE_CONTRACT_ID, + mockAlertsService); + + registrar.registerFactory(MOCK_SYSTEM_ALERTS_CID, "system alerts service", + SYSTEM_ALERTS_SERVICE_CONTRACT_ID, + mockAlertsService); + }, + + unregister: function () { + registrar.unregisterFactory(MOCK_ALERTS_CID, mockAlertsService); + registrar.unregisterFactory(MOCK_SYSTEM_ALERTS_CID, mockAlertsService); + }, + + activeAlertNotifications: activeAlertNotifications, + + activeAppNotifications: activeAppNotifications, + }; +})(); diff --git a/dom/tests/mochitest/notification/NotificationTest.js b/dom/tests/mochitest/notification/NotificationTest.js new file mode 100644 index 000000000..f17dc1d49 --- /dev/null +++ b/dom/tests/mochitest/notification/NotificationTest.js @@ -0,0 +1,136 @@ +var NotificationTest = (function () { + "use strict"; + + function info(msg, name) { + SimpleTest.info("::Notification Tests::" + (name || ""), msg); + } + + function setup_testing_env() { + SimpleTest.waitForExplicitFinish(); + // turn on testing pref (used by notification.cpp, and mock the alerts + SpecialPowers.setBoolPref("notification.prompt.testing", true); + } + + function teardown_testing_env() { + SimpleTest.finish(); + } + + function executeTests(tests, callback) { + // context is `this` object in test functions + // it can be used to track data between tests + var context = {}; + + (function executeRemainingTests(remainingTests) { + if (!remainingTests.length) { + return callback(); + } + + var nextTest = remainingTests.shift(); + var finishTest = executeRemainingTests.bind(null, remainingTests); + var startTest = nextTest.call.bind(nextTest, context, finishTest); + + try { + startTest(); + // if no callback was defined for test function, + // we must manually invoke finish to continue + if (nextTest.length === 0) { + finishTest(); + } + } catch (e) { + ok(false, "Test threw exception!"); + finishTest(); + } + })(tests); + } + + var fakeCustomData = (function () { + var buffer = new ArrayBuffer(2); + var dv = new DataView(buffer).setInt16(0, 42, true); + var canvas = document.createElement("canvas"); + canvas.width = canvas.height = 100; + var context = canvas.getContext("2d"); + + var map = new Map(); + var set = new Set(); + map.set("test", 42); + set.add(4); set.add(2); + + return { + primitives: { + a: 123, + b: "test", + c: true, + d: [1, 2, 3] + }, + date: new Date(2013, 2, 1, 1, 10), + regexp: new RegExp("[^.]+"), + arrayBuffer: buffer, + imageData: context.createImageData(100, 100), + map: map, + set: set + }; + })(); + + // NotificationTest API + return { + run: function (tests, callback) { + setup_testing_env(); + + addLoadEvent(function () { + executeTests(tests, function () { + teardown_testing_env(); + callback && callback(); + }); + }); + }, + + allowNotifications: function () { + SpecialPowers.setBoolPref("notification.prompt.testing.allow", true); + }, + + denyNotifications: function () { + SpecialPowers.setBoolPref("notification.prompt.testing.allow", false); + }, + + clickNotification: function (notification) { + // TODO: how?? + }, + + fireCloseEvent: function (title) { + window.dispatchEvent(new CustomEvent("mock-notification-close-event", { + detail: { + title: title + } + })); + }, + + info: info, + + customDataMatches: function(dataObj) { + var url = "http://www.domain.com"; + try { + return (JSON.stringify(dataObj.primitives) === + JSON.stringify(fakeCustomData.primitives)) && + (dataObj.date.toDateString() === + fakeCustomData.date.toDateString()) && + (dataObj.regexp.exec(url)[0].substr(7) === "www") && + (new Int16Array(dataObj.arrayBuffer)[0] === 42) && + (JSON.stringify(dataObj.imageData.data) === + JSON.stringify(fakeCustomData.imageData.data)) && + (dataObj.map.get("test") == 42) && + (dataObj.set.has(4) && dataObj.set.has(2)); + } catch(e) { + return false; + } + }, + + payload: { + body: "Body", + tag: "fakeTag", + icon: "icon.jpg", + lang: "en-US", + dir: "ltr", + data: fakeCustomData + } + }; +})(); diff --git a/dom/tests/mochitest/notification/desktop-notification/create_notification.html b/dom/tests/mochitest/notification/desktop-notification/create_notification.html new file mode 100644 index 000000000..b0387e4ff --- /dev/null +++ b/dom/tests/mochitest/notification/desktop-notification/create_notification.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<html> +<head><meta charset=utf-8> + <title>Create a notification</title> +</head> +<body> +<script> + +var notification = new Notification("This is a title", { + body: "This is a notification body", + tag: "sometag", + }); + +</script> +</body> +</html> diff --git a/dom/tests/mochitest/notification/desktop-notification/moz.build b/dom/tests/mochitest/notification/desktop-notification/moz.build new file mode 100644 index 000000000..28919c271 --- /dev/null +++ b/dom/tests/mochitest/notification/desktop-notification/moz.build @@ -0,0 +1,6 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + diff --git a/dom/tests/mochitest/notification/desktop-notification/notification_common.js b/dom/tests/mochitest/notification/desktop-notification/notification_common.js new file mode 100644 index 000000000..921b1e753 --- /dev/null +++ b/dom/tests/mochitest/notification/desktop-notification/notification_common.js @@ -0,0 +1,70 @@ +const MOCK_ALERTS_CID = SpecialPowers.wrap(SpecialPowers.Components).ID("{48068bc2-40ab-4904-8afd-4cdfb3a385f3}"); +const ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/alerts-service;1"; + +const MOCK_SYSTEM_ALERTS_CID = SpecialPowers.wrap(SpecialPowers.Components).ID("{e86d888c-e41b-4b78-9104-2f2742a532de}"); +const SYSTEM_ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/system-alerts-service;1"; + +var registrar = SpecialPowers.wrap(SpecialPowers.Components).manager. + QueryInterface(SpecialPowers.Ci.nsIComponentRegistrar); + +var mockAlertsService = { + showAlert: function(alert, alertListener) { + // probably should do this async.... + SpecialPowers.wrap(alertListener).observe(null, "alertshow", alert.cookie); + + if (SpecialPowers.getBoolPref("notification.prompt.testing.click_on_notification") == true) { + SpecialPowers.wrap(alertListener).observe(null, "alertclickcallback", alert.cookie); + } + + SpecialPowers.wrap(alertListener).observe(null, "alertfinished", alert.cookie); + }, + + showAlertNotification: function(imageUrl, title, text, textClickable, + cookie, alertListener, name, bidi, + lang, data) { + return this.showAlert({ + cookie: cookie + }, alertListener); + }, + + QueryInterface: function(aIID) { + if (SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsISupports) || + SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsIAlertsService)) { + return this; + } + throw SpecialPowers.Components.results.NS_ERROR_NO_INTERFACE; + }, + + createInstance: function(aOuter, aIID) { + if (aOuter != null) { + throw SpecialPowers.Components.results.NS_ERROR_NO_AGGREGATION; + } + return this.QueryInterface(aIID); + } +}; +mockAlertsService = SpecialPowers.wrapCallbackObject(mockAlertsService); + +function setup_notifications(allowPrompt, forceClick, callback) { + SpecialPowers.pushPrefEnv({'set': [["notification.prompt.testing", true], + ["notification.prompt.testing.allow", allowPrompt], + ["notification.prompt.testing.click_on_notification", forceClick]]}, + callback); + + registrar.registerFactory(MOCK_SYSTEM_ALERTS_CID, "system alerts service", + SYSTEM_ALERTS_SERVICE_CONTRACT_ID, + mockAlertsService); + + registrar.registerFactory(MOCK_ALERTS_CID, "alerts service", + ALERTS_SERVICE_CONTRACT_ID, + mockAlertsService); +} + +function reset_notifications() { + registrar.unregisterFactory(MOCK_SYSTEM_ALERTS_CID, mockAlertsService); + registrar.unregisterFactory(MOCK_ALERTS_CID, mockAlertsService); +} + +function is_feature_enabled() { + return navigator.mozNotification && SpecialPowers.getBoolPref("notification.feature.enabled"); +} + diff --git a/dom/tests/mochitest/notification/desktop-notification/test_basic_notification.html b/dom/tests/mochitest/notification/desktop-notification/test_basic_notification.html new file mode 100644 index 000000000..75f3c84b4 --- /dev/null +++ b/dom/tests/mochitest/notification/desktop-notification/test_basic_notification.html @@ -0,0 +1,50 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=573588 +--> +<head> + <title>Basic functional test</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="notification_common.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=573588">Basic property tests</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +</pre> +<script type="text/javascript"> + if (is_feature_enabled()) { + SimpleTest.waitForExplicitFinish(); + + function showNotifications() { + ok(navigator.mozNotification, "test for notification."); + + var notification = navigator.mozNotification.createNotification("test", "test"); + ok(notification, "test to ensure we can create a notification"); + + notification.onclose = function() { + ok(true, "notification was display and is now closing"); + reset_notifications(); + SimpleTest.finish(); + }; + + notification.onclick = function() { + ok(false, "Click should not have been called."); + reset_notifications(); + SimpleTest.finish(); + }; + + notification.show(); + } + + setup_notifications(true, false, showNotifications); + } else { + ok(true, "Desktop notifications not enabled."); + } +</script> +</body> +</html> diff --git a/dom/tests/mochitest/notification/desktop-notification/test_basic_notification_click.html b/dom/tests/mochitest/notification/desktop-notification/test_basic_notification_click.html new file mode 100644 index 000000000..defa0f412 --- /dev/null +++ b/dom/tests/mochitest/notification/desktop-notification/test_basic_notification_click.html @@ -0,0 +1,53 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=573588 +--> +<head> + <title>Basic functional test</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="notification_common.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=573588">Basic property tests</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +</pre> +<script type="text/javascript"> + if (is_feature_enabled()) { + SimpleTest.waitForExplicitFinish(); + + var click_was_called = false; + + function showNotifications() { + ok(navigator.mozNotification, "test for notification."); + + var notification = navigator.mozNotification.createNotification("test", "test"); + ok(notification, "test to ensure we can create a notification"); + + notification.onclose = function() { + ok(true, "notification was display and is now closing"); + ok(click_was_called, "was notification clicked?"); + + reset_notifications(); + SimpleTest.finish(); + }; + + notification.onclick = function() { + ok(true, "Click was called. Good."); + click_was_called = true; + }; + + notification.show(); + } + + setup_notifications(true, true, showNotifications); + } else { + ok(true, "Desktop notifications not enabled."); + } +</script> +</body> +</html> diff --git a/dom/tests/mochitest/notification/desktop-notification/test_leak_windowClose.html b/dom/tests/mochitest/notification/desktop-notification/test_leak_windowClose.html new file mode 100644 index 000000000..c0c9699ae --- /dev/null +++ b/dom/tests/mochitest/notification/desktop-notification/test_leak_windowClose.html @@ -0,0 +1,34 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=605309 +--> +<head> + <title>Test for leak when window closes</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="notification_common.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + +<script> +if (is_feature_enabled()) { + SimpleTest.waitForExplicitFinish(); + + function boom() + { + document.documentElement.focus(); + var x = navigator.mozNotification; + document.documentElement.addEventListener('', function(){x}, false); + ok(true, "load callback called"); + SimpleTest.finish(); + } + + window.addEventListener("load", boom, false); +} else { + ok(true, "Desktop notifications not enabled."); +} +</script> +</head> +<body> +<p> I like to write tests </p> +</body> +</html> diff --git a/dom/tests/mochitest/notification/desktop-notification/test_notification_tag.html b/dom/tests/mochitest/notification/desktop-notification/test_notification_tag.html new file mode 100644 index 000000000..37bcb16c0 --- /dev/null +++ b/dom/tests/mochitest/notification/desktop-notification/test_notification_tag.html @@ -0,0 +1,110 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=782211 +--> +<head> + <title>Bug 782211</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=782211">Bug 782211</a> +<p id="display"></p> +<iframe name="sameDomain"></iframe> +<iframe name="anotherSameDomain"></iframe> +<iframe name="crossDomain"></iframe> +<div id="content" style="display: none"> +</div> +<pre id="test"> +</pre> +<script type="text/javascript"> + const MOCK_CID = SpecialPowers.wrap(SpecialPowers.Components).ID("{dbe37e64-d9a3-402c-8d8a-0826c619f7ad}"); + const ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/alerts-service;1"; + + var mockAlertsService = { + showAlert: function(alert, alertListener) { + notificationsCreated.push(alert.name); + if (notificationsCreated.length == 3) { + checkNotifications(); + } + }, + + showAlertNotification: function(imageUrl, title, text, textClickable, + cookie, alertListener, name, dir, + lang, data) { + this.showAlert({ name: name }); + }, + + QueryInterface: function(aIID) { + if (SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsISupports) || + SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsIAlertsService)) { + return this; + } + throw SpecialPowers.Components.results.NS_ERROR_NO_INTERFACE; + }, + + createInstance: function(aOuter, aIID) { + if (aOuter != null) { + throw SpecialPowers.Components.results.NS_ERROR_NO_AGGREGATION; + } + return this.QueryInterface(aIID); + } + }; + mockAlertsService = SpecialPowers.wrapCallbackObject(mockAlertsService); + + var notificationsCreated = []; + function checkNotifications() { + // notifications created by the test1 origin + var test1notifications = []; + // notifications created by the test2 origin + var test2notifications = []; + for (var i = 0; i < notificationsCreated.length; i++) { + var notificationName = notificationsCreated[i]; + if (notificationName.indexOf("test1") !== -1) { + test1notifications.push(notificationsCreated[i]); + } else if (notificationName.indexOf("test2") !== -1) { + test2notifications.push(notificationsCreated[i]); + } + } + + is(test1notifications.length, 2, "2 notifications should be created by test1.example.org:80 origin."); + is(test1notifications[0], test1notifications[1], "notification names should be identical."); + is(test2notifications.length, 1, "1 notification should be created by test2.example.org:80 origin."); + + // Register original alerts service. + SpecialPowers.wrap(SpecialPowers.Components). + manager.QueryInterface(SpecialPowers.Ci.nsIComponentRegistrar). + unregisterFactory(MOCK_CID, mockAlertsService); + + SimpleTest.finish(); + } + + if (window.Notification) { + SimpleTest.waitForExplicitFinish(); + + function showNotifications() { + SpecialPowers.wrap(SpecialPowers.Components). + manager.QueryInterface(SpecialPowers.Ci.nsIComponentRegistrar). + registerFactory(MOCK_CID, "alerts service", ALERTS_SERVICE_CONTRACT_ID, mockAlertsService); + + // Load two frames with the same origin that create notification with the same tag. + // Both pages should generate notifications with the same name, and thus the second + // notification should replace the first. + frames["sameDomain"].location.href = "http://test1.example.org:80/tests/dom/tests/mochitest/notification/create_notification.html"; + frames["anotherSameDomain"].location.href = "http://test1.example.org:80/tests/dom/tests/mochitest/notification/create_notification.html"; + + // Load a frame with a different origin that creates a notification with the same tag. + // The notification name should be different and thus no notifications should be replaced. + frames["crossDomain"].location.href = "http://test2.example.org:80/tests/dom/tests/mochitest/notification/create_notification.html"; + } + + SpecialPowers.pushPrefEnv({'set': [["notification.prompt.testing", true], + ["notification.prompt.testing.allow", true]]}, + showNotifications); + } else { + ok(true, "Notifications are not enabled on the platform."); + } +</script> +</body> +</html> diff --git a/dom/tests/mochitest/notification/desktop-notification/test_system_principal.xul b/dom/tests/mochitest/notification/desktop-notification/test_system_principal.xul new file mode 100644 index 000000000..1690bc101 --- /dev/null +++ b/dom/tests/mochitest/notification/desktop-notification/test_system_principal.xul @@ -0,0 +1,85 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=874090 +--> +<window title="Mozilla Bug 874090" onload="runTests()" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=874090" + target="_blank">Mozilla Bug 874090</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Bug 874090 **/ + const MOCK_CID = Components.ID("{2a0f83c4-8818-4914-a184-f1172b4eaaa7}"); + const ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/alerts-service;1"; + + var mockAlertsService = { + showAlert: function(alert, alertListener) { + ok(true, "System principal was granted permission and is able to call showAlert."); + unregisterMock(); + SimpleTest.finish(); + }, + + showAlertNotification: function(imageUrl, title, text, textClickable, + cookie, alertListener, name, dir, lang, data) { + this.showAlert(); + }, + + QueryInterface: function(aIID) { + if (aIID.equals(Components.interfaces.nsISupports) || + aIID.equals(Components.interfaces.nsIAlertsService)) { + return this; + } + throw Components.results.NS_ERROR_NO_INTERFACE; + }, + + createInstance: function(aOuter, aIID) { + if (aOuter != null) { + throw Components.results.NS_ERROR_NO_AGGREGATION; + } + return this.QueryInterface(aIID); + } + }; + + function registerMock() { + Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar). + registerFactory(MOCK_CID, "alerts service", ALERTS_SERVICE_CONTRACT_ID, mockAlertsService); + } + + function unregisterMock() { + Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar). + unregisterFactory(MOCK_CID, mockAlertsService); + } + + function runTests() { + registerMock(); + + is(Notification.permission, "granted", "System principal should be automatically granted permission."); + + Notification.requestPermission(function(permission) { + is(permission, "granted", "System principal should be granted permission when calling requestPermission."); + + if (permission == "granted") { + // Create a notification and make sure that it is able to call into + // the mock alert service to show the notification. + new Notification("Hello"); + } else { + unregisterMock(); + SimpleTest.finish(); + } + }); + } + + SimpleTest.waitForExplicitFinish(); + ]]> + </script> +</window> diff --git a/dom/tests/mochitest/notification/mochitest.ini b/dom/tests/mochitest/notification/mochitest.ini new file mode 100644 index 000000000..c0de5ed46 --- /dev/null +++ b/dom/tests/mochitest/notification/mochitest.ini @@ -0,0 +1,10 @@ +[DEFAULT] + +support-files = + MockServices.js + NotificationTest.js + +[test_notification_basics.html] +[test_notification_storage.html] +[test_bug931307.html] +skip-if = (os == 'android') # Bug 1258975 on android. diff --git a/dom/tests/mochitest/notification/test_bug931307.html b/dom/tests/mochitest/notification/test_bug931307.html new file mode 100644 index 000000000..bd31c7061 --- /dev/null +++ b/dom/tests/mochitest/notification/test_bug931307.html @@ -0,0 +1,34 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html> +<head> + <title>Bug 931307</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<pre id="test"> +<script type="application/javascript"><!-- + +SimpleTest.waitForExplicitFinish(); +var notification = new Notification(""); +var promise = Notification.get(); +promise.then( + function onSuccess() { + ok(true, "No error when creating a notification without title"); + }, + function onFailure() { + ok(false, "Should not throw error when creating a notification without title"); + } +).then(() => { + notification.close(); +}).then(() => { + SimpleTest.finish(); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/tests/mochitest/notification/test_notification_basics.html b/dom/tests/mochitest/notification/test_notification_basics.html new file mode 100644 index 000000000..3d0465c3f --- /dev/null +++ b/dom/tests/mochitest/notification/test_notification_basics.html @@ -0,0 +1,129 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Notification Basics</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="MockServices.js"></script> + <script type="text/javascript" src="NotificationTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"></div> +<pre id="test"></pre> +<script type="text/javascript"> + + var info = NotificationTest.info; + var options; + + SimpleTest.requestFlakyTimeout("untriaged"); + + var steps = [ + function () { + info("Test notification spec"); + ok(Notification, "Notification constructor exists"); + ok(Notification.permission, "Notification.permission exists"); + ok(Notification.requestPermission, "Notification.requestPermission exists"); + ok(Notification.get, "Notification.get exists"); + }, + + function () { + info("Test requestPermission without callback"); + Notification.requestPermission(); + }, + + function (done) { + info("Test requestPermission deny"); + function assertPermissionDenied(perm) { + is(perm, "denied", "Permission should be denied."); + is(Notification.permission, "denied", "Permission should be denied."); + } + NotificationTest.denyNotifications(); + Notification.requestPermission() + .then(assertPermissionDenied) + .then(_ => Notification.requestPermission(assertPermissionDenied)) + .catch(err => { + ok(!err, "requestPermission should not reject promise"); + }) + .then(done); + }, + + function (done) { + info("Test requestPermission grant"); + function assertPermissionGranted(perm) { + is(perm, "granted", "Permission should be granted."); + is(Notification.permission, "granted", "Permission should be granted"); + } + NotificationTest.allowNotifications(); + Notification.requestPermission() + .then(assertPermissionGranted) + .then(_ => Notification.requestPermission(assertPermissionGranted)) + .catch(err => { + ok(!err, "requestPermission should not reject promise"); + }) + .then(done); + }, + + function (done) { + info("Test invalid requestPermission"); + Notification.requestPermission({}) + .then(_ => { + ok(false, "Non callable arg to requestPermission should reject promise"); + }, err => { + ok(true, "Non callable arg to requestPermission should reject promise"); + }) + .then(done); + }, + + function (done) { + info("Test create notification"); + + options = NotificationTest.payload; + + var notification = new Notification("This is a title", options); + + ok(notification, "Notification exists"); + is(notification.onclick, null, "onclick() should be null"); + is(notification.onshow, null, "onshow() should be null"); + is(notification.onerror, null, "onerror() should be null"); + is(notification.onclose, null, "onclose() should be null"); + is(typeof notification.close, "function", "close() should exist"); + is(typeof notification.data, "object", "data should be a JS object"); + + is(notification.dir, options.dir, "auto should get set"); + is(notification.lang, options.lang, "lang should get set"); + is(notification.body, options.body, "body should get set"); + is(notification.tag, options.tag, "tag should get set"); + is(notification.icon, options.icon, "icon should get set"); + ok(NotificationTest.customDataMatches(notification.data), + "data should get set"); + + // store notification in test context + this.notification = notification; + + notification.onshow = function () { + ok(true, "onshow handler should be called"); + done(); + }; + }, + + function (done) { + info("Test closing a notification"); + var notification = this.notification; + + notification.onclose = function () { + ok(true, "onclose handler should be called"); + done(); + }; + + notification.close(); + } + ]; + + MockServices.register(); + NotificationTest.run(steps, function () { + MockServices.unregister(); + }); +</script> +</body> +</html> diff --git a/dom/tests/mochitest/notification/test_notification_storage.html b/dom/tests/mochitest/notification/test_notification_storage.html new file mode 100644 index 000000000..ce5530cb8 --- /dev/null +++ b/dom/tests/mochitest/notification/test_notification_storage.html @@ -0,0 +1,158 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Notification Basics</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="MockServices.js"></script> + <script type="text/javascript" src="NotificationTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"></div> +<pre id="test"></pre> +<script type="text/javascript"> + + SimpleTest.requestFlakyTimeout("untriaged"); + + function deleteAllNotifications(done) { + var promise = Notification.get(); + promise.then(function (notifications) { + notifications.forEach(function(notification) { + notification.close(); + }); + done(); + }); + } + + var info = NotificationTest.info; + + var steps = [ + function (done) { + info("Test that Notifcation.get fulfills the promise"); + var promise = Notification.get(); + ok(promise.then, "should return a promise"); + + // Create a new notification to make sure + // Notification.get() works while creating + var notification = new Notification("this is a test"); + + promise.then(function () { + ok(true, "promise should be fulfilled"); + done(); + }); + }, + + deleteAllNotifications, + + function (done) { + info("Test adding a notification, and making sure get returns it"); + NotificationTest.allowNotifications(); + var options = NotificationTest.payload; + + var notification = new Notification("This is a title", options); + var promise = Notification.get(); + promise.then(function (notifications) { + ok(notifications.length, "should return notifications"); + for (var i = 0; i < notifications.length; i++) { + var notification = notifications[i]; + if (notification.tag === options.tag) { + ok(true, "should contain newly created notification"); + for (var key in options) { + if (key === "data") { + ok(NotificationTest.customDataMatches(notification.data), + "data property should match"); + continue; + } + is(notification[key], options[key], key + " property should match"); + } + notification.close(); + return; + } + } + ok(false, "should contain newly created notification"); + notification.close(); + }); + notification.onclose = done; + }, + + function (done) { + info("Testing fetching notification by tag filter"); + var n1 = new Notification("title1", {tag: "tag1"}); + var n2 = new Notification("title2", {tag: "tag2"}); + var n3 = new Notification("title3", {tag: "tag3"}); + var promise = Notification.get({tag: "tag3"}); + promise.then(function (notifications) { + var notification = notifications[0]; + is(notifications.length, 1, "should return 1 notification"); + is(notifications[0].title, "title3", "titles should match"); + is(notifications[0].tag, "tag3", "tags should match"); + var closeCount = 0; + var waitForAll = function () { + if (++closeCount >= 3) { + done(); + } + }; + n1.onclose = waitForAll; + n2.onclose = waitForAll; + n3.onclose = waitForAll; + n1.close(); + n2.close(); + n3.close(); + }); + }, + + deleteAllNotifications, + + function (done) { + info("Testing fetching no notifications"); + var promise = Notification.get(); + promise.then(function (notifications) { + is(notifications.length, 0, "should return 0 notifications"); + done(); + }); + }, + + function (done) { + info("Testing fetching multiple notifications"); + var n1 = new Notification("title1"); + var n2 = new Notification("title2"); + var n3 = new Notification("title3"); + var promise = Notification.get(); + promise.then(function (notifications) { + is(notifications.length, 3, "should return 3 notifications"); + n1.close(); + n2.close(); + n3.close(); + done(); + }); + }, + + deleteAllNotifications, + + function (done) { + info("Testing 'alertfinished' removes the notification from DB"); + var n = new Notification("test-title" + Math.random()); + n.onclose = function() { + Notification.get().then(function(notifications) { + is(notifications.length, 0, "should return 0 notifications"); + done(); + }); + }; + info("Installing 'onshow' for " + n.title); + n.onshow = function() { + info("Triggered 'onshow' for " + n.title); + window.setTimeout(function() { + NotificationTest.fireCloseEvent(n.title); + }, 100); + }; + } + ]; + + MockServices.register(); + NotificationTest.run(steps, function () { + MockServices.unregister(); + }); +</script> +</body> +</html> |