1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 const notifications = chrome.notifications;
7 const red_dot = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA" +
8 "AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO" +
9 "9TXL0Y4OHwAAAABJRU5ErkJggg==";
11 function createBigImageUrl() {
12 var canvas = document.createElement('canvas');
15 var ctx = canvas.getContext('2d');
16 ctx.fillStyle = "rgb(200, 0, 0)";
17 ctx.fillRect(10, 20, 30, 40);
19 return canvas.toDataURL();
22 var basicNotificationOptions = {
25 message: "Basic message",
29 function create(id, options) {
30 return new Promise(function (resolve, reject) {
31 notifications.create(id, options, function (id) {
32 if (chrome.runtime.lastError) {
33 reject(new Error("Unable to create notification"));
42 function update(id, options) {
43 return new Promise(function (resolve, reject) {
44 notifications.update(id, options, function (ok) {
45 if (chrome.runtime.lastError || !ok) {
46 reject(new Error("Unable to update notification"));
56 return new Promise(function (resolve, reject) {
57 notifications.clear(id, function (ok) {
58 if (chrome.runtime.lastError || !ok) {
59 reject(new Error("Unable to clear notification"));
69 return new Promise(function (resolve, reject) {
70 notifications.getAll(function (ids) {
71 if (chrome.runtime.lastError) {
72 reject(new Error(chrome.runtime.lastError.message));
76 if (ids === undefined) {
81 var id_list = Object.keys(ids);
88 return getAll().then(function (ids) {
89 var idPromises = ids.map(function (id) { return clear(id); });
90 return Promise.all(idPromises);
94 function succeedTest(testName) {
96 return clearAll().then(
97 function () { chrome.test.succeed(testName); },
99 console.log("Unknown error in clearAll: " +
100 JSON.stringify(arguments));
105 function failTest(testName) {
107 return clearAll().then(
108 function () { chrome.test.fail(testName); },
110 console.log("Unknown error in clearAll: " +
111 JSON.stringify(error.message));
116 function testIdUsage() {
117 var testName = "testIdUsage";
118 console.log("Starting testIdUsage.");
119 var succeed = succeedTest(testName);
120 var fail = failTest(testName);
122 var createNotification = function (idString) {
127 message: "Check out Cirque du Soleil"
130 return create(idString, options);
133 var updateNotification = function (idString) {
134 var options = { title: "!", message: "!" };
135 return update(idString, options);
138 // Should successfully create the notification
139 createNotification("foo")
141 .then(updateNotification)
143 // Next try to update a non-existent notification.
144 .then(function () { return updateNotification("foo2"); })
145 // And fail if it returns true.
147 // Next try to clear a non-existent notification.
148 .catch(function () { return clear("foo2"); })
150 // And finally clear the original notification.
151 .catch(function () { return clear("foo"); })
156 function testBaseFormat() {
157 var testName = "testBaseFormat";
158 console.log("Starting " + testName);
159 var succeed = succeedTest(testName);
160 var fail = failTest(testName);
162 var createNotificationWithout = function(toDelete) {
167 message: "Check out Cirque du Soleil",
168 contextMessage: "Foobar.",
170 eventTime: 123457896.12389,
171 expandedMessage: "This is a longer expanded message.",
175 for (var i = 0; i < toDelete.length; i++) {
176 delete options[toDelete[i]];
179 return create("", options);
182 // Construct some exclusion lists. The |createNotificationWithout| function
183 // starts with a complex notification and then deletes items in this list.
184 var basicNotification= [
190 var bareNotification = basicNotification.concat([
195 var basicNoType = basicNotification.concat(["type"]);
196 var basicNoIcon = basicNotification.concat(["iconUrl"]);
197 var basicNoTitle = basicNotification.concat(["title"]);
198 var basicNoMessage = basicNotification.concat(["message"]);
200 // Try creating a basic notification with just some of the fields.
201 createNotificationWithout(basicNotification)
202 // Try creating a basic notification with all possible fields.
203 .then(function () { return createNotificationWithout([]); })
204 // Try creating a basic notification with the minimum in fields.
205 .then(function () { return createNotificationWithout(bareNotification); })
206 // After this line we are checking to make sure that there is an error
207 // when notifications are created without the proper fields.
210 .then(function () { return createNotificationWithout(basicNoType) })
212 .catch(function () { return createNotificationWithout(basicNoIcon) })
213 // Error if no title.
214 .catch(function () { return createNotificationWithout(basicNoTitle) })
215 // Error if no message.
216 .catch(function () { return createNotificationWithout(basicNoMessage) })
217 .then(fail, succeed);
220 function testListItem() {
221 var testName = "testListItem";
222 console.log("Starting " + testName);
223 var succeed = succeedTest(testName);
224 var fail = failTest(testName);
226 var item = { title: "Item title.", message: "Item message." };
231 message: "Check out Cirque du Soleil",
232 contextMessage: "Foobar.",
234 eventTime: 123457896.12389,
235 items: [item, item, item, item, item],
238 create("id", options).then(succeed, fail);
241 function arrayEquals(a, b) {
242 if (a === b) return true;
243 if (a == null || b == null) return false;
244 if (a.length !== b.length) return false;
246 for (var i = 0; i < a.length; i++) {
247 if (a[i] !== b[i]) return false;
252 function testGetAll() {
253 var testName = "testGetAll";
254 console.log("Starting " + testName);
255 var succeed = succeedTest(testName);
256 var fail = failTest(testName);
257 var in_ids = ["a", "b", "c", "d"];
259 // First do a get all, make sure the list is empty.
261 .then(function (ids) {
262 chrome.test.assertEq(0, ids.length);
264 // Then create a bunch of notifications.
266 var newNotifications = in_ids.map(function (id) {
267 return create(id, basicNotificationOptions);
269 return Promise.all(newNotifications);
272 .then(function () { return getAll(); })
273 // Check that the right set of notifications is in the center.
274 .then(function (ids) {
275 chrome.test.assertEq(4, ids.length);
276 chrome.test.assertTrue(arrayEquals(ids, in_ids));
281 function testProgress() {
282 var testName = "testProgress";
283 console.log("Starting " + testName);
284 var succeed = succeedTest(testName);
285 var fail = failTest(testName);
286 var progressOptions = {
288 title: "Basic title",
289 message: "Basic message",
294 // First, create a basic progress notification.
295 create("progress", progressOptions)
296 // and update it to have a different progress level.
297 .then(function () { return update("progress", { progress: 60 }); })
298 // If either of the above failed, the test fails.
300 // Now the following parts should all cause an error:
301 // First update the progress to a low value, out-of-range
302 .then(function () { return update("progress", { progress: -10 }); })
303 // First update the progress to a high value, out-of-range
304 .then(fail, function () { return update("progress", { progress: 101 }); })
305 .then(function () { return clear("progress"); })
306 // Finally try to create a notification that has a progress value but not
308 .then(fail, function () {
309 progressOptions.type = "basic";
310 return create("progress", progressOptions);
311 }).then(fail, succeed);
314 function testLargeImage() {
315 var testName = "testLargeImage";
316 console.log("Starting " + testName);
317 var succeed = succeedTest(testName);
318 var fail = failTest(testName);
321 title: "Basic title",
322 message: "Basic message",
323 iconUrl: createBigImageUrl(),
325 create("largeImage", options).then(succeed, fail);
328 function testOptionalParameters() {
329 var testName = "testOptionalParameters";
330 var succeed = succeedTest(testName);
331 var fail = failTest(testName);
332 function createCallback(notificationId) {
333 new Promise(function() {
334 chrome.test.assertNoLastError();
335 chrome.test.assertEq("string", typeof notificationId);
336 // Optional callback - should run without problems
337 chrome.notifications.clear(notificationId);
338 // Note: The point of the previous line is to show that a callback can be
339 // optional. Because .clear is asynchronous, we have to be careful with
340 // calling .clear again. Since .clear is processed in order, calling
341 // clear() synchronously is okay.
342 // If this assumption does not hold and leaks to flaky tests, file a bug
343 // report and/or put the following call in a setTimeout call.
345 // The notification should not exist any more, so clear() should fail.
346 clear(notificationId).then(fail, succeed);
349 // .create should succeed even when notificationId is omitted.
350 chrome.notifications.create(basicNotificationOptions, createCallback);
353 chrome.test.runTests([
354 testIdUsage, testBaseFormat, testListItem, testGetAll, testProgress,
355 testLargeImage, testOptionalParameters