summaryrefslogtreecommitdiffstats
path: root/toolkit/components/places/tests/unit/test_async_history_api.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/places/tests/unit/test_async_history_api.js')
-rw-r--r--toolkit/components/places/tests/unit/test_async_history_api.js1118
1 files changed, 0 insertions, 1118 deletions
diff --git a/toolkit/components/places/tests/unit/test_async_history_api.js b/toolkit/components/places/tests/unit/test_async_history_api.js
deleted file mode 100644
index a012fcda2..000000000
--- a/toolkit/components/places/tests/unit/test_async_history_api.js
+++ /dev/null
@@ -1,1118 +0,0 @@
-/**
- * This file tests the async history API exposed by mozIAsyncHistory.
- */
-
-// Globals
-
-const TEST_DOMAIN = "http://mozilla.org/";
-const URI_VISIT_SAVED = "uri-visit-saved";
-const RECENT_EVENT_THRESHOLD = 15 * 60 * 1000000;
-
-// Helpers
-/**
- * Object that represents a mozIVisitInfo object.
- *
- * @param [optional] aTransitionType
- * The transition type of the visit. Defaults to TRANSITION_LINK if not
- * provided.
- * @param [optional] aVisitTime
- * The time of the visit. Defaults to now if not provided.
- */
-function VisitInfo(aTransitionType,
- aVisitTime) {
- this.transitionType =
- aTransitionType === undefined ? TRANSITION_LINK : aTransitionType;
- this.visitDate = aVisitTime || Date.now() * 1000;
-}
-
-function promiseUpdatePlaces(aPlaces) {
- return new Promise((resolve, reject) => {
- PlacesUtils.asyncHistory.updatePlaces(aPlaces, {
- _errors: [],
- _results: [],
- handleError(aResultCode, aPlace) {
- this._errors.push({ resultCode: aResultCode, info: aPlace});
- },
- handleResult(aPlace) {
- this._results.push(aPlace);
- },
- handleCompletion() {
- resolve({ errors: this._errors, results: this._results });
- }
- });
- });
-}
-
-/**
- * Listens for a title change notification, and calls aCallback when it gets it.
- *
- * @param aURI
- * The URI of the page we expect a notification for.
- * @param aExpectedTitle
- * The expected title of the URI we expect a notification for.
- * @param aCallback
- * The method to call when we have gotten the proper notification about
- * the title changing.
- */
-function TitleChangedObserver(aURI,
- aExpectedTitle,
- aCallback) {
- this.uri = aURI;
- this.expectedTitle = aExpectedTitle;
- this.callback = aCallback;
-}
-TitleChangedObserver.prototype = {
- __proto__: NavHistoryObserver.prototype,
- onTitleChanged(aURI, aTitle, aGUID) {
- do_print("onTitleChanged(" + aURI.spec + ", " + aTitle + ", " + aGUID + ")");
- if (!this.uri.equals(aURI)) {
- return;
- }
- do_check_eq(aTitle, this.expectedTitle);
- do_check_guid_for_uri(aURI, aGUID);
- this.callback();
- },
-};
-
-/**
- * Listens for a visit notification, and calls aCallback when it gets it.
- *
- * @param aURI
- * The URI of the page we expect a notification for.
- * @param aCallback
- * The method to call when we have gotten the proper notification about
- * being visited.
- */
-function VisitObserver(aURI,
- aGUID,
- aCallback)
-{
- this.uri = aURI;
- this.guid = aGUID;
- this.callback = aCallback;
-}
-VisitObserver.prototype = {
- __proto__: NavHistoryObserver.prototype,
- onVisit: function(aURI,
- aVisitId,
- aTime,
- aSessionId,
- aReferringId,
- aTransitionType,
- aGUID)
- {
- do_print("onVisit(" + aURI.spec + ", " + aVisitId + ", " + aTime +
- ", " + aSessionId + ", " + aReferringId + ", " +
- aTransitionType + ", " + aGUID + ")");
- if (!this.uri.equals(aURI) || this.guid != aGUID) {
- return;
- }
- this.callback(aTime, aTransitionType);
- },
-};
-
-/**
- * Tests that a title was set properly in the database.
- *
- * @param aURI
- * The uri to check.
- * @param aTitle
- * The expected title in the database.
- */
-function do_check_title_for_uri(aURI,
- aTitle)
-{
- let stack = Components.stack.caller;
- let stmt = DBConn().createStatement(
- `SELECT title
- FROM moz_places
- WHERE url_hash = hash(:url) AND url = :url`
- );
- stmt.params.url = aURI.spec;
- do_check_true(stmt.executeStep(), stack);
- do_check_eq(stmt.row.title, aTitle, stack);
- stmt.finalize();
-}
-
-// Test Functions
-
-add_task(function* test_interface_exists() {
- let history = Cc["@mozilla.org/browser/history;1"].getService(Ci.nsISupports);
- do_check_true(history instanceof Ci.mozIAsyncHistory);
-});
-
-add_task(function* test_invalid_uri_throws() {
- // First, test passing in nothing.
- let place = {
- visits: [
- new VisitInfo(),
- ],
- };
- try {
- yield promiseUpdatePlaces(place);
- do_throw("Should have thrown!");
- }
- catch (e) {
- do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
- }
-
- // Now, test other bogus things.
- const TEST_VALUES = [
- null,
- undefined,
- {},
- [],
- TEST_DOMAIN + "test_invalid_id_throws",
- ];
- for (let i = 0; i < TEST_VALUES.length; i++) {
- place.uri = TEST_VALUES[i];
- try {
- yield promiseUpdatePlaces(place);
- do_throw("Should have thrown!");
- }
- catch (e) {
- do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
- }
- }
-});
-
-add_task(function* test_invalid_places_throws() {
- // First, test passing in nothing.
- try {
- PlacesUtils.asyncHistory.updatePlaces();
- do_throw("Should have thrown!");
- }
- catch (e) {
- do_check_eq(e.result, Cr.NS_ERROR_XPC_NOT_ENOUGH_ARGS);
- }
-
- // Now, test other bogus things.
- const TEST_VALUES = [
- null,
- undefined,
- {},
- [],
- "",
- ];
- for (let i = 0; i < TEST_VALUES.length; i++) {
- let value = TEST_VALUES[i];
- try {
- yield promiseUpdatePlaces(value);
- do_throw("Should have thrown!");
- }
- catch (e) {
- do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
- }
- }
-});
-
-add_task(function* test_invalid_guid_throws() {
- // First check invalid length guid.
- let place = {
- guid: "BAD_GUID",
- uri: NetUtil.newURI(TEST_DOMAIN + "test_invalid_guid_throws"),
- visits: [
- new VisitInfo(),
- ],
- };
- try {
- yield promiseUpdatePlaces(place);
- do_throw("Should have thrown!");
- }
- catch (e) {
- do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
- }
-
- // Now check invalid character guid.
- place.guid = "__BADGUID+__";
- do_check_eq(place.guid.length, 12);
- try {
- yield promiseUpdatePlaces(place);
- do_throw("Should have thrown!");
- }
- catch (e) {
- do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
- }
-});
-
-add_task(function* test_no_visits_throws() {
- const TEST_URI =
- NetUtil.newURI(TEST_DOMAIN + "test_no_id_or_guid_no_visits_throws");
- const TEST_GUID = "_RANDOMGUID_";
-
- let log_test_conditions = function(aPlace) {
- let str = "Testing place with " +
- (aPlace.uri ? "uri" : "no uri") + ", " +
- (aPlace.guid ? "guid" : "no guid") + ", " +
- (aPlace.visits ? "visits array" : "no visits array");
- do_print(str);
- };
-
- // Loop through every possible case. Note that we don't actually care about
- // the case where we have no uri, place id, or guid (covered by another test),
- // but it is easier to just make sure it too throws than to exclude it.
- let place = { };
- for (let uri = 1; uri >= 0; uri--) {
- place.uri = uri ? TEST_URI : undefined;
-
- for (let guid = 1; guid >= 0; guid--) {
- place.guid = guid ? TEST_GUID : undefined;
-
- for (let visits = 1; visits >= 0; visits--) {
- place.visits = visits ? [] : undefined;
-
- log_test_conditions(place);
- try {
- yield promiseUpdatePlaces(place);
- do_throw("Should have thrown!");
- }
- catch (e) {
- do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
- }
- }
- }
- }
-});
-
-add_task(function* test_add_visit_no_date_throws() {
- let place = {
- uri: NetUtil.newURI(TEST_DOMAIN + "test_add_visit_no_date_throws"),
- visits: [
- new VisitInfo(),
- ],
- };
- delete place.visits[0].visitDate;
- try {
- yield promiseUpdatePlaces(place);
- do_throw("Should have thrown!");
- }
- catch (e) {
- do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
- }
-});
-
-add_task(function* test_add_visit_no_transitionType_throws() {
- let place = {
- uri: NetUtil.newURI(TEST_DOMAIN + "test_add_visit_no_transitionType_throws"),
- visits: [
- new VisitInfo(),
- ],
- };
- delete place.visits[0].transitionType;
- try {
- yield promiseUpdatePlaces(place);
- do_throw("Should have thrown!");
- }
- catch (e) {
- do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
- }
-});
-
-add_task(function* test_add_visit_invalid_transitionType_throws() {
- // First, test something that has a transition type lower than the first one.
- let place = {
- uri: NetUtil.newURI(TEST_DOMAIN +
- "test_add_visit_invalid_transitionType_throws"),
- visits: [
- new VisitInfo(TRANSITION_LINK - 1),
- ],
- };
- try {
- yield promiseUpdatePlaces(place);
- do_throw("Should have thrown!");
- }
- catch (e) {
- do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
- }
-
- // Now, test something that has a transition type greater than the last one.
- place.visits[0] = new VisitInfo(TRANSITION_RELOAD + 1);
- try {
- yield promiseUpdatePlaces(place);
- do_throw("Should have thrown!");
- }
- catch (e) {
- do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
- }
-});
-
-add_task(function* test_non_addable_uri_errors() {
- // Array of protocols that nsINavHistoryService::canAddURI returns false for.
- const URLS = [
- "about:config",
- "imap://cyrus.andrew.cmu.edu/archive.imap",
- "news://new.mozilla.org/mozilla.dev.apps.firefox",
- "mailbox:Inbox",
- "moz-anno:favicon:http://mozilla.org/made-up-favicon",
- "view-source:http://mozilla.org",
- "chrome://browser/content/browser.xul",
- "resource://gre-resources/hiddenWindow.html",
- "data:,Hello%2C%20World!",
- "wyciwyg:/0/http://mozilla.org",
- "javascript:alert('hello wolrd!');",
- "blob:foo",
- ];
- let places = [];
- URLS.forEach(function(url) {
- try {
- let place = {
- uri: NetUtil.newURI(url),
- title: "test for " + url,
- visits: [
- new VisitInfo(),
- ],
- };
- places.push(place);
- }
- catch (e) {
- if (e.result != Cr.NS_ERROR_FAILURE) {
- throw e;
- }
- // NetUtil.newURI() can throw if e.g. our app knows about imap://
- // but the account is not set up and so the URL is invalid for us.
- // Note this in the log but ignore as it's not the subject of this test.
- do_print("Could not construct URI for '" + url + "'; ignoring");
- }
- });
-
- let placesResult = yield promiseUpdatePlaces(places);
- if (placesResult.results.length > 0) {
- do_throw("Unexpected success.");
- }
- for (let place of placesResult.errors) {
- do_print("Checking '" + place.info.uri.spec + "'");
- do_check_eq(place.resultCode, Cr.NS_ERROR_INVALID_ARG);
- do_check_false(yield promiseIsURIVisited(place.info.uri));
- }
- yield PlacesTestUtils.promiseAsyncUpdates();
-});
-
-add_task(function* test_duplicate_guid_errors() {
- // This test ensures that trying to add a visit, with a guid already found in
- // another visit, fails.
- let place = {
- uri: NetUtil.newURI(TEST_DOMAIN + "test_duplicate_guid_fails_first"),
- visits: [
- new VisitInfo(),
- ],
- };
-
- do_check_false(yield promiseIsURIVisited(place.uri));
- let placesResult = yield promiseUpdatePlaces(place);
- if (placesResult.errors.length > 0) {
- do_throw("Unexpected error.");
- }
- let placeInfo = placesResult.results[0];
- do_check_true(yield promiseIsURIVisited(placeInfo.uri));
-
- let badPlace = {
- uri: NetUtil.newURI(TEST_DOMAIN + "test_duplicate_guid_fails_second"),
- visits: [
- new VisitInfo(),
- ],
- guid: placeInfo.guid,
- };
-
- do_check_false(yield promiseIsURIVisited(badPlace.uri));
- placesResult = yield promiseUpdatePlaces(badPlace);
- if (placesResult.results.length > 0) {
- do_throw("Unexpected success.");
- }
- let badPlaceInfo = placesResult.errors[0];
- do_check_eq(badPlaceInfo.resultCode, Cr.NS_ERROR_STORAGE_CONSTRAINT);
- do_check_false(yield promiseIsURIVisited(badPlaceInfo.info.uri));
-
- yield PlacesTestUtils.promiseAsyncUpdates();
-});
-
-add_task(function* test_invalid_referrerURI_ignored() {
- let place = {
- uri: NetUtil.newURI(TEST_DOMAIN +
- "test_invalid_referrerURI_ignored"),
- visits: [
- new VisitInfo(),
- ],
- };
- place.visits[0].referrerURI = NetUtil.newURI(place.uri.spec + "_unvisistedURI");
- do_check_false(yield promiseIsURIVisited(place.uri));
- do_check_false(yield promiseIsURIVisited(place.visits[0].referrerURI));
-
- let placesResult = yield promiseUpdatePlaces(place);
- if (placesResult.errors.length > 0) {
- do_throw("Unexpected error.");
- }
- let placeInfo = placesResult.results[0];
- do_check_true(yield promiseIsURIVisited(placeInfo.uri));
-
- // Check to make sure we do not visit the invalid referrer.
- do_check_false(yield promiseIsURIVisited(place.visits[0].referrerURI));
-
- // Check to make sure from_visit is zero in database.
- let stmt = DBConn().createStatement(
- `SELECT from_visit
- FROM moz_historyvisits
- WHERE id = :visit_id`
- );
- stmt.params.visit_id = placeInfo.visits[0].visitId;
- do_check_true(stmt.executeStep());
- do_check_eq(stmt.row.from_visit, 0);
- stmt.finalize();
-
- yield PlacesTestUtils.promiseAsyncUpdates();
-});
-
-add_task(function* test_nonnsIURI_referrerURI_ignored() {
- let place = {
- uri: NetUtil.newURI(TEST_DOMAIN +
- "test_nonnsIURI_referrerURI_ignored"),
- visits: [
- new VisitInfo(),
- ],
- };
- place.visits[0].referrerURI = place.uri.spec + "_nonnsIURI";
- do_check_false(yield promiseIsURIVisited(place.uri));
-
- let placesResult = yield promiseUpdatePlaces(place);
- if (placesResult.errors.length > 0) {
- do_throw("Unexpected error.");
- }
- let placeInfo = placesResult.results[0];
- do_check_true(yield promiseIsURIVisited(placeInfo.uri));
-
- // Check to make sure from_visit is zero in database.
- let stmt = DBConn().createStatement(
- `SELECT from_visit
- FROM moz_historyvisits
- WHERE id = :visit_id`
- );
- stmt.params.visit_id = placeInfo.visits[0].visitId;
- do_check_true(stmt.executeStep());
- do_check_eq(stmt.row.from_visit, 0);
- stmt.finalize();
-
- yield PlacesTestUtils.promiseAsyncUpdates();
-});
-
-add_task(function* test_old_referrer_ignored() {
- // This tests that a referrer for a visit which is not recent (specifically,
- // older than 15 minutes as per RECENT_EVENT_THRESHOLD) is not saved by
- // updatePlaces.
- let oldTime = (Date.now() * 1000) - (RECENT_EVENT_THRESHOLD + 1);
- let referrerPlace = {
- uri: NetUtil.newURI(TEST_DOMAIN + "test_old_referrer_ignored_referrer"),
- visits: [
- new VisitInfo(TRANSITION_LINK, oldTime),
- ],
- };
-
- // First we must add our referrer to the history so that it is not ignored
- // as being invalid.
- do_check_false(yield promiseIsURIVisited(referrerPlace.uri));
- let placesResult = yield promiseUpdatePlaces(referrerPlace);
- if (placesResult.errors.length > 0) {
- do_throw("Unexpected error.");
- }
-
- // Now that the referrer is added, we can add a page with a valid
- // referrer to determine if the recency of the referrer is taken into
- // account.
- do_check_true(yield promiseIsURIVisited(referrerPlace.uri));
-
- let visitInfo = new VisitInfo();
- visitInfo.referrerURI = referrerPlace.uri;
- let place = {
- uri: NetUtil.newURI(TEST_DOMAIN + "test_old_referrer_ignored_page"),
- visits: [
- visitInfo,
- ],
- };
-
- do_check_false(yield promiseIsURIVisited(place.uri));
- placesResult = yield promiseUpdatePlaces(place);
- if (placesResult.errors.length > 0) {
- do_throw("Unexpected error.");
- }
- let placeInfo = placesResult.results[0];
- do_check_true(yield promiseIsURIVisited(place.uri));
-
- // Though the visit will not contain the referrer, we must examine the
- // database to be sure.
- do_check_eq(placeInfo.visits[0].referrerURI, null);
- let stmt = DBConn().createStatement(
- `SELECT COUNT(1) AS count
- FROM moz_historyvisits
- JOIN moz_places h ON h.id = place_id
- WHERE url_hash = hash(:page_url) AND url = :page_url
- AND from_visit = 0`
- );
- stmt.params.page_url = place.uri.spec;
- do_check_true(stmt.executeStep());
- do_check_eq(stmt.row.count, 1);
- stmt.finalize();
-
- yield PlacesTestUtils.promiseAsyncUpdates();
-});
-
-add_task(function* test_place_id_ignored() {
- let place = {
- uri: NetUtil.newURI(TEST_DOMAIN + "test_place_id_ignored_first"),
- visits: [
- new VisitInfo(),
- ],
- };
-
- do_check_false(yield promiseIsURIVisited(place.uri));
- let placesResult = yield promiseUpdatePlaces(place);
- if (placesResult.errors.length > 0) {
- do_throw("Unexpected error.");
- }
- let placeInfo = placesResult.results[0];
- do_check_true(yield promiseIsURIVisited(place.uri));
-
- let placeId = placeInfo.placeId;
- do_check_neq(placeId, 0);
-
- let badPlace = {
- uri: NetUtil.newURI(TEST_DOMAIN + "test_place_id_ignored_second"),
- visits: [
- new VisitInfo(),
- ],
- placeId: placeId,
- };
-
- do_check_false(yield promiseIsURIVisited(badPlace.uri));
- placesResult = yield promiseUpdatePlaces(badPlace);
- if (placesResult.errors.length > 0) {
- do_throw("Unexpected error.");
- }
- placeInfo = placesResult.results[0];
-
- do_check_neq(placeInfo.placeId, placeId);
- do_check_true(yield promiseIsURIVisited(badPlace.uri));
-
- yield PlacesTestUtils.promiseAsyncUpdates();
-});
-
-add_task(function* test_handleCompletion_called_when_complete() {
- // We test a normal visit, and embeded visit, and a uri that would fail
- // the canAddURI test to make sure that the notification happens after *all*
- // of them have had a callback.
- let places = [
- { uri: NetUtil.newURI(TEST_DOMAIN +
- "test_handleCompletion_called_when_complete"),
- visits: [
- new VisitInfo(),
- new VisitInfo(TRANSITION_EMBED),
- ],
- },
- { uri: NetUtil.newURI("data:,Hello%2C%20World!"),
- visits: [
- new VisitInfo(),
- ],
- },
- ];
- do_check_false(yield promiseIsURIVisited(places[0].uri));
- do_check_false(yield promiseIsURIVisited(places[1].uri));
-
- const EXPECTED_COUNT_SUCCESS = 2;
- const EXPECTED_COUNT_FAILURE = 1;
-
- let {results, errors} = yield promiseUpdatePlaces(places);
-
- do_check_eq(results.length, EXPECTED_COUNT_SUCCESS);
- do_check_eq(errors.length, EXPECTED_COUNT_FAILURE);
-
- yield PlacesTestUtils.promiseAsyncUpdates();
-});
-
-add_task(function* test_add_visit() {
- const VISIT_TIME = Date.now() * 1000;
- let place = {
- uri: NetUtil.newURI(TEST_DOMAIN + "test_add_visit"),
- title: "test_add_visit title",
- visits: [],
- };
- for (let t in PlacesUtils.history.TRANSITIONS) {
- let transitionType = PlacesUtils.history.TRANSITIONS[t];
- place.visits.push(new VisitInfo(transitionType, VISIT_TIME));
- }
- do_check_false(yield promiseIsURIVisited(place.uri));
-
- let callbackCount = 0;
- let placesResult = yield promiseUpdatePlaces(place);
- if (placesResult.errors.length > 0) {
- do_throw("Unexpected error.");
- }
- for (let placeInfo of placesResult.results) {
- do_check_true(yield promiseIsURIVisited(place.uri));
-
- // Check mozIPlaceInfo properties.
- do_check_true(place.uri.equals(placeInfo.uri));
- do_check_eq(placeInfo.frecency, -1); // We don't pass frecency here!
- do_check_eq(placeInfo.title, place.title);
-
- // Check mozIVisitInfo properties.
- let visits = placeInfo.visits;
- do_check_eq(visits.length, 1);
- let visit = visits[0];
- do_check_eq(visit.visitDate, VISIT_TIME);
- do_check_true(Object.values(PlacesUtils.history.TRANSITIONS).includes(visit.transitionType));
- do_check_true(visit.referrerURI === null);
-
- // For TRANSITION_EMBED visits, many properties will always be zero or
- // undefined.
- if (visit.transitionType == TRANSITION_EMBED) {
- // Check mozIPlaceInfo properties.
- do_check_eq(placeInfo.placeId, 0, '//');
- do_check_eq(placeInfo.guid, null);
-
- // Check mozIVisitInfo properties.
- do_check_eq(visit.visitId, 0);
- }
- // But they should be valid for non-embed visits.
- else {
- // Check mozIPlaceInfo properties.
- do_check_true(placeInfo.placeId > 0);
- do_check_valid_places_guid(placeInfo.guid);
-
- // Check mozIVisitInfo properties.
- do_check_true(visit.visitId > 0);
- }
-
- // If we have had all of our callbacks, continue running tests.
- if (++callbackCount == place.visits.length) {
- yield PlacesTestUtils.promiseAsyncUpdates();
- }
- }
-});
-
-add_task(function* test_properties_saved() {
- // Check each transition type to make sure it is saved properly.
- let places = [];
- for (let t in PlacesUtils.history.TRANSITIONS) {
- let transitionType = PlacesUtils.history.TRANSITIONS[t];
- let place = {
- uri: NetUtil.newURI(TEST_DOMAIN + "test_properties_saved/" +
- transitionType),
- title: "test_properties_saved test",
- visits: [
- new VisitInfo(transitionType),
- ],
- };
- do_check_false(yield promiseIsURIVisited(place.uri));
- places.push(place);
- }
-
- let callbackCount = 0;
- let placesResult = yield promiseUpdatePlaces(places);
- if (placesResult.errors.length > 0) {
- do_throw("Unexpected error.");
- }
- for (let placeInfo of placesResult.results) {
- let uri = placeInfo.uri;
- do_check_true(yield promiseIsURIVisited(uri));
- let visit = placeInfo.visits[0];
- print("TEST-INFO | test_properties_saved | updatePlaces callback for " +
- "transition type " + visit.transitionType);
-
- // Note that TRANSITION_EMBED should not be in the database.
- const EXPECTED_COUNT = visit.transitionType == TRANSITION_EMBED ? 0 : 1;
-
- // mozIVisitInfo::date
- let stmt = DBConn().createStatement(
- `SELECT COUNT(1) AS count
- FROM moz_places h
- JOIN moz_historyvisits v
- ON h.id = v.place_id
- WHERE h.url_hash = hash(:page_url) AND h.url = :page_url
- AND v.visit_date = :visit_date`
- );
- stmt.params.page_url = uri.spec;
- stmt.params.visit_date = visit.visitDate;
- do_check_true(stmt.executeStep());
- do_check_eq(stmt.row.count, EXPECTED_COUNT);
- stmt.finalize();
-
- // mozIVisitInfo::transitionType
- stmt = DBConn().createStatement(
- `SELECT COUNT(1) AS count
- FROM moz_places h
- JOIN moz_historyvisits v
- ON h.id = v.place_id
- WHERE h.url_hash = hash(:page_url) AND h.url = :page_url
- AND v.visit_type = :transition_type`
- );
- stmt.params.page_url = uri.spec;
- stmt.params.transition_type = visit.transitionType;
- do_check_true(stmt.executeStep());
- do_check_eq(stmt.row.count, EXPECTED_COUNT);
- stmt.finalize();
-
- // mozIPlaceInfo::title
- stmt = DBConn().createStatement(
- `SELECT COUNT(1) AS count
- FROM moz_places h
- WHERE h.url_hash = hash(:page_url) AND h.url = :page_url
- AND h.title = :title`
- );
- stmt.params.page_url = uri.spec;
- stmt.params.title = placeInfo.title;
- do_check_true(stmt.executeStep());
- do_check_eq(stmt.row.count, EXPECTED_COUNT);
- stmt.finalize();
-
- // If we have had all of our callbacks, continue running tests.
- if (++callbackCount == places.length) {
- yield PlacesTestUtils.promiseAsyncUpdates();
- }
- }
-});
-
-add_task(function* test_guid_saved() {
- let place = {
- uri: NetUtil.newURI(TEST_DOMAIN + "test_guid_saved"),
- guid: "__TESTGUID__",
- visits: [
- new VisitInfo(),
- ],
- };
- do_check_valid_places_guid(place.guid);
- do_check_false(yield promiseIsURIVisited(place.uri));
-
- let placesResult = yield promiseUpdatePlaces(place);
- if (placesResult.errors.length > 0) {
- do_throw("Unexpected error.");
- }
- let placeInfo = placesResult.results[0];
- let uri = placeInfo.uri;
- do_check_true(yield promiseIsURIVisited(uri));
- do_check_eq(placeInfo.guid, place.guid);
- do_check_guid_for_uri(uri, place.guid);
- yield PlacesTestUtils.promiseAsyncUpdates();
-});
-
-add_task(function* test_referrer_saved() {
- let places = [
- { uri: NetUtil.newURI(TEST_DOMAIN + "test_referrer_saved/referrer"),
- visits: [
- new VisitInfo(),
- ],
- },
- { uri: NetUtil.newURI(TEST_DOMAIN + "test_referrer_saved/test"),
- visits: [
- new VisitInfo(),
- ],
- },
- ];
- places[1].visits[0].referrerURI = places[0].uri;
- do_check_false(yield promiseIsURIVisited(places[0].uri));
- do_check_false(yield promiseIsURIVisited(places[1].uri));
-
- let resultCount = 0;
- let placesResult = yield promiseUpdatePlaces(places);
- if (placesResult.errors.length > 0) {
- do_throw("Unexpected error.");
- }
- for (let placeInfo of placesResult.results) {
- let uri = placeInfo.uri;
- do_check_true(yield promiseIsURIVisited(uri));
- let visit = placeInfo.visits[0];
-
- // We need to insert all of our visits before we can test conditions.
- if (++resultCount == places.length) {
- do_check_true(places[0].uri.equals(visit.referrerURI));
-
- let stmt = DBConn().createStatement(
- `SELECT COUNT(1) AS count
- FROM moz_historyvisits
- JOIN moz_places h ON h.id = place_id
- WHERE url_hash = hash(:page_url) AND url = :page_url
- AND from_visit = (
- SELECT v.id
- FROM moz_historyvisits v
- JOIN moz_places h ON h.id = place_id
- WHERE url_hash = hash(:referrer) AND url = :referrer
- )`
- );
- stmt.params.page_url = uri.spec;
- stmt.params.referrer = visit.referrerURI.spec;
- do_check_true(stmt.executeStep());
- do_check_eq(stmt.row.count, 1);
- stmt.finalize();
-
- yield PlacesTestUtils.promiseAsyncUpdates();
- }
- }
-});
-
-add_task(function* test_guid_change_saved() {
- // First, add a visit for it.
- let place = {
- uri: NetUtil.newURI(TEST_DOMAIN + "test_guid_change_saved"),
- visits: [
- new VisitInfo(),
- ],
- };
- do_check_false(yield promiseIsURIVisited(place.uri));
-
- let placesResult = yield promiseUpdatePlaces(place);
- if (placesResult.errors.length > 0) {
- do_throw("Unexpected error.");
- }
- // Then, change the guid with visits.
- place.guid = "_GUIDCHANGE_";
- place.visits = [new VisitInfo()];
- placesResult = yield promiseUpdatePlaces(place);
- if (placesResult.errors.length > 0) {
- do_throw("Unexpected error.");
- }
- do_check_guid_for_uri(place.uri, place.guid);
-
- yield PlacesTestUtils.promiseAsyncUpdates();
-});
-
-add_task(function* test_title_change_saved() {
- // First, add a visit for it.
- let place = {
- uri: NetUtil.newURI(TEST_DOMAIN + "test_title_change_saved"),
- title: "original title",
- visits: [
- new VisitInfo(),
- ],
- };
- do_check_false(yield promiseIsURIVisited(place.uri));
-
- let placesResult = yield promiseUpdatePlaces(place);
- if (placesResult.errors.length > 0) {
- do_throw("Unexpected error.");
- }
-
- // Now, make sure the empty string clears the title.
- place.title = "";
- place.visits = [new VisitInfo()];
- placesResult = yield promiseUpdatePlaces(place);
- if (placesResult.errors.length > 0) {
- do_throw("Unexpected error.");
- }
- do_check_title_for_uri(place.uri, null);
-
- // Then, change the title with visits.
- place.title = "title change";
- place.visits = [new VisitInfo()];
- placesResult = yield promiseUpdatePlaces(place);
- if (placesResult.errors.length > 0) {
- do_throw("Unexpected error.");
- }
- do_check_title_for_uri(place.uri, place.title);
-
- // Lastly, check that the title is cleared if we set it to null.
- place.title = null;
- place.visits = [new VisitInfo()];
- placesResult = yield promiseUpdatePlaces(place);
- if (placesResult.errors.length > 0) {
- do_throw("Unexpected error.");
- }
- do_check_title_for_uri(place.uri, place.title);
-
- yield PlacesTestUtils.promiseAsyncUpdates();
-});
-
-add_task(function* test_no_title_does_not_clear_title() {
- const TITLE = "test title";
- // First, add a visit for it.
- let place = {
- uri: NetUtil.newURI(TEST_DOMAIN + "test_no_title_does_not_clear_title"),
- title: TITLE,
- visits: [
- new VisitInfo(),
- ],
- };
- do_check_false(yield promiseIsURIVisited(place.uri));
-
- let placesResult = yield promiseUpdatePlaces(place);
- if (placesResult.errors.length > 0) {
- do_throw("Unexpected error.");
- }
- // Now, make sure that not specifying a title does not clear it.
- delete place.title;
- place.visits = [new VisitInfo()];
- placesResult = yield promiseUpdatePlaces(place);
- if (placesResult.errors.length > 0) {
- do_throw("Unexpected error.");
- }
- do_check_title_for_uri(place.uri, TITLE);
-
- yield PlacesTestUtils.promiseAsyncUpdates();
-});
-
-add_task(function* test_title_change_notifies() {
- // There are three cases to test. The first case is to make sure we do not
- // get notified if we do not specify a title.
- let place = {
- uri: NetUtil.newURI(TEST_DOMAIN + "test_title_change_notifies"),
- visits: [
- new VisitInfo(),
- ],
- };
- do_check_false(yield promiseIsURIVisited(place.uri));
-
- let silentObserver =
- new TitleChangedObserver(place.uri, "DO NOT WANT", function() {
- do_throw("unexpected callback!");
- });
-
- PlacesUtils.history.addObserver(silentObserver, false);
- let placesResult = yield promiseUpdatePlaces(place);
- if (placesResult.errors.length > 0) {
- do_throw("Unexpected error.");
- }
-
- // The second case to test is that we get the notification when we add
- // it for the first time. The first case will fail before our callback if it
- // is busted, so we can do this now.
- place.uri = NetUtil.newURI(place.uri.spec + "/new-visit-with-title");
- place.title = "title 1";
- function promiseTitleChangedObserver(aPlace) {
- return new Promise((resolve, reject) => {
- let callbackCount = 0;
- let observer = new TitleChangedObserver(aPlace.uri, aPlace.title, function() {
- switch (++callbackCount) {
- case 1:
- // The third case to test is to make sure we get a notification when
- // we change an existing place.
- observer.expectedTitle = place.title = "title 2";
- place.visits = [new VisitInfo()];
- PlacesUtils.asyncHistory.updatePlaces(place);
- break;
- case 2:
- PlacesUtils.history.removeObserver(silentObserver);
- PlacesUtils.history.removeObserver(observer);
- resolve();
- break;
- }
- });
-
- PlacesUtils.history.addObserver(observer, false);
- PlacesUtils.asyncHistory.updatePlaces(aPlace);
- });
- }
-
- yield promiseTitleChangedObserver(place);
- yield PlacesTestUtils.promiseAsyncUpdates();
-});
-
-add_task(function* test_visit_notifies() {
- // There are two observers we need to see for each visit. One is an
- // nsINavHistoryObserver and the other is the uri-visit-saved observer topic.
- let place = {
- guid: "abcdefghijkl",
- uri: NetUtil.newURI(TEST_DOMAIN + "test_visit_notifies"),
- visits: [
- new VisitInfo(),
- ],
- };
- do_check_false(yield promiseIsURIVisited(place.uri));
-
- function promiseVisitObserver(aPlace) {
- return new Promise((resolve, reject) => {
- let callbackCount = 0;
- let finisher = function() {
- if (++callbackCount == 2) {
- resolve();
- }
- }
- let visitObserver = new VisitObserver(place.uri, place.guid,
- function(aVisitDate,
- aTransitionType) {
- let visit = place.visits[0];
- do_check_eq(visit.visitDate, aVisitDate);
- do_check_eq(visit.transitionType, aTransitionType);
-
- PlacesUtils.history.removeObserver(visitObserver);
- finisher();
- });
- PlacesUtils.history.addObserver(visitObserver, false);
- let observer = function(aSubject, aTopic, aData) {
- do_print("observe(" + aSubject + ", " + aTopic + ", " + aData + ")");
- do_check_true(aSubject instanceof Ci.nsIURI);
- do_check_true(aSubject.equals(place.uri));
-
- Services.obs.removeObserver(observer, URI_VISIT_SAVED);
- finisher();
- };
- Services.obs.addObserver(observer, URI_VISIT_SAVED, false);
- PlacesUtils.asyncHistory.updatePlaces(place);
- });
- }
-
- yield promiseVisitObserver(place);
- yield PlacesTestUtils.promiseAsyncUpdates();
-});
-
-// test with empty mozIVisitInfoCallback object
-add_task(function* test_callbacks_not_supplied() {
- const URLS = [
- "imap://cyrus.andrew.cmu.edu/archive.imap", // bad URI
- "http://mozilla.org/" // valid URI
- ];
- let places = [];
- URLS.forEach(function(url) {
- try {
- let place = {
- uri: NetUtil.newURI(url),
- title: "test for " + url,
- visits: [
- new VisitInfo(),
- ],
- };
- places.push(place);
- }
- catch (e) {
- if (e.result != Cr.NS_ERROR_FAILURE) {
- throw e;
- }
- // NetUtil.newURI() can throw if e.g. our app knows about imap://
- // but the account is not set up and so the URL is invalid for us.
- // Note this in the log but ignore as it's not the subject of this test.
- do_print("Could not construct URI for '" + url + "'; ignoring");
- }
- });
-
- PlacesUtils.asyncHistory.updatePlaces(places, {});
- yield PlacesTestUtils.promiseAsyncUpdates();
-});
-
-// Test that we don't wrongly overwrite typed and hidden when adding new visits.
-add_task(function* test_typed_hidden_not_overwritten() {
- yield PlacesTestUtils.clearHistory();
- let places = [
- { uri: NetUtil.newURI("http://mozilla.org/"),
- title: "test",
- visits: [
- new VisitInfo(TRANSITION_TYPED),
- new VisitInfo(TRANSITION_LINK)
- ]
- },
- { uri: NetUtil.newURI("http://mozilla.org/"),
- title: "test",
- visits: [
- new VisitInfo(TRANSITION_FRAMED_LINK)
- ]
- },
- ];
- yield promiseUpdatePlaces(places);
-
- let db = yield PlacesUtils.promiseDBConnection();
- let rows = yield db.execute(
- "SELECT hidden, typed FROM moz_places WHERE url_hash = hash(:url) AND url = :url",
- { url: "http://mozilla.org/" });
- Assert.equal(rows[0].getResultByName("typed"), 1,
- "The page should be marked as typed");
- Assert.equal(rows[0].getResultByName("hidden"), 0,
- "The page should be marked as not hidden");
-});
-
-function run_test()
-{
- run_next_test();
-}