browser/base/content/test/general/browser_sanitizeDialog_treeView.js

Wed, 31 Dec 2014 06:55:46 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:46 +0100
changeset 1
ca08bd8f51b2
permissions
-rw-r--r--

Added tag TORBROWSER_REPLICA for changeset 6474c204b198

michael@0 1 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim:set ts=2 sw=2 sts=2 et: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 /**
michael@0 8 * Tests the sanitize dialog (a.k.a. the clear recent history dialog).
michael@0 9 * See bug 480169.
michael@0 10 *
michael@0 11 * The purpose of this test is not to fully flex the sanitize timespan code;
michael@0 12 * browser/base/content/test/general/browser_sanitize-timespans.js does that. This
michael@0 13 * test checks the UI of the dialog and makes sure it's correctly connected to
michael@0 14 * the sanitize timespan code.
michael@0 15 *
michael@0 16 * Some of this code, especially the history creation parts, was taken from
michael@0 17 * browser/base/content/test/general/browser_sanitize-timespans.js.
michael@0 18 */
michael@0 19
michael@0 20 Cc["@mozilla.org/moz/jssubscript-loader;1"].
michael@0 21 getService(Ci.mozIJSSubScriptLoader).
michael@0 22 loadSubScript("chrome://browser/content/sanitize.js");
michael@0 23
michael@0 24 const dm = Cc["@mozilla.org/download-manager;1"].
michael@0 25 getService(Ci.nsIDownloadManager);
michael@0 26 const formhist = Cc["@mozilla.org/satchel/form-history;1"].
michael@0 27 getService(Ci.nsIFormHistory2);
michael@0 28
michael@0 29 // Add tests here. Each is a function that's called by doNextTest().
michael@0 30 var gAllTests = [
michael@0 31
michael@0 32 /**
michael@0 33 * Moves the grippy around, makes sure it works OK.
michael@0 34 */
michael@0 35 function () {
michael@0 36 // Add history (within the past hour) to get some rows in the tree.
michael@0 37 let uris = [];
michael@0 38 let places = [];
michael@0 39 let pURI;
michael@0 40 for (let i = 0; i < 30; i++) {
michael@0 41 pURI = makeURI("http://" + i + "-minutes-ago.com/");
michael@0 42 places.push({uri: pURI, visitDate: visitTimeForMinutesAgo(i)});
michael@0 43 uris.push(pURI);
michael@0 44 }
michael@0 45
michael@0 46 addVisits(places, function() {
michael@0 47 // Open the dialog and do our tests.
michael@0 48 openWindow(function (aWin) {
michael@0 49 let wh = new WindowHelper(aWin);
michael@0 50 wh.selectDuration(Sanitizer.TIMESPAN_HOUR);
michael@0 51 wh.checkGrippy("Grippy should be at last row after selecting HOUR " +
michael@0 52 "duration",
michael@0 53 wh.getRowCount() - 1);
michael@0 54
michael@0 55 // Move the grippy around.
michael@0 56 let row = wh.getGrippyRow();
michael@0 57 while (row !== 0) {
michael@0 58 row--;
michael@0 59 wh.moveGrippyBy(-1);
michael@0 60 wh.checkGrippy("Grippy should be moved up one row", row);
michael@0 61 }
michael@0 62 wh.moveGrippyBy(-1);
michael@0 63 wh.checkGrippy("Grippy should remain at first row after trying to move " +
michael@0 64 "it up",
michael@0 65 0);
michael@0 66 while (row !== wh.getRowCount() - 1) {
michael@0 67 row++;
michael@0 68 wh.moveGrippyBy(1);
michael@0 69 wh.checkGrippy("Grippy should be moved down one row", row);
michael@0 70 }
michael@0 71 wh.moveGrippyBy(1);
michael@0 72 wh.checkGrippy("Grippy should remain at last row after trying to move " +
michael@0 73 "it down",
michael@0 74 wh.getRowCount() - 1);
michael@0 75
michael@0 76 // Cancel the dialog, make sure history visits are not cleared.
michael@0 77 wh.checkPrefCheckbox("history", false);
michael@0 78
michael@0 79 wh.cancelDialog();
michael@0 80 yield promiseHistoryClearedState(uris, false);
michael@0 81
michael@0 82 // OK, done, cleanup after ourselves.
michael@0 83 blankSlate();
michael@0 84 yield promiseHistoryClearedState(uris, true);
michael@0 85 });
michael@0 86 });
michael@0 87 },
michael@0 88
michael@0 89 /**
michael@0 90 * Ensures that the combined history-downloads checkbox clears both history
michael@0 91 * visits and downloads when checked; the dialog respects simple timespan.
michael@0 92 */
michael@0 93 function () {
michael@0 94 // Add history (within the past hour).
michael@0 95 let uris = [];
michael@0 96 let places = [];
michael@0 97 let pURI;
michael@0 98 for (let i = 0; i < 30; i++) {
michael@0 99 pURI = makeURI("http://" + i + "-minutes-ago.com/");
michael@0 100 places.push({uri: pURI, visitDate: visitTimeForMinutesAgo(i)});
michael@0 101 uris.push(pURI);
michael@0 102 }
michael@0 103 // Add history (over an hour ago).
michael@0 104 let olderURIs = [];
michael@0 105 for (let i = 0; i < 5; i++) {
michael@0 106 pURI = makeURI("http://" + (60 + i) + "-minutes-ago.com/");
michael@0 107 places.push({uri: pURI, visitDate: visitTimeForMinutesAgo(60 + i)});
michael@0 108 olderURIs.push(pURI);
michael@0 109 }
michael@0 110
michael@0 111 addVisits(places, function() {
michael@0 112 // Add downloads (within the past hour).
michael@0 113 let downloadIDs = [];
michael@0 114 for (let i = 0; i < 5; i++) {
michael@0 115 downloadIDs.push(addDownloadWithMinutesAgo(i));
michael@0 116 }
michael@0 117 // Add downloads (over an hour ago).
michael@0 118 let olderDownloadIDs = [];
michael@0 119 for (let i = 0; i < 5; i++) {
michael@0 120 olderDownloadIDs.push(addDownloadWithMinutesAgo(61 + i));
michael@0 121 }
michael@0 122 let totalHistoryVisits = uris.length + olderURIs.length;
michael@0 123
michael@0 124 // Open the dialog and do our tests.
michael@0 125 openWindow(function (aWin) {
michael@0 126 let wh = new WindowHelper(aWin);
michael@0 127 wh.selectDuration(Sanitizer.TIMESPAN_HOUR);
michael@0 128 wh.checkGrippy("Grippy should be at proper row after selecting HOUR " +
michael@0 129 "duration",
michael@0 130 uris.length);
michael@0 131
michael@0 132 // Accept the dialog, make sure history visits and downloads within one
michael@0 133 // hour are cleared.
michael@0 134 wh.checkPrefCheckbox("history", true);
michael@0 135 wh.acceptDialog();
michael@0 136 yield promiseHistoryClearedState(uris, true);
michael@0 137 ensureDownloadsClearedState(downloadIDs, true);
michael@0 138
michael@0 139 // Make sure visits and downloads > 1 hour still exist.
michael@0 140 yield promiseHistoryClearedState(olderURIs, false);
michael@0 141 ensureDownloadsClearedState(olderDownloadIDs, false);
michael@0 142
michael@0 143 // OK, done, cleanup after ourselves.
michael@0 144 blankSlate();
michael@0 145 yield promiseHistoryClearedState(olderURIs, true);
michael@0 146 ensureDownloadsClearedState(olderDownloadIDs, true);
michael@0 147 });
michael@0 148 });
michael@0 149 },
michael@0 150
michael@0 151 /**
michael@0 152 * Ensures that the combined history-downloads checkbox removes neither
michael@0 153 * history visits nor downloads when not checked.
michael@0 154 */
michael@0 155 function () {
michael@0 156 // Add history, downloads, form entries (within the past hour).
michael@0 157 let uris = [];
michael@0 158 let places = [];
michael@0 159 let pURI;
michael@0 160 for (let i = 0; i < 5; i++) {
michael@0 161 pURI = makeURI("http://" + i + "-minutes-ago.com/");
michael@0 162 places.push({uri: pURI, visitDate: visitTimeForMinutesAgo(i)});
michael@0 163 uris.push(pURI);
michael@0 164 }
michael@0 165
michael@0 166 addVisits(places, function() {
michael@0 167 let downloadIDs = [];
michael@0 168 for (let i = 0; i < 5; i++) {
michael@0 169 downloadIDs.push(addDownloadWithMinutesAgo(i));
michael@0 170 }
michael@0 171 let formEntries = [];
michael@0 172 for (let i = 0; i < 5; i++) {
michael@0 173 formEntries.push(addFormEntryWithMinutesAgo(i));
michael@0 174 }
michael@0 175
michael@0 176 // Open the dialog and do our tests.
michael@0 177 openWindow(function (aWin) {
michael@0 178 let wh = new WindowHelper(aWin);
michael@0 179 wh.selectDuration(Sanitizer.TIMESPAN_HOUR);
michael@0 180 wh.checkGrippy("Grippy should be at last row after selecting HOUR " +
michael@0 181 "duration",
michael@0 182 wh.getRowCount() - 1);
michael@0 183
michael@0 184 // Remove only form entries, leave history (including downloads).
michael@0 185 wh.checkPrefCheckbox("history", false);
michael@0 186 wh.checkPrefCheckbox("formdata", true);
michael@0 187 wh.acceptDialog();
michael@0 188
michael@0 189 // Of the three only form entries should be cleared.
michael@0 190 yield promiseHistoryClearedState(uris, false);
michael@0 191 ensureDownloadsClearedState(downloadIDs, false);
michael@0 192 ensureFormEntriesClearedState(formEntries, true);
michael@0 193
michael@0 194 // OK, done, cleanup after ourselves.
michael@0 195 blankSlate();
michael@0 196 yield promiseHistoryClearedState(uris, true);
michael@0 197 ensureDownloadsClearedState(downloadIDs, true);
michael@0 198 });
michael@0 199 });
michael@0 200 },
michael@0 201
michael@0 202 /**
michael@0 203 * Ensures that the "Everything" duration option works.
michael@0 204 */
michael@0 205 function () {
michael@0 206 // Add history.
michael@0 207 let uris = [];
michael@0 208 let places = [];
michael@0 209 let pURI;
michael@0 210 // within past hour, within past two hours, within past four hours and
michael@0 211 // outside past four hours
michael@0 212 [10, 70, 130, 250].forEach(function(aValue) {
michael@0 213 pURI = makeURI("http://" + aValue + "-minutes-ago.com/");
michael@0 214 places.push({uri: pURI, visitDate: visitTimeForMinutesAgo(aValue)});
michael@0 215 uris.push(pURI);
michael@0 216 });
michael@0 217 addVisits(places, function() {
michael@0 218
michael@0 219 // Open the dialog and do our tests.
michael@0 220 openWindow(function (aWin) {
michael@0 221 let wh = new WindowHelper(aWin);
michael@0 222 wh.selectDuration(Sanitizer.TIMESPAN_EVERYTHING);
michael@0 223 wh.checkPrefCheckbox("history", true);
michael@0 224 wh.acceptDialog();
michael@0 225 yield promiseHistoryClearedState(uris, true);
michael@0 226 });
michael@0 227 });
michael@0 228 }
michael@0 229 ];
michael@0 230
michael@0 231 // Used as the download database ID for a new download. Incremented for each
michael@0 232 // new download. See addDownloadWithMinutesAgo().
michael@0 233 var gDownloadId = 5555551;
michael@0 234
michael@0 235 // Index in gAllTests of the test currently being run. Incremented for each
michael@0 236 // test run. See doNextTest().
michael@0 237 var gCurrTest = 0;
michael@0 238
michael@0 239 var now_uSec = Date.now() * 1000;
michael@0 240
michael@0 241 ///////////////////////////////////////////////////////////////////////////////
michael@0 242
michael@0 243 /**
michael@0 244 * This wraps the dialog and provides some convenience methods for interacting
michael@0 245 * with it.
michael@0 246 *
michael@0 247 * A warning: Before you call any function that uses the tree (or any function
michael@0 248 * that calls a function that uses the tree), you must set a non-everything
michael@0 249 * duration by calling selectDuration(). The dialog does not initialize the
michael@0 250 * tree if it does not yet need to be shown.
michael@0 251 *
michael@0 252 * @param aWin
michael@0 253 * The dialog's nsIDOMWindow
michael@0 254 */
michael@0 255 function WindowHelper(aWin) {
michael@0 256 this.win = aWin;
michael@0 257 }
michael@0 258
michael@0 259 WindowHelper.prototype = {
michael@0 260 /**
michael@0 261 * "Presses" the dialog's OK button.
michael@0 262 */
michael@0 263 acceptDialog: function () {
michael@0 264 is(this.win.document.documentElement.getButton("accept").disabled, false,
michael@0 265 "Dialog's OK button should not be disabled");
michael@0 266 this.win.document.documentElement.acceptDialog();
michael@0 267 },
michael@0 268
michael@0 269 /**
michael@0 270 * "Presses" the dialog's Cancel button.
michael@0 271 */
michael@0 272 cancelDialog: function () {
michael@0 273 this.win.document.documentElement.cancelDialog();
michael@0 274 },
michael@0 275
michael@0 276 /**
michael@0 277 * Ensures that the grippy row is in the right place, tree selection is OK,
michael@0 278 * and that the grippy's visible.
michael@0 279 *
michael@0 280 * @param aMsg
michael@0 281 * Passed to is() when checking grippy location
michael@0 282 * @param aExpectedRow
michael@0 283 * The row that the grippy should be at
michael@0 284 */
michael@0 285 checkGrippy: function (aMsg, aExpectedRow) {
michael@0 286 is(this.getGrippyRow(), aExpectedRow, aMsg);
michael@0 287 this.checkTreeSelection();
michael@0 288 this.ensureGrippyIsVisible();
michael@0 289 },
michael@0 290
michael@0 291 /**
michael@0 292 * (Un)checks a history scope checkbox (browser & download history,
michael@0 293 * form history, etc.).
michael@0 294 *
michael@0 295 * @param aPrefName
michael@0 296 * The final portion of the checkbox's privacy.cpd.* preference name
michael@0 297 * @param aCheckState
michael@0 298 * True if the checkbox should be checked, false otherwise
michael@0 299 */
michael@0 300 checkPrefCheckbox: function (aPrefName, aCheckState) {
michael@0 301 var pref = "privacy.cpd." + aPrefName;
michael@0 302 var cb = this.win.document.querySelectorAll(
michael@0 303 "#itemList > [preference='" + pref + "']");
michael@0 304 is(cb.length, 1, "found checkbox for " + pref + " preference");
michael@0 305 if (cb[0].checked != aCheckState)
michael@0 306 cb[0].click();
michael@0 307 },
michael@0 308
michael@0 309 /**
michael@0 310 * Ensures that the tree selection is appropriate to the grippy row. (A
michael@0 311 * single, contiguous selection should exist from the first row all the way
michael@0 312 * to the grippy.)
michael@0 313 */
michael@0 314 checkTreeSelection: function () {
michael@0 315 let grippyRow = this.getGrippyRow();
michael@0 316 let sel = this.getTree().view.selection;
michael@0 317 if (grippyRow === 0) {
michael@0 318 is(sel.getRangeCount(), 0,
michael@0 319 "Grippy row is 0, so no tree selection should exist");
michael@0 320 }
michael@0 321 else {
michael@0 322 is(sel.getRangeCount(), 1,
michael@0 323 "Grippy row > 0, so only one tree selection range should exist");
michael@0 324 let min = {};
michael@0 325 let max = {};
michael@0 326 sel.getRangeAt(0, min, max);
michael@0 327 is(min.value, 0, "Tree selection should start at first row");
michael@0 328 is(max.value, grippyRow - 1,
michael@0 329 "Tree selection should end at row before grippy");
michael@0 330 }
michael@0 331 },
michael@0 332
michael@0 333 /**
michael@0 334 * The grippy should always be visible when it's moved directly. This method
michael@0 335 * ensures that.
michael@0 336 */
michael@0 337 ensureGrippyIsVisible: function () {
michael@0 338 let tbo = this.getTree().treeBoxObject;
michael@0 339 let firstVis = tbo.getFirstVisibleRow();
michael@0 340 let lastVis = tbo.getLastVisibleRow();
michael@0 341 let grippyRow = this.getGrippyRow();
michael@0 342 ok(firstVis <= grippyRow && grippyRow <= lastVis,
michael@0 343 "Grippy row should be visible; this inequality should be true: " +
michael@0 344 firstVis + " <= " + grippyRow + " <= " + lastVis);
michael@0 345 },
michael@0 346
michael@0 347 /**
michael@0 348 * @return The dialog's duration dropdown
michael@0 349 */
michael@0 350 getDurationDropdown: function () {
michael@0 351 return this.win.document.getElementById("sanitizeDurationChoice");
michael@0 352 },
michael@0 353
michael@0 354 /**
michael@0 355 * @return The grippy row index
michael@0 356 */
michael@0 357 getGrippyRow: function () {
michael@0 358 return this.win.gContiguousSelectionTreeHelper.getGrippyRow();
michael@0 359 },
michael@0 360
michael@0 361 /**
michael@0 362 * @return The tree's row count (includes the grippy row)
michael@0 363 */
michael@0 364 getRowCount: function () {
michael@0 365 return this.getTree().view.rowCount;
michael@0 366 },
michael@0 367
michael@0 368 /**
michael@0 369 * @return The tree
michael@0 370 */
michael@0 371 getTree: function () {
michael@0 372 return this.win.gContiguousSelectionTreeHelper.tree;
michael@0 373 },
michael@0 374
michael@0 375 /**
michael@0 376 * @return True if the "Everything" warning panel is visible (as opposed to
michael@0 377 * the tree)
michael@0 378 */
michael@0 379 isWarningPanelVisible: function () {
michael@0 380 return this.win.document.getElementById("durationDeck").selectedIndex == 1;
michael@0 381 },
michael@0 382
michael@0 383 /**
michael@0 384 * @return True if the tree is visible (as opposed to the warning panel)
michael@0 385 */
michael@0 386 isTreeVisible: function () {
michael@0 387 return this.win.document.getElementById("durationDeck").selectedIndex == 0;
michael@0 388 },
michael@0 389
michael@0 390 /**
michael@0 391 * Moves the grippy one row at a time in the direction and magnitude specified.
michael@0 392 * If aDelta < 0, moves the grippy up; if aDelta > 0, moves it down.
michael@0 393 *
michael@0 394 * @param aDelta
michael@0 395 * The amount and direction to move
michael@0 396 */
michael@0 397 moveGrippyBy: function (aDelta) {
michael@0 398 if (aDelta === 0)
michael@0 399 return;
michael@0 400 let key = aDelta < 0 ? "UP" : "DOWN";
michael@0 401 let abs = Math.abs(aDelta);
michael@0 402 let treechildren = this.getTree().treeBoxObject.treeBody;
michael@0 403 treechildren.focus();
michael@0 404 for (let i = 0; i < abs; i++) {
michael@0 405 EventUtils.sendKey(key);
michael@0 406 }
michael@0 407 },
michael@0 408
michael@0 409 /**
michael@0 410 * Selects a duration in the duration dropdown.
michael@0 411 *
michael@0 412 * @param aDurVal
michael@0 413 * One of the Sanitizer.TIMESPAN_* values
michael@0 414 */
michael@0 415 selectDuration: function (aDurVal) {
michael@0 416 this.getDurationDropdown().value = aDurVal;
michael@0 417 if (aDurVal === Sanitizer.TIMESPAN_EVERYTHING) {
michael@0 418 is(this.isTreeVisible(), false,
michael@0 419 "Tree should not be visible for TIMESPAN_EVERYTHING");
michael@0 420 is(this.isWarningPanelVisible(), true,
michael@0 421 "Warning panel should be visible for TIMESPAN_EVERYTHING");
michael@0 422 }
michael@0 423 else {
michael@0 424 is(this.isTreeVisible(), true,
michael@0 425 "Tree should be visible for non-TIMESPAN_EVERYTHING");
michael@0 426 is(this.isWarningPanelVisible(), false,
michael@0 427 "Warning panel should not be visible for non-TIMESPAN_EVERYTHING");
michael@0 428 }
michael@0 429 }
michael@0 430 };
michael@0 431
michael@0 432 /**
michael@0 433 * Adds a download to history.
michael@0 434 *
michael@0 435 * @param aMinutesAgo
michael@0 436 * The download will be downloaded this many minutes ago
michael@0 437 */
michael@0 438 function addDownloadWithMinutesAgo(aMinutesAgo) {
michael@0 439 let name = "fakefile-" + aMinutesAgo + "-minutes-ago";
michael@0 440 let data = {
michael@0 441 id: gDownloadId,
michael@0 442 name: name,
michael@0 443 source: "https://bugzilla.mozilla.org/show_bug.cgi?id=480169",
michael@0 444 target: name,
michael@0 445 startTime: now_uSec - (aMinutesAgo * 60 * 1000000),
michael@0 446 endTime: now_uSec - ((aMinutesAgo + 1) *60 * 1000000),
michael@0 447 state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
michael@0 448 currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0,
michael@0 449 guid: "a1bcD23eF4g5"
michael@0 450 };
michael@0 451
michael@0 452 let db = dm.DBConnection;
michael@0 453 let stmt = db.createStatement(
michael@0 454 "INSERT INTO moz_downloads (id, name, source, target, startTime, endTime, " +
michael@0 455 "state, currBytes, maxBytes, preferredAction, autoResume, guid) " +
michael@0 456 "VALUES (:id, :name, :source, :target, :startTime, :endTime, :state, " +
michael@0 457 ":currBytes, :maxBytes, :preferredAction, :autoResume, :guid)");
michael@0 458 try {
michael@0 459 for (let prop in data) {
michael@0 460 stmt.params[prop] = data[prop];
michael@0 461 }
michael@0 462 stmt.execute();
michael@0 463 }
michael@0 464 finally {
michael@0 465 stmt.reset();
michael@0 466 }
michael@0 467
michael@0 468 is(downloadExists(gDownloadId), true,
michael@0 469 "Sanity check: download " + gDownloadId +
michael@0 470 " should exist after creating it");
michael@0 471
michael@0 472 return gDownloadId++;
michael@0 473 }
michael@0 474
michael@0 475 /**
michael@0 476 * Adds a form entry to history.
michael@0 477 *
michael@0 478 * @param aMinutesAgo
michael@0 479 * The entry will be added this many minutes ago
michael@0 480 */
michael@0 481 function addFormEntryWithMinutesAgo(aMinutesAgo) {
michael@0 482 let name = aMinutesAgo + "-minutes-ago";
michael@0 483 formhist.addEntry(name, "dummy");
michael@0 484
michael@0 485 // Artifically age the entry to the proper vintage.
michael@0 486 let db = formhist.DBConnection;
michael@0 487 let timestamp = now_uSec - (aMinutesAgo * 60 * 1000000);
michael@0 488 db.executeSimpleSQL("UPDATE moz_formhistory SET firstUsed = " +
michael@0 489 timestamp + " WHERE fieldname = '" + name + "'");
michael@0 490
michael@0 491 is(formhist.nameExists(name), true,
michael@0 492 "Sanity check: form entry " + name + " should exist after creating it");
michael@0 493 return name;
michael@0 494 }
michael@0 495
michael@0 496 /**
michael@0 497 * Removes all history visits, downloads, and form entries.
michael@0 498 */
michael@0 499 function blankSlate() {
michael@0 500 PlacesUtils.bhistory.removeAllPages();
michael@0 501 dm.cleanUp();
michael@0 502 formhist.removeAllEntries();
michael@0 503 }
michael@0 504
michael@0 505 /**
michael@0 506 * Checks to see if the download with the specified ID exists.
michael@0 507 *
michael@0 508 * @param aID
michael@0 509 * The ID of the download to check
michael@0 510 * @return True if the download exists, false otherwise
michael@0 511 */
michael@0 512 function downloadExists(aID)
michael@0 513 {
michael@0 514 let db = dm.DBConnection;
michael@0 515 let stmt = db.createStatement(
michael@0 516 "SELECT * " +
michael@0 517 "FROM moz_downloads " +
michael@0 518 "WHERE id = :id"
michael@0 519 );
michael@0 520 stmt.params.id = aID;
michael@0 521 let rows = stmt.executeStep();
michael@0 522 stmt.finalize();
michael@0 523 return !!rows;
michael@0 524 }
michael@0 525
michael@0 526 /**
michael@0 527 * Runs the next test in the gAllTests array. If all tests have been run,
michael@0 528 * finishes the entire suite.
michael@0 529 */
michael@0 530 function doNextTest() {
michael@0 531 if (gAllTests.length <= gCurrTest) {
michael@0 532 blankSlate();
michael@0 533 waitForAsyncUpdates(finish);
michael@0 534 }
michael@0 535 else {
michael@0 536 let ct = gCurrTest;
michael@0 537 gCurrTest++;
michael@0 538 gAllTests[ct]();
michael@0 539 }
michael@0 540 }
michael@0 541
michael@0 542 /**
michael@0 543 * Ensures that the specified downloads are either cleared or not.
michael@0 544 *
michael@0 545 * @param aDownloadIDs
michael@0 546 * Array of download database IDs
michael@0 547 * @param aShouldBeCleared
michael@0 548 * True if each download should be cleared, false otherwise
michael@0 549 */
michael@0 550 function ensureDownloadsClearedState(aDownloadIDs, aShouldBeCleared) {
michael@0 551 let niceStr = aShouldBeCleared ? "no longer" : "still";
michael@0 552 aDownloadIDs.forEach(function (id) {
michael@0 553 is(downloadExists(id), !aShouldBeCleared,
michael@0 554 "download " + id + " should " + niceStr + " exist");
michael@0 555 });
michael@0 556 }
michael@0 557
michael@0 558 /**
michael@0 559 * Ensures that the specified form entries are either cleared or not.
michael@0 560 *
michael@0 561 * @param aFormEntries
michael@0 562 * Array of form entry names
michael@0 563 * @param aShouldBeCleared
michael@0 564 * True if each form entry should be cleared, false otherwise
michael@0 565 */
michael@0 566 function ensureFormEntriesClearedState(aFormEntries, aShouldBeCleared) {
michael@0 567 let niceStr = aShouldBeCleared ? "no longer" : "still";
michael@0 568 aFormEntries.forEach(function (entry) {
michael@0 569 is(formhist.nameExists(entry), !aShouldBeCleared,
michael@0 570 "form entry " + entry + " should " + niceStr + " exist");
michael@0 571 });
michael@0 572 }
michael@0 573
michael@0 574 /**
michael@0 575 * Opens the sanitize dialog and runs a callback once it's finished loading.
michael@0 576 *
michael@0 577 * @param aOnloadCallback
michael@0 578 * A function that will be called once the dialog has loaded
michael@0 579 */
michael@0 580 function openWindow(aOnloadCallback) {
michael@0 581 function windowObserver(aSubject, aTopic, aData) {
michael@0 582 if (aTopic != "domwindowopened")
michael@0 583 return;
michael@0 584
michael@0 585 Services.ww.unregisterNotification(windowObserver);
michael@0 586 let win = aSubject.QueryInterface(Ci.nsIDOMWindow);
michael@0 587 win.addEventListener("load", function onload(event) {
michael@0 588 win.removeEventListener("load", onload, false);
michael@0 589 executeSoon(function () {
michael@0 590 // Some exceptions that reach here don't reach the test harness, but
michael@0 591 // ok()/is() do...
michael@0 592 try {
michael@0 593 Task.spawn(function() {
michael@0 594 aOnloadCallback(win);
michael@0 595 }).then(function() {
michael@0 596 waitForAsyncUpdates(doNextTest);
michael@0 597 });
michael@0 598 }
michael@0 599 catch (exc) {
michael@0 600 win.close();
michael@0 601 ok(false, "Unexpected exception: " + exc + "\n" + exc.stack);
michael@0 602 finish();
michael@0 603 }
michael@0 604 });
michael@0 605 }, false);
michael@0 606 }
michael@0 607 Services.ww.registerNotification(windowObserver);
michael@0 608 Services.ww.openWindow(null,
michael@0 609 "chrome://browser/content/sanitize.xul",
michael@0 610 "Sanitize",
michael@0 611 "chrome,titlebar,dialog,centerscreen,modal",
michael@0 612 null);
michael@0 613 }
michael@0 614
michael@0 615 /**
michael@0 616 * Creates a visit time.
michael@0 617 *
michael@0 618 * @param aMinutesAgo
michael@0 619 * The visit will be visited this many minutes ago
michael@0 620 */
michael@0 621 function visitTimeForMinutesAgo(aMinutesAgo) {
michael@0 622 return now_uSec - (aMinutesAgo * 60 * 1000000);
michael@0 623 }
michael@0 624
michael@0 625 ///////////////////////////////////////////////////////////////////////////////
michael@0 626
michael@0 627 function test() {
michael@0 628 blankSlate();
michael@0 629 waitForExplicitFinish();
michael@0 630 // Kick off all the tests in the gAllTests array.
michael@0 631 waitForAsyncUpdates(doNextTest);
michael@0 632 }

mercurial