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

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial