browser/metro/base/tests/mochitest/browser_downloads.js

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:73f81a90caa8
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* Any copyright is dedicated to the Public Domain.
4 http://creativecommons.org/publicdomain/zero/1.0/ */
5
6 "use strict";
7
8 /**
9 * Provides infrastructure for automated download components tests.
10 * (adapted from browser/component/downloads test's head.js)
11 */
12
13 ////////////////////////////////////////////////////////////////////////////////
14 //// Globals
15
16 XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
17 "resource://gre/modules/FileUtils.jsm");
18
19 const nsIDM = Ci.nsIDownloadManager;
20
21 ////////////////////////////////////////////////////////////////////////////////
22 // Test Helpers
23
24 var { spawn } = Task;
25
26 function equalStrings(){
27 let ref = ""+arguments[0];
28 for (let i=1; i<arguments.length; i++){
29 if (ref !== ""+arguments[i]) {
30 info("equalStrings failure: " + ref + " != " + arguments[i]);
31 return false
32 }
33 }
34 return true;
35 }
36
37 function equalNumbers(){
38 let ref = Number(arguments[0]);
39 for (let i=1; i<arguments.length; i++){
40 if (ref !== Number(arguments[i])) return false;
41 if (ref !== Number(arguments[i])) {
42 info("equalNumbers failure: " + ref + " != " + Number(arguments[i]));
43 return false
44 }
45 }
46 return true;
47 }
48
49 function getPromisedDbResult(aStatement) {
50 let dbConnection = MetroDownloadsView.manager.DBConnection;
51 let statement = ("string" == typeof aStatement) ?
52 dbConnection.createAsyncStatement(
53 aStatement
54 ) : aStatement;
55
56 let deferred = Promise.defer(),
57 resultRows = [],
58 err = null;
59 try {
60 statement.executeAsync({
61 handleResult: function(aResultSet) {
62 let row;
63 if(!aResultSet) {
64 return;
65 }
66 while ((row = aResultSet.getNextRow())){
67 resultRows.push(row);
68 }
69 },
70 handleError: function(aError) {
71 Cu.reportError(aError);
72 err = aError;
73 },
74 handleCompletion: function(){
75 if (err) {
76 deferred.reject(err);
77 } else {
78 deferred.resolve(resultRows);
79 }
80 }
81 });
82 } finally {
83 statement.finalize();
84 }
85 return deferred.promise;
86 }
87
88 let gTestTargetFile = FileUtils.getFile("TmpD", ["dm-ui-test.file"]);
89 gTestTargetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
90 registerCleanupFunction(function () {
91 gTestTargetFile.remove(false);
92 PanelUI.hide();
93 });
94
95 /**
96 * This object contains a property for each column in the downloads table.
97 */
98 let gDownloadRowTemplate = {
99 name: "test-download.txt",
100 source: "http://www.example.com/test-download.txt",
101 target: NetUtil.newURI(gTestTargetFile).spec,
102 startTime: 1180493839859230,
103 endTime: 1180493839859234,
104 state: nsIDM.DOWNLOAD_FINISHED,
105 currBytes: 0,
106 maxBytes: -1,
107 preferredAction: 0,
108 autoResume: 0
109 };
110
111 ////////////////////////////////////////////////////////////////////////////////
112 // Test Infrastructure
113
114 function test() {
115 runTests();
116 }
117
118 /////////////////////////////////////
119 // shared test setup
120 function resetDownloads(){
121 // clear out existing and any pending downloads in the db
122 // returns a promise
123
124 let promisedResult = getPromisedDbResult(
125 "DELETE FROM moz_downloads"
126 );
127 return promisedResult.then(function(aResult){
128 // // Reset any prefs that might have been changed.
129 // Services.prefs.clearUserPref("browser.download.panel.shown");
130
131 // Ensure that data is unloaded.
132 let dlMgr = MetroDownloadsView.manager;
133 let dlsToRemove = [];
134 // Clear all completed/cancelled downloads
135 dlMgr.cleanUp();
136 dlMgr.cleanUpPrivate();
137
138 // Queue up all active ones as well
139 for (let dlsEnum of [dlMgr.activeDownloads, dlMgr.activePrivateDownloads]) {
140 while (dlsEnum.hasMoreElements()) {
141 dlsToRemove.push(dlsEnum.next());
142 }
143 }
144 // Remove any queued up active downloads
145 dlsToRemove.forEach(function (dl) {
146 dl.remove();
147 });
148 });
149 }
150
151 function addDownloadRow(aDataRow) {
152 let deferredInsert = Promise.defer();
153 let dataRow = aDataRow;
154
155 let dm = Cc["@mozilla.org/download-manager;1"].getService(Ci.nsIDownloadManager);
156 let db = dm.DBConnection;
157
158 let columnNames = Object.keys(gDownloadRowTemplate).join(", ");
159 let parameterNames = Object.keys(gDownloadRowTemplate)
160 .map(function(n) ":" + n)
161 .join(", ");
162
163 let statement = db.createAsyncStatement(
164 "INSERT INTO moz_downloads (" + columnNames +
165 ", guid) VALUES(" + parameterNames + ", GENERATE_GUID())");
166
167 // Populate insert parameters from the provided data.
168 for (let columnName in gDownloadRowTemplate) {
169 if (!(columnName in dataRow)) {
170 // Update the provided row object with data from the global template,
171 // for columns whose value is not provided explicitly.
172 dataRow[columnName] = gDownloadRowTemplate[columnName];
173 }
174 statement.params[columnName] = dataRow[columnName];
175 }
176
177 // Run the statement asynchronously and wait.
178 let promisedDownloads = getPromisedDbResult(
179 statement
180 );
181 yield promisedDownloads.then(function(){
182 let newItemId = db.lastInsertRowID;
183 let download = dm.getDownload(newItemId);
184 deferredInsert.resolve(download);
185 });
186 }
187
188 function gen_addDownloadRows(aDataRows){
189 if (!aDataRows.length) {
190 yield null;
191 }
192
193 try {
194 // Add each of the provided downloads in reverse.
195 for (let i = aDataRows.length - 1; i >= 0; i--) {
196 let dataRow = aDataRows[i];
197 let download = yield addDownloadRow(dataRow);
198
199 // At each iteration, ensure that the start and end time in the global
200 // template is distinct, as these column are used to sort each download
201 // in its category.
202 gDownloadRowTemplate.startTime++;
203 gDownloadRowTemplate.endTime++;
204 }
205 } finally {
206 info("gen_addDownloadRows, finally");
207 }
208 }
209
210 /////////////////////////////////////
211 // Test implementations
212
213 gTests.push({
214 desc: "zero downloads",
215 run: function () {
216 yield resetDownloads();
217 todo(false, "Test there are no visible notifications with an empty db.");
218 }
219 });
220
221 /**
222 * Make sure the downloads panel can display items in the right order and
223 * contains the expected data.
224 */
225 gTests.push({
226 desc: "Show downloads",
227 run: function(){
228 // Display one of each download state.
229 let DownloadData = [
230 { endTime: 1180493839859239, state: nsIDM.DOWNLOAD_NOTSTARTED },
231 { endTime: 1180493839859238, state: nsIDM.DOWNLOAD_DOWNLOADING },
232 { endTime: 1180493839859237, state: nsIDM.DOWNLOAD_PAUSED },
233 { endTime: 1180493839859236, state: nsIDM.DOWNLOAD_SCANNING },
234 { endTime: 1180493839859235, state: nsIDM.DOWNLOAD_QUEUED },
235 { endTime: 1180493839859234, state: nsIDM.DOWNLOAD_FINISHED },
236 { endTime: 1180493839859233, state: nsIDM.DOWNLOAD_FAILED },
237 { endTime: 1180493839859232, state: nsIDM.DOWNLOAD_CANCELED },
238 { endTime: 1180493839859231, state: nsIDM.DOWNLOAD_BLOCKED_PARENTAL },
239 { endTime: 1180493839859230, state: nsIDM.DOWNLOAD_DIRTY },
240 { endTime: 1180493839859229, state: nsIDM.DOWNLOAD_BLOCKED_POLICY }
241 ];
242
243 yield resetDownloads();
244
245 try {
246 // Populate the downloads database with the data required by this test.
247 // we're going to add stuff to the downloads db.
248 yield spawn( gen_addDownloadRows( DownloadData ) );
249
250 todo( false, "Check that MetroDownloadsView._progressNotificationInfo and MetroDownloadsView._downloadCount \
251 have the correct length (DownloadData.length) \
252 May also test that the correct notifications show up for various states.");
253
254 todo(false, "Iterate through download objects in MetroDownloadsView._progressNotificationInfo \
255 and confirm that the downloads they refer to are the same as those in \
256 DownloadData.");
257 } catch(e) {
258 info("Show downloads, some error: " + e);
259 }
260 finally {
261 // Clean up when the test finishes.
262 yield resetDownloads();
263 }
264 }
265 });
266
267 /**
268 * Make sure the downloads can be removed with the expected result on the notifications
269 */
270 gTests.push({
271 desc: "Remove downloads",
272 run: function(){
273 // Push a few items into the downloads db.
274 let DownloadData = [
275 { endTime: 1180493839859239, state: nsIDM.DOWNLOAD_FINISHED },
276 { endTime: 1180493839859238, state: nsIDM.DOWNLOAD_FINISHED },
277 { endTime: 1180493839859237, state: nsIDM.DOWNLOAD_FINISHED }
278 ];
279
280 yield resetDownloads();
281
282 try {
283 // Populate the downloads database with the data required by this test.
284 yield spawn( gen_addDownloadRows( DownloadData ) );
285
286 let downloadRows = null,
287 promisedDownloads;
288 // get all the downloads from the db
289 promisedDownloads = getPromisedDbResult(
290 "SELECT guid "
291 + "FROM moz_downloads "
292 + "ORDER BY startTime DESC"
293 ).then(function(aRows){
294 downloadRows = aRows;
295 }, function(aError){
296 throw aError;
297 });
298 yield promisedDownloads;
299
300 is(downloadRows.length, 3, "Correct number of downloads in the db before removal");
301
302 todo(false, "Get some download from MetroDownloadsView._progressNotificationInfo, \
303 confirm that its file exists, then remove it.");
304
305 // remove is async(?), wait a bit
306 yield waitForMs(0);
307
308 // get all the downloads from the db
309 downloadRows = null;
310 promisedDownloads = getPromisedDbResult(
311 "SELECT guid "
312 + "FROM moz_downloads "
313 + "ORDER BY startTime DESC"
314 ).then(function(aRows){
315 downloadRows = aRows;
316 }, function(aError){
317 throw aError;
318 });
319 yield promisedDownloads;
320
321 todo(false, "confirm that the removed download is no longer in the database \
322 and its file no longer exists.");
323
324 } catch(e) {
325 info("Remove downloads, some error: " + e);
326 }
327 finally {
328 // Clean up when the test finishes.
329 yield resetDownloads();
330 }
331 }
332 });
333
334 /**
335 * Make sure the cancelled/aborted downloads are handled correctly.
336 */
337 gTests.push({
338 desc: "Cancel/Abort Downloads",
339 run: function(){
340 todo(false, "Ensure that a cancelled/aborted download is in the correct state \
341 including correct values for state variables (e.g. _downloadCount, _downloadsInProgress) \
342 and the existence of the downloaded file.");
343 }
344 });
345
346 /**
347 * Make sure download notifications are moved when we close tabs.
348 */
349 gTests.push({
350 desc: "Download notifications in closed tabs",
351 setUp: function() {
352 // put up a couple notifications on the initial tab
353 let notificationBox = Browser.getNotificationBox();
354 notificationBox.appendNotification("not important", "low-priority-thing", "", notificationBox.PRIORITY_INFO_LOW, []);
355 notificationBox.appendNotification("so important", "high-priority-thing", "", notificationBox.PRIORITY_CRITICAL_HIGH, []);
356
357 // open a new tab where we'll conduct the test
358 yield addTab("about:mozilla");
359 },
360 run: function(){
361 let notificationBox = Browser.getNotificationBox();
362 let notn = MetroDownloadsView.showNotification("download-progress", "test message", [],
363 notificationBox.PRIORITY_WARNING_LOW);
364 Browser.closeTab(Browser.selectedTab);
365
366 yield waitForEvent(Elements.tabList, "TabRemove");
367
368 // expected behavior when a tab is closed while a download notification is showing:
369 // * the notification remains visible as long as a next tab/browser exists
370 // * normal rules about priority apply
371 // * notifications - including any pre-existing ones - display in expected order
372 let nextBox = Browser.getNotificationBox();
373 let currentNotification;
374
375 ok(nextBox.getNotificationWithValue("download-progress"), "notification was moved to next tab");
376
377 currentNotification = nextBox.currentNotification;
378 is(currentNotification.value, "high-priority-thing", "high priority notification is current");
379 currentNotification.close();
380
381 currentNotification = nextBox.currentNotification;
382 is(currentNotification.value, "download-progress", "download notification is next");
383 currentNotification.close();
384
385 currentNotification = nextBox.currentNotification;
386 is(currentNotification.value, "low-priority-thing", "low priority notification is next");
387 currentNotification.close();
388 }
389 });

mercurial