diff options
Diffstat (limited to 'testing/web-platform/tests/notifications')
32 files changed, 965 insertions, 0 deletions
diff --git a/testing/web-platform/tests/notifications/META.yml b/testing/web-platform/tests/notifications/META.yml new file mode 100644 index 0000000000..0daa86e6f4 --- /dev/null +++ b/testing/web-platform/tests/notifications/META.yml @@ -0,0 +1,3 @@ +spec: https://notifications.spec.whatwg.org/ +suggested_reviewers: + - sideshowbarker diff --git a/testing/web-platform/tests/notifications/body-basic-manual.https.html b/testing/web-platform/tests/notifications/body-basic-manual.https.html new file mode 100644 index 0000000000..a479917aee --- /dev/null +++ b/testing/web-platform/tests/notifications/body-basic-manual.https.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Notification.body (basic)</title> +<link rel="author" title="Intel" href="http://www.intel.com/"> +<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="common.js"></script> +<div id=passfail></div> +<script> +setup({ explicit_timeout: true }) +if (hasNotificationPermission()) { + async_test(function (t) { + t.step(function () { + var notification = null, + notifications = [], + text = "This is the body content: Room 101" + createPassFail("If a notification appears containing the text" + + " \"" + text + "\"", + t, closeNotifications, notifications) + notification = new Notification("", { + body: text + }) + notifications.push(notification) + }) + }) +} +</script> diff --git a/testing/web-platform/tests/notifications/body-empty-manual.https.html b/testing/web-platform/tests/notifications/body-empty-manual.https.html new file mode 100644 index 0000000000..a94f08e1c5 --- /dev/null +++ b/testing/web-platform/tests/notifications/body-empty-manual.https.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Notification.body (empty string)</title> +<link rel="author" title="Intel" href="http://www.intel.com/"> +<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="common.js"></script> +<div id=passfail></div> +<script> +setup({ explicit_timeout: true }) +if (hasNotificationPermission()) { + async_test(function (t) { + t.step(function () { + var notification = null, + notifications = [], + text = "This is the title: New e-mail received" + createPassFail("If a notification appears containing the text " + + "\"" + text + "\"" + + " but containing no body text other than any boilerplate" + + " content the browser may automatically add to all" + + " notifications (for example, some browsers show the origin" + + " in the notification)", t, closeNotifications, notifications) + notification = new Notification(text, { + body: "" + }) + notifications.push(notification) + }) + }) +} +</script> diff --git a/testing/web-platform/tests/notifications/common.js b/testing/web-platform/tests/notifications/common.js new file mode 100644 index 0000000000..ecfa0e3c2d --- /dev/null +++ b/testing/web-platform/tests/notifications/common.js @@ -0,0 +1,48 @@ +function createPassFail(condition, test, cleanup, cleanupParam) { + var div = document.querySelector("#passfail") + var para = document.createElement("p") + var pass = document.createElement("button") + var fail = document.createElement("button") + var style = "font-family: monospace" + para.innerHTML = condition + + ', press the PASS button;' + + ' otherwise press the FAIL button.', + pass.innerHTML = "PASS" + fail.innerHTML = "FAIL" + pass.setAttribute("style", style) + fail.setAttribute("style", style) + pass.addEventListener("click", function () { + clearPassFail() + cleanup(cleanupParam) + test.done() + }, false) + fail.addEventListener("click", function () { + clearPassFail() + cleanup(cleanupParam) + test.force_timeout() + test.set_status(test.FAIL) + test.done() + }, false) + document.body.appendChild(div) + div.appendChild(para) + div.appendChild(pass) + div.appendChild(fail) +} +function clearPassFail() { + document.querySelector("#passfail").innerHTML = "" +} +function closeNotifications(notifications) { + for (var i=0; i < notifications.length; i++) { + notifications[i].close() + } +} +function hasNotificationPermission() { + Notification.requestPermission() + if (Notification.permission != "granted") { + alert("TEST NOT RUN. Change your browser settings so that" + + " notifications for this origin are allowed, and then re-run" + + " this test.") + return false + } + return true +} diff --git a/testing/web-platform/tests/notifications/constructor-basic.https.html b/testing/web-platform/tests/notifications/constructor-basic.https.html new file mode 100644 index 0000000000..3f704de03e --- /dev/null +++ b/testing/web-platform/tests/notifications/constructor-basic.https.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Notification constructor (basic)</title> +<link rel="author" title="Intel" href="http://www.intel.com/"> +<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(function() { + var notification = new Notification("New Email Received") + assert_true(notification instanceof Notification) + notification.onshow = function() { + notification.close() + } +}, "Called the notification constructor with one argument.") +</script> diff --git a/testing/web-platform/tests/notifications/constructor-invalid.https.html b/testing/web-platform/tests/notifications/constructor-invalid.https.html new file mode 100644 index 0000000000..2fae804c2c --- /dev/null +++ b/testing/web-platform/tests/notifications/constructor-invalid.https.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Notification constructor (invalid)</title> +<link rel="author" title="Intel" href="http://www.intel.com/"> +<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(function() { + assert_throws_js(TypeError, function() { + new Notification() + }) +}, "Called the notification constructor with no arguments.") +</script> diff --git a/testing/web-platform/tests/notifications/constructor-non-secure.html b/testing/web-platform/tests/notifications/constructor-non-secure.html new file mode 100644 index 0000000000..df1f74a71f --- /dev/null +++ b/testing/web-platform/tests/notifications/constructor-non-secure.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Notification constructor (basic) on a non-secure connection</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +async_test(function (t) { + const notification = new Notification("Sup."); + notification.onerror = t.step_func_done(e => { + assert_equals(e.type, "error"); + }); +}, "new Notification calls onerror in non-secure contexts") +</script> diff --git a/testing/web-platform/tests/notifications/event-onclick-manual.https.html b/testing/web-platform/tests/notifications/event-onclick-manual.https.html new file mode 100644 index 0000000000..0d48d06ae8 --- /dev/null +++ b/testing/web-platform/tests/notifications/event-onclick-manual.https.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Notification.onclick (basic)</title> +<link rel="author" title="Apple Inc." href="http://www.apple.com/"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="common.js"></script> +<script> +setup({ explicit_timeout: true }) +if (hasNotificationPermission()) { + async_test(function (t) { + t.step(function () { + var notification = + new Notification("Please click on the notification.", { + body: "Click me to test clicking on notifications." + }) + notification.onclick = function(e) { + assert_equals(Object.prototype.toString.call(e), "[object Event]") + assert_equals(e.type, "click") + t.done() + } + }) + }) +} +</script> diff --git a/testing/web-platform/tests/notifications/event-onclose.https.html b/testing/web-platform/tests/notifications/event-onclose.https.html new file mode 100644 index 0000000000..b410e6c9a1 --- /dev/null +++ b/testing/web-platform/tests/notifications/event-onclose.https.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Notification.onclose (basic)</title> +<link rel="author" title="Apple Inc." href="http://www.apple.com/"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script> +promise_setup(() => { + return test_driver.set_permission({ name: "notifications" }, "granted") +}) + +promise_test(async t => { + const notification = new Notification("New Email Received") + await new Promise(resolve => { + notification.onshow = resolve; + }) + notification.close() + const event = await new Promise(resolve => { + notification.onclose = resolve; + }) + assert_equals(Object.prototype.toString.call(event), "[object Event]") + assert_equals(event.type, "close", "Checked the event type.") +}, "Invoked the onclose event handler.") +</script> diff --git a/testing/web-platform/tests/notifications/event-onerror-default-manual.https.html b/testing/web-platform/tests/notifications/event-onerror-default-manual.https.html new file mode 100644 index 0000000000..4a50de7366 --- /dev/null +++ b/testing/web-platform/tests/notifications/event-onerror-default-manual.https.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Notification.onerror (permission=default)</title> +<link rel="author" title="Apple Inc." href="http://www.apple.com/"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +setup({ explicit_timeout: true }) +if (Notification.permission != "default") { + alert("TEST NOT RUN. Change your browser settings so that the notification" + + " settings for this origin are completely cleared/removed, (so your" + + " browser default settings are used for this origin), and then reload" + + " this page.") +} else { + async_test(function (t) { + t.step(function () { + var notification = new Notification("New Email Received") + notification.onerror = function(e) { + assert_equals(Object.prototype.toString.call(e), "[object Event]") + assert_equals(e.type, "error") + Notification.requestPermission() + t.done() + } + }) + }) +} +</script> diff --git a/testing/web-platform/tests/notifications/event-onerror-denied-manual.https.html b/testing/web-platform/tests/notifications/event-onerror-denied-manual.https.html new file mode 100644 index 0000000000..b90fb38cc1 --- /dev/null +++ b/testing/web-platform/tests/notifications/event-onerror-denied-manual.https.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Notification.onerror (permission=denied)</title> +<link rel="author" title="Apple Inc." href="http://www.apple.com/"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +setup({ explicit_timeout: true }) +Notification.requestPermission() +if (Notification.permission != "denied") { + alert("TEST NOT RUN. Change your browser settings so that notifications" + + " for this origin are blocked, and then reload this page.") +} else { + async_test(function (t) { + t.step(function () { + var notification = new Notification("New Email Received") + notification.onerror = function(e) { + assert_equals(Object.prototype.toString.call(e), "[object Event]") + assert_equals(e.type, "error") + Notification.requestPermission() + t.done() + } + }) + }) +} +</script> diff --git a/testing/web-platform/tests/notifications/event-onshow.https.html b/testing/web-platform/tests/notifications/event-onshow.https.html new file mode 100644 index 0000000000..2f7959e7d3 --- /dev/null +++ b/testing/web-platform/tests/notifications/event-onshow.https.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Notification.onshow (basic)</title> +<link rel="author" title="Intel" href="http://www.intel.com/"> +<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script> +promise_setup(() => { + return test_driver.set_permission({ name: "notifications" }, "granted") +}) + +promise_test(async t => { + const notification = new Notification("New Email Received") + const event = await new Promise(resolve => { + notification.onshow = resolve; + }) + notification.close() + assert_equals(Object.prototype.toString.call(event), "[object Event]") + assert_equals(event.type, "show", "Checked the event type.") +}, "Invoked the onshow event handler.") +</script> diff --git a/testing/web-platform/tests/notifications/getnotifications-across-processes.https.window.js b/testing/web-platform/tests/notifications/getnotifications-across-processes.https.window.js new file mode 100644 index 0000000000..ad0ecf27ef --- /dev/null +++ b/testing/web-platform/tests/notifications/getnotifications-across-processes.https.window.js @@ -0,0 +1,21 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/service-workers/service-worker/resources/test-helpers.sub.js + +// (Cannot use `global=serviceworker` because testdriver only supports window) + +navigator.serviceWorker.addEventListener("message", async ev => { + if (ev.data === "notification-create") { + // (Scope used by service_worker_test) + const scope = "scope" + window.location.pathname; + const reg = await navigator.serviceWorker.getRegistration(scope); + await reg.showNotification("Created from window"); + reg.active.postMessage("notification-created"); + } +}); + +promise_setup(() => { + return test_driver.set_permission({ name: "notifications" }, "granted"); +}); + +service_worker_test("getnotifications-sw.js", "Service worker test setup"); diff --git a/testing/web-platform/tests/notifications/getnotifications-sw.js b/testing/web-platform/tests/notifications/getnotifications-sw.js new file mode 100644 index 0000000000..331913b993 --- /dev/null +++ b/testing/web-platform/tests/notifications/getnotifications-sw.js @@ -0,0 +1,56 @@ +importScripts("/resources/testharness.js"); + +async function cleanup() { + for (const n of await registration.getNotifications()) { + n.close(); + } +} + +async function test_notification(t, title) { + t.add_cleanup(cleanup); + + const notifications = await registration.getNotifications(); + + assert_equals( + notifications.length, + 1, + "There should be one stored notification" + ); + const notification = notifications[0]; + assert_true(notification instanceof Notification, "Should be a Notification"); + assert_equals(notification.title, title, "Title should match"); +} + +async function postAll(data) { + const clients = await self.clients.matchAll({ includeUncontrolled: true }); + assert_true(clients.length > 0, "clients.length"); + for (const client of clients) { + client.postMessage(data); + } +} + +async function untilActivate() { + if (registration.active) { + return; + } + return new Promise(resolve => { + addEventListener("activate", resolve, { once: true }); + }); +} + +promise_test(async t => { + await new Promise((resolve, reject) => { + self.addEventListener("message", ev => { + if (ev.data === "notification-created") { + resolve(); + } + }); + untilActivate().then(() => postAll("notification-create")).catch(reject); + }); + await test_notification(t, "Created from window"); +}, "Get notification created from window"); + +promise_test(async t => { + await registration.showNotification("Created here"); + await test_notification(t, "Created here"); +}, "Create and get notification within service worker"); diff --git a/testing/web-platform/tests/notifications/historical.any.js b/testing/web-platform/tests/notifications/historical.any.js new file mode 100644 index 0000000000..fe5f3e9059 --- /dev/null +++ b/testing/web-platform/tests/notifications/historical.any.js @@ -0,0 +1,3 @@ +test(() => { + assert_equals(Notification.get, undefined); +}, "Notification.get is obsolete"); diff --git a/testing/web-platform/tests/notifications/icon-basic-manual.https.html b/testing/web-platform/tests/notifications/icon-basic-manual.https.html new file mode 100644 index 0000000000..32e8e0bbbd --- /dev/null +++ b/testing/web-platform/tests/notifications/icon-basic-manual.https.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Notification.icon (basic)</title> +<link rel="author" title="Intel" href="http://www.intel.com/"> +<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="common.js"></script> +<div id=passfail></div> +<script> +setup({ explicit_timeout: true }) +if (hasNotificationPermission()) { + async_test(function (t) { + t.step(function () { + var notification = null, + notifications = [] + createPassFail("If a notification appears containing" + + " an image of a cat", + t, closeNotifications, notifications) + notification = new Notification("New Email Received", { + body: "Room 101", + icon: "http://test.csswg.org/source/support/cat.png" + }) + notifications.push(notification) + }) + }) +} +</script> diff --git a/testing/web-platform/tests/notifications/icon-empty-manual.https.html b/testing/web-platform/tests/notifications/icon-empty-manual.https.html new file mode 100644 index 0000000000..a4b288fa59 --- /dev/null +++ b/testing/web-platform/tests/notifications/icon-empty-manual.https.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Notification.icon (empty string)</title> +<link rel="author" title="Intel" href="http://www.intel.com/"> +<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="common.js"></script> +<div id=passfail></div> +<script> +setup({ explicit_timeout: true }) +if (hasNotificationPermission()) { + async_test(function (t) { + t.step(function () { + var notification = null, + notifications = [] + createPassFail("If a notification appears containing no image", + t, closeNotifications, notifications) + notification = new Notification("New Email Received", { + body: "Room 101", + icon: "" + }) + notifications.push(notification) + }) + }) +} +</script> diff --git a/testing/web-platform/tests/notifications/idlharness.https.any.js b/testing/web-platform/tests/notifications/idlharness.https.any.js new file mode 100644 index 0000000000..e3afe2c219 --- /dev/null +++ b/testing/web-platform/tests/notifications/idlharness.https.any.js @@ -0,0 +1,31 @@ +// META: global=window,worker +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js + +'use strict'; + +// https://notifications.spec.whatwg.org/ + +idl_test( + ['notifications'], + ['service-workers', 'hr-time', 'html', 'dom'], + idl_array => { + if (self.ServiceWorkerGlobalScope) { + idl_array.add_objects({ + ServiceWorkerGlobalScope: ['self'], + }); + // NotificationEvent could be tested here, but the constructor requires + // a Notification instance which cannot be created in a service worker, + // see below. + } else { + // While the Notification interface is exposed in service workers, the + // constructor (https://notifications.spec.whatwg.org/#dom-notification-notification) + // is defined to throw a TypeError. Therefore, we only add the object in + // the other scopes. + idl_array.add_objects({ + Notification: ['notification'], + }); + self.notification = new Notification('title'); + } + } +); diff --git a/testing/web-platform/tests/notifications/instance.https.html b/testing/web-platform/tests/notifications/instance.https.html new file mode 100644 index 0000000000..5ccc6cd1e3 --- /dev/null +++ b/testing/web-platform/tests/notifications/instance.https.html @@ -0,0 +1,60 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Notification instance basic tests</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/custom-data.js"></script> +<script> +var n = new Notification("Radio check", + { + dir: "ltr", + lang: "aa", + body: "This is a radio check.", + tag: "radio_check999", + icon: "http://example.com/icon.png", + data: fakeCustomData, + } +) +n.onshow = function() { + n.close() +} +test(function() { + assert_true(n instanceof Notification) +},"Notification instance exists.") +test(function() { + assert_true("close" in n) +},"Attribute exists: close") +test(function() { + assert_true("onclick" in n) +},"Attribute exists: onclick") +test(function() { + assert_true("onshow" in n) +},"Attribute exists: onshow") +test(function() { + assert_true("onerror" in n) +},"Attribute exists: onerror") +test(function() { + assert_true("onclose" in n) +},"Attribute exists: onclose") +test(function() { + assert_equals("Radio check", n.title) +},"Attribute exists with expected value: title") +test(function() { + assert_equals("ltr", n.dir) +},"Attribute exists with expected value: dir") +test(function() { + assert_equals("aa", n.lang) +},"Attribute exists with expected value: lang") +test(function() { + assert_equals("This is a radio check.", n.body) +},"Attribute exists with expected value: body") +test(function() { + assert_equals("radio_check999", n.tag) +},"Attribute exists with expected value: tag") +test(function() { + assert_equals("http://example.com/icon.png", n.icon) +},"Attribute exists with expected value: icon") +test(function() { + assert_custom_data(n.data); +},"Attribute exists with expected value: data") +</script> diff --git a/testing/web-platform/tests/notifications/lang.https.html b/testing/web-platform/tests/notifications/lang.https.html new file mode 100644 index 0000000000..be1795c8c9 --- /dev/null +++ b/testing/web-platform/tests/notifications/lang.https.html @@ -0,0 +1,63 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Notification.lang</title> +<link rel="author" title="Apple Inc." href="http://www.apple.com/"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +setup({ explicit_done: true }); + +/* Validity and well-formedness was determined by using the BCP 47 + Validator at http://schneegans.de/lv/ */ + +/* The empty string is valid, as well as any valid BCP 47 language tag. */ +var valid_langs = ["", "en", "en-US-x-hixie", "de-DE", "de-de", "de-De", + "de-dE", "de-DE-1996", "de-Latn-DE", "de-Latf-DE", + "de-Latn-DE-1996", "de-CH", "it-CH", "fr-CH", + "rm-CH", "es-CH"]; + +/* Well-formed but invalid BCP 47 language tags should not round-trip; + they should come back as the empty string. */ +var well_formed_langs = ["Latn-de", "Latf-de", "tic-tac-tac-toe", + "cocoa-1-bar", "cocoa-a-bar"]; + +/* Invalid BCP 47 language tags should not round-trip; they should come + back as the empty string. */ +var invalid_langs = ["en-", "en-\-", "foo-\-bar", "id-\-\-Java", "fr-x", + "fr-xenomorph", "fr-x-xenomorph", "a", "a-fr-lang", + "b-fr-lang", "es1-KK-aa-bb-cc-dd", + "es2-KL-aa-bb-cc-dd", "es3-KM-aa-bb-cc-dd", "fooÉ", + "foöÉ-bÁr", "foöÉbÁr"]; + +function test_lang(language, should_passthrough) { + var expected = should_passthrough ? language : ""; + test(function() { + if (Notification.permission != "granted") { + this.force_timeout() + this.set_status(this.NOTRUN, "You must allow notifications for this origin before running this test.") + } + var notification = new Notification("This is a notification.", { + lang: language + }); + assert_equals(notification.lang, expected, "notification.lang"); + notification.onshow = function() { + notification.close(); + }; + }, + "Roundtripping lang \"" + language + "\". Expecting \"" + expected + "\"."); +} + +for (var i=0; i<valid_langs.length; i++) { + test_lang(valid_langs[i], true); +} + +for (var i=0; i<well_formed_langs.length; i++) { + test_lang(well_formed_langs[i], false); +} + +for (var i=0; i<invalid_langs.length; i++) { + test_lang(invalid_langs[i], false); +} + +done(); +</script> diff --git a/testing/web-platform/tests/notifications/noop-sw.js b/testing/web-platform/tests/notifications/noop-sw.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testing/web-platform/tests/notifications/noop-sw.js diff --git a/testing/web-platform/tests/notifications/permission.html b/testing/web-platform/tests/notifications/permission.html new file mode 100644 index 0000000000..d8b201e42e --- /dev/null +++ b/testing/web-platform/tests/notifications/permission.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Notification.permission (basic)</title> +<link rel="author" title="Intel" href="http://www.intel.com/"> +<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(function() { + assert_in_array(Notification.permission, + ["default", "denied", "granted"], + "Notification.permission") +}, "Checked the Notification.permission property.") +</script> diff --git a/testing/web-platform/tests/notifications/permissions-non-secure.html b/testing/web-platform/tests/notifications/permissions-non-secure.html new file mode 100644 index 0000000000..0f4724c9b6 --- /dev/null +++ b/testing/web-platform/tests/notifications/permissions-non-secure.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Notification permissions should be denied in non-secure contexts</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +promise_test(t => { + return Notification.requestPermission().then(result => { + assert_equals(result, "denied"); + }); +}, "Notification.requestPermission must be called from a secure context"); + +test(t => { + assert_equals(Notification.permission, "denied"); +}, "Notification.permission must be called from a secure context"); +</script> diff --git a/testing/web-platform/tests/notifications/requestPermission-denied-manual.https.html b/testing/web-platform/tests/notifications/requestPermission-denied-manual.https.html new file mode 100644 index 0000000000..a7ec052dba --- /dev/null +++ b/testing/web-platform/tests/notifications/requestPermission-denied-manual.https.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Notification.requestPermission (permission=denied)</title> +<link rel="author" title="Intel" href="http://www.intel.com/"> +<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +setup({ explicit_timeout: true }) +Notification.requestPermission() +if (Notification.permission != "denied") { + alert("TEST NOT RUN. Change your browser settings so that notifications" + + " for this origin are blocked, and then reload this page.") +} else { + async_test(function (t) { + t.step(function () { + Notification.requestPermission() + t.done() + }) + }) +} +</script> diff --git a/testing/web-platform/tests/notifications/requestPermission-granted-manual.https.html b/testing/web-platform/tests/notifications/requestPermission-granted-manual.https.html new file mode 100644 index 0000000000..970f4e3cbc --- /dev/null +++ b/testing/web-platform/tests/notifications/requestPermission-granted-manual.https.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Notification.requestPermission (permission=granted)</title> +<link rel="author" title="Intel" href="http://www.intel.com/"> +<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="common.js"></script> +<script> +setup({ explicit_timeout: true }) +if (hasNotificationPermission()) { + async_test(function (t) { + t.step(function () { + t.done() + }) + }) +} +</script> diff --git a/testing/web-platform/tests/notifications/resources/custom-data.js b/testing/web-platform/tests/notifications/resources/custom-data.js new file mode 100644 index 0000000000..b21d28a1bb --- /dev/null +++ b/testing/web-platform/tests/notifications/resources/custom-data.js @@ -0,0 +1,66 @@ +var fakeCustomData = (function() { + var buffer = new ArrayBuffer(2); + 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, + set, + }; +})(); + +function assert_custom_data(dataObj) { + assert_equals(typeof dataObj, "object", "data should be a JS object"); + assert_equals( + JSON.stringify(dataObj.primitives), + JSON.stringify(fakeCustomData.primitives), + "data.primitives should be preserved" + ); + assert_equals( + dataObj.date.toDateString(), + fakeCustomData.date.toDateString(), + "data.date should be preserved" + ); + assert_equals( + dataObj.regexp.exec("http://www.domain.com")[0].substr(7), + "www", + "data.regexp should be preserved" + ); + assert_equals( + new Int16Array(dataObj.arrayBuffer)[0], + 42, + "data.arrayBuffer should be preserved" + ); + assert_equals( + JSON.stringify(dataObj.imageData.data), + JSON.stringify(fakeCustomData.imageData.data), + "data.imageData should be preserved" + ) + assert_equals( + dataObj.map.get("test"), + 42, + "data.map should be preserved" + ); + assert_true( + dataObj.set.has(4) && dataObj.set.has(2), + "data.set should be preserved" + ); +} diff --git a/testing/web-platform/tests/notifications/resources/icon.png b/testing/web-platform/tests/notifications/resources/icon.png Binary files differnew file mode 100644 index 0000000000..ee919cd512 --- /dev/null +++ b/testing/web-platform/tests/notifications/resources/icon.png diff --git a/testing/web-platform/tests/notifications/resources/shownotification-sw.js b/testing/web-platform/tests/notifications/resources/shownotification-sw.js new file mode 100644 index 0000000000..63a1569460 --- /dev/null +++ b/testing/web-platform/tests/notifications/resources/shownotification-sw.js @@ -0,0 +1,27 @@ +self.onmessage = event => { + // Checking for a particular value, so more tests can be added in future. + if (event.data !== 'test-shownotification') return; + + // Random number, so we can identify the notification we create. + const random = Math.random().toString(); + const start = Date.now(); + + event.waitUntil( + self.registration.showNotification('test', { + tag: random, + // ?pipe=trickle(d2) delays the icon request by two seconds + icon: 'icon.png?pipe=trickle(d2)' + }).then(() => { + const resolveDuration = Date.now() - start; + + return self.registration.getNotifications().then(notifications => { + event.source.postMessage({ + type: 'notification-data', + resolveDuration, + // Check if our notification is in notifications + notificationReturned: notifications.some(n => n.tag == random) + }); + }); + }) + ); +};
\ No newline at end of file diff --git a/testing/web-platform/tests/notifications/shownotification-resolve-manual.https.html b/testing/web-platform/tests/notifications/shownotification-resolve-manual.https.html new file mode 100644 index 0000000000..a73b11d100 --- /dev/null +++ b/testing/web-platform/tests/notifications/shownotification-resolve-manual.https.html @@ -0,0 +1,52 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<script> +const worker = 'resources/shownotification-sw.js'; + +function reset() { + return navigator.serviceWorker.getRegistrations().then(registrations => { + return Promise.all(registrations.map(r => r.unregister())); + }); +} + +function getNewestWorker(reg) { + return reg.installing || reg.waiting || reg.active; +} + +function registerSwAndGetWorker() { + return reset() + .then(() => navigator.serviceWorker.register(worker)) + .then(getNewestWorker); +} + +promise_test(() => { + // Get notification permission + return Notification.requestPermission().then(permission => { + if (permission != "granted") { + throw Error('You must allow notifications for this origin before running this test.'); + } + return registerSwAndGetWorker(); + }).then(worker => { + return new Promise(resolve => { + // Wait for the service worker to post a message with type 'notification-data'. + navigator.serviceWorker.onmessage = event => { + if (event.data && event.data.type == 'notification-data') { + resolve(event.data); + navigator.serviceWorker.onmessage = null; + } + }; + + // Ask the service worker to run the test. + worker.postMessage('test-shownotification'); + }) + }).then(result => { + assert_true(result.notificationReturned, `Notification appeared in getNotifications`); + // The icon is delayed by 2000ms, so showNotification should have taken at least 1900 to resolve. + assert_greater_than(result.resolveDuration, 1900, `showNotification appeared to wait for icon load`); + }); +}, 'showNotification resolves after icon fetch'); + +</script> +</body> diff --git a/testing/web-platform/tests/notifications/shownotification.https.window.js b/testing/web-platform/tests/notifications/shownotification.https.window.js new file mode 100644 index 0000000000..4def327181 --- /dev/null +++ b/testing/web-platform/tests/notifications/shownotification.https.window.js @@ -0,0 +1,106 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=resources/custom-data.js + +"use strict"; + +/** @type {ServiceWorkerRegistration} */ +let registration; + +function reset() { + return navigator.serviceWorker.getRegistrations().then(registrations => { + return Promise.all(registrations.map(r => r.unregister())); + }); +} + +async function registerSw() { + await reset(); + const reg = await navigator.serviceWorker.register("noop-sw.js"); + add_completion_callback(() => reg.unregister()); + await navigator.serviceWorker.ready; + return reg; +} + +async function cleanup() { + for (const n of await registration.getNotifications()) { + n.close(); + } +} + +promise_setup(async () => { + await test_driver.set_permission({ name: "notifications" }, "granted"); + registration = await registerSw(); +}); + +promise_test(async () => { + const notifications = await registration.getNotifications(); + assert_equals(notifications.length, 0, "Should return zero notification"); +}, "fetching no notifications"); + +promise_test(async t => { + t.add_cleanup(cleanup); + await registration.showNotification(""); + const notifications = await registration.getNotifications(); + assert_equals(notifications.length, 1, "Should return one notification"); + assert_equals(notifications[0].title, "", "Should return an empty title"); +}, "fetching notification with an empty title"); + +promise_test(async t => { + t.add_cleanup(cleanup); + await Promise.all([ + registration.showNotification("thunder", { tag: "fire" }), + registration.showNotification("bird", { tag: "fox" }), + registration.showNotification("supernova", { tag: "quantum" }), + ]); + const notifications = await registration.getNotifications({ tag: "quantum" }); + assert_equals( + notifications.length, + 1, + "Should return only the matching notification" + ); + assert_equals(notifications[0].title, "supernova", "title should match"); + assert_equals(notifications[0].tag, "quantum", "tag should match"); +}, "fetching notification by tag filter"); + +promise_test(async t => { + t.add_cleanup(cleanup); + await Promise.all([ + registration.showNotification("thunder"), + registration.showNotification("bird"), + registration.showNotification("supernova"), + ]); + const notifications = await registration.getNotifications(); + assert_equals(notifications.length, 3, "Should return three notifications"); +}, "fetching multiple notifications"); + +// https://notifications.spec.whatwg.org/#dom-serviceworkerregistration-getnotifications +// Step 5.2: Let notifications be a list of all notifications in the list of +// notifications ... whose service worker registration is this ... +promise_test(async t => { + t.add_cleanup(cleanup); + const another = await navigator.serviceWorker.register("noop-sw.js", { scope: "./scope" }); + await registration.showNotification("Hello"); + const notifications = await another.getNotifications(); + assert_equals(notifications.length, 0, "Should return no notification"); +}, "fetching from another registration") + +// https://notifications.spec.whatwg.org/#non-persistent-notification +// A non-persistent notification is a notification without an associated +// service worker registration. +promise_test(async t => { + t.add_cleanup(cleanup); + const nonPersistent = new Notification("Non-persistent"); + t.add_cleanup(() => nonPersistent.close()); + await registration.showNotification("Hello"); + const notifications = await registration.getNotifications(); + assert_equals(notifications.length, 1, "Should return a notification"); + assert_equals(notifications[0].title, "Hello", "Title should match"); +}, "fetching only persistent notifications") + +promise_test(async t => { + t.add_cleanup(cleanup); + await registration.showNotification("Hello", { data: fakeCustomData }); + const notifications = await registration.getNotifications(); + assert_equals(notifications.length, 1, "Should return a notification"); + assert_custom_data(notifications[0].data); +}, "fetching a notification with custom data") diff --git a/testing/web-platform/tests/notifications/tag-different-manual.https.html b/testing/web-platform/tests/notifications/tag-different-manual.https.html new file mode 100644 index 0000000000..e463e97670 --- /dev/null +++ b/testing/web-platform/tests/notifications/tag-different-manual.https.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Notification.tag (two tags with different values)</title> +<link rel="author" title="Intel" href="http://www.intel.com/"> +<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="common.js"></script> +<div id=passfail></div> +<script> +setup({ explicit_timeout: true }) +if (hasNotificationPermission()) { + async_test(function (t) { + t.step(function () { + var notification1 = null, + notification2 = null, + notifications = [], + text1 = "This is the body: Room 101", + text2 = "This is the body: Room 202" + createPassFail("If two notifications appear: First one with the" + + " text \"" + text1 + "\", followed by one with the text \"" + + text2 + "\"", + t, closeNotifications, notifications) + notification1 = new Notification("New Email Received", { + body: text1, + tag: "Tom" + }) + notification2 = new Notification("New Email Received", { + body: text2, + tag: "Rose" + }) + notifications.push(notification1) + notifications.push(notification2) + }) + }) +} +</script> diff --git a/testing/web-platform/tests/notifications/tag-same-manual.https.html b/testing/web-platform/tests/notifications/tag-same-manual.https.html new file mode 100644 index 0000000000..4454944c53 --- /dev/null +++ b/testing/web-platform/tests/notifications/tag-same-manual.https.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Notification.tag (two tags with same value)</title> +<link rel="author" title="Intel" href="http://www.intel.com/"> +<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="common.js"></script> +<div id=passfail></div> +<script> +setup({ explicit_timeout: true }) +if (hasNotificationPermission()) { + async_test(function (t) { + t.step(function () { + var notification1 = null, + notification2 = null, + notifications = [], + text1 = "This is the body: Room 101", + text2 = "This is the body: Room 202" + createPassFail("If a notification with the text \"" + + text2 + "\", replaces the notification with the text \"" + + text1 + "\" in the same position", + t, closeNotifications, notifications) + notification1 = new Notification("New Email Received", { + body: text1, + tag: "Tom" + }) + notification2 = new Notification("New Email Received", { + body: text2, + tag: "Tom" + }) + notifications.push(notification1) + notifications.push(notification2) + }) + }) +} +</script> |