summaryrefslogtreecommitdiffstats
path: root/toolkit/components/places/tests/bookmarks/test_keywords.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/places/tests/bookmarks/test_keywords.js')
-rw-r--r--toolkit/components/places/tests/bookmarks/test_keywords.js310
1 files changed, 310 insertions, 0 deletions
diff --git a/toolkit/components/places/tests/bookmarks/test_keywords.js b/toolkit/components/places/tests/bookmarks/test_keywords.js
new file mode 100644
index 000000000..149d6d0b0
--- /dev/null
+++ b/toolkit/components/places/tests/bookmarks/test_keywords.js
@@ -0,0 +1,310 @@
+const URI1 = NetUtil.newURI("http://test1.mozilla.org/");
+const URI2 = NetUtil.newURI("http://test2.mozilla.org/");
+const URI3 = NetUtil.newURI("http://test3.mozilla.org/");
+
+function check_keyword(aURI, aKeyword) {
+ if (aKeyword)
+ aKeyword = aKeyword.toLowerCase();
+
+ for (let bm of PlacesUtils.getBookmarksForURI(aURI)) {
+ let keyword = PlacesUtils.bookmarks.getKeywordForBookmark(bm);
+ if (keyword && !aKeyword) {
+ throw (`${aURI.spec} should not have a keyword`);
+ } else if (aKeyword && keyword == aKeyword) {
+ Assert.equal(keyword, aKeyword);
+ }
+ }
+
+ if (aKeyword) {
+ let uri = PlacesUtils.bookmarks.getURIForKeyword(aKeyword);
+ Assert.equal(uri.spec, aURI.spec);
+ // Check case insensitivity.
+ uri = PlacesUtils.bookmarks.getURIForKeyword(aKeyword.toUpperCase());
+ Assert.equal(uri.spec, aURI.spec);
+ }
+}
+
+function* check_orphans() {
+ let db = yield PlacesUtils.promiseDBConnection();
+ let rows = yield db.executeCached(
+ `SELECT id FROM moz_keywords k
+ WHERE NOT EXISTS (SELECT 1 FROM moz_places WHERE id = k.place_id)
+ `);
+ Assert.equal(rows.length, 0);
+}
+
+function expectNotifications() {
+ let notifications = [];
+ let observer = new Proxy(NavBookmarkObserver, {
+ get(target, name) {
+ if (name == "check") {
+ PlacesUtils.bookmarks.removeObserver(observer);
+ return expectedNotifications =>
+ Assert.deepEqual(notifications, expectedNotifications);
+ }
+
+ if (name.startsWith("onItemChanged")) {
+ return function(id, prop, isAnno, val, lastMod, itemType, parentId, guid, parentGuid, oldVal) {
+ if (prop != "keyword")
+ return;
+ let args = Array.from(arguments, arg => {
+ if (arg && arg instanceof Ci.nsIURI)
+ return new URL(arg.spec);
+ if (arg && typeof(arg) == "number" && arg >= Date.now() * 1000)
+ return new Date(parseInt(arg/1000));
+ return arg;
+ });
+ notifications.push({ name: name, arguments: args });
+ }
+ }
+
+ return target[name];
+ }
+ });
+ PlacesUtils.bookmarks.addObserver(observer, false);
+ return observer;
+}
+
+add_task(function test_invalid_input() {
+ Assert.throws(() => PlacesUtils.bookmarks.getURIForKeyword(null),
+ /NS_ERROR_ILLEGAL_VALUE/);
+ Assert.throws(() => PlacesUtils.bookmarks.getURIForKeyword(""),
+ /NS_ERROR_ILLEGAL_VALUE/);
+ Assert.throws(() => PlacesUtils.bookmarks.getKeywordForBookmark(null),
+ /NS_ERROR_ILLEGAL_VALUE/);
+ Assert.throws(() => PlacesUtils.bookmarks.getKeywordForBookmark(0),
+ /NS_ERROR_ILLEGAL_VALUE/);
+ Assert.throws(() => PlacesUtils.bookmarks.setKeywordForBookmark(null, "k"),
+ /NS_ERROR_ILLEGAL_VALUE/);
+ Assert.throws(() => PlacesUtils.bookmarks.setKeywordForBookmark(0, "k"),
+ /NS_ERROR_ILLEGAL_VALUE/);
+});
+
+add_task(function* test_addBookmarkAndKeyword() {
+ check_keyword(URI1, null);
+ let fc = yield foreign_count(URI1);
+ let observer = expectNotifications();
+
+ let itemId =
+ PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
+ URI1,
+ PlacesUtils.bookmarks.DEFAULT_INDEX,
+ "test");
+
+ PlacesUtils.bookmarks.setKeywordForBookmark(itemId, "keyword");
+ let bookmark = yield PlacesUtils.bookmarks.fetch({ url: URI1 });
+ observer.check([ { name: "onItemChanged",
+ arguments: [ itemId, "keyword", false, "keyword",
+ bookmark.lastModified, bookmark.type,
+ (yield PlacesUtils.promiseItemId(bookmark.parentGuid)),
+ bookmark.guid, bookmark.parentGuid, "",
+ Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
+ ]);
+ yield PlacesTestUtils.promiseAsyncUpdates();
+
+ check_keyword(URI1, "keyword");
+ Assert.equal((yield foreign_count(URI1)), fc + 2); // + 1 bookmark + 1 keyword
+
+ yield PlacesTestUtils.promiseAsyncUpdates();
+ yield check_orphans();
+});
+
+add_task(function* test_addBookmarkToURIHavingKeyword() {
+ // The uri has already a keyword.
+ check_keyword(URI1, "keyword");
+ let fc = yield foreign_count(URI1);
+
+ let itemId =
+ PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
+ URI1,
+ PlacesUtils.bookmarks.DEFAULT_INDEX,
+ "test");
+ check_keyword(URI1, "keyword");
+ Assert.equal((yield foreign_count(URI1)), fc + 1); // + 1 bookmark
+
+ PlacesUtils.bookmarks.removeItem(itemId);
+ yield PlacesTestUtils.promiseAsyncUpdates();
+ check_orphans();
+});
+
+add_task(function* test_sameKeywordDifferentURI() {
+ let fc1 = yield foreign_count(URI1);
+ let fc2 = yield foreign_count(URI2);
+ let observer = expectNotifications();
+
+ let itemId =
+ PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
+ URI2,
+ PlacesUtils.bookmarks.DEFAULT_INDEX,
+ "test2");
+ check_keyword(URI1, "keyword");
+ check_keyword(URI2, null);
+
+ PlacesUtils.bookmarks.setKeywordForBookmark(itemId, "kEyWoRd");
+
+ let bookmark1 = yield PlacesUtils.bookmarks.fetch({ url: URI1 });
+ let bookmark2 = yield PlacesUtils.bookmarks.fetch({ url: URI2 });
+ observer.check([ { name: "onItemChanged",
+ arguments: [ (yield PlacesUtils.promiseItemId(bookmark1.guid)),
+ "keyword", false, "",
+ bookmark1.lastModified, bookmark1.type,
+ (yield PlacesUtils.promiseItemId(bookmark1.parentGuid)),
+ bookmark1.guid, bookmark1.parentGuid, "",
+ Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
+ { name: "onItemChanged",
+ arguments: [ itemId, "keyword", false, "keyword",
+ bookmark2.lastModified, bookmark2.type,
+ (yield PlacesUtils.promiseItemId(bookmark2.parentGuid)),
+ bookmark2.guid, bookmark2.parentGuid, "",
+ Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
+ ]);
+ yield PlacesTestUtils.promiseAsyncUpdates();
+
+ // The keyword should have been "moved" to the new URI.
+ check_keyword(URI1, null);
+ Assert.equal((yield foreign_count(URI1)), fc1 - 1); // - 1 keyword
+ check_keyword(URI2, "keyword");
+ Assert.equal((yield foreign_count(URI2)), fc2 + 2); // + 1 bookmark + 1 keyword
+
+ yield PlacesTestUtils.promiseAsyncUpdates();
+ check_orphans();
+});
+
+add_task(function* test_sameURIDifferentKeyword() {
+ let fc = yield foreign_count(URI2);
+ let observer = expectNotifications();
+
+ let itemId =
+ PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
+ URI2,
+ PlacesUtils.bookmarks.DEFAULT_INDEX,
+ "test2");
+ check_keyword(URI2, "keyword");
+
+ PlacesUtils.bookmarks.setKeywordForBookmark(itemId, "keyword2");
+
+ let bookmarks = [];
+ yield PlacesUtils.bookmarks.fetch({ url: URI2 }, bookmark => bookmarks.push(bookmark));
+ observer.check([ { name: "onItemChanged",
+ arguments: [ (yield PlacesUtils.promiseItemId(bookmarks[0].guid)),
+ "keyword", false, "keyword2",
+ bookmarks[0].lastModified, bookmarks[0].type,
+ (yield PlacesUtils.promiseItemId(bookmarks[0].parentGuid)),
+ bookmarks[0].guid, bookmarks[0].parentGuid, "",
+ Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
+ { name: "onItemChanged",
+ arguments: [ (yield PlacesUtils.promiseItemId(bookmarks[1].guid)),
+ "keyword", false, "keyword2",
+ bookmarks[1].lastModified, bookmarks[1].type,
+ (yield PlacesUtils.promiseItemId(bookmarks[1].parentGuid)),
+ bookmarks[1].guid, bookmarks[1].parentGuid, "",
+ Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
+ ]);
+ yield PlacesTestUtils.promiseAsyncUpdates();
+
+ check_keyword(URI2, "keyword2");
+ Assert.equal((yield foreign_count(URI2)), fc + 2); // + 1 bookmark + 1 keyword
+
+ yield PlacesTestUtils.promiseAsyncUpdates();
+ check_orphans();
+});
+
+add_task(function* test_removeBookmarkWithKeyword() {
+ let fc = yield foreign_count(URI2);
+ let itemId =
+ PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
+ URI2,
+ PlacesUtils.bookmarks.DEFAULT_INDEX,
+ "test");
+
+ // The keyword should not be removed, since there are other bookmarks yet.
+ PlacesUtils.bookmarks.removeItem(itemId);
+
+ check_keyword(URI2, "keyword2");
+ Assert.equal((yield foreign_count(URI2)), fc); // + 1 bookmark - 1 bookmark
+
+ yield PlacesTestUtils.promiseAsyncUpdates();
+ check_orphans();
+});
+
+add_task(function* test_unsetKeyword() {
+ let fc = yield foreign_count(URI2);
+ let observer = expectNotifications();
+
+ let itemId =
+ PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
+ URI2,
+ PlacesUtils.bookmarks.DEFAULT_INDEX,
+ "test");
+
+ // The keyword should be removed from any bookmark.
+ PlacesUtils.bookmarks.setKeywordForBookmark(itemId, null);
+
+ let bookmarks = [];
+ yield PlacesUtils.bookmarks.fetch({ url: URI2 }, bookmark => bookmarks.push(bookmark));
+ do_print(bookmarks.length);
+ observer.check([ { name: "onItemChanged",
+ arguments: [ (yield PlacesUtils.promiseItemId(bookmarks[0].guid)),
+ "keyword", false, "",
+ bookmarks[0].lastModified, bookmarks[0].type,
+ (yield PlacesUtils.promiseItemId(bookmarks[0].parentGuid)),
+ bookmarks[0].guid, bookmarks[0].parentGuid, "",
+ Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
+ { name: "onItemChanged",
+ arguments: [ (yield PlacesUtils.promiseItemId(bookmarks[1].guid)),
+ "keyword", false, "",
+ bookmarks[1].lastModified, bookmarks[1].type,
+ (yield PlacesUtils.promiseItemId(bookmarks[1].parentGuid)),
+ bookmarks[1].guid, bookmarks[1].parentGuid, "",
+ Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
+ { name: "onItemChanged",
+ arguments: [ (yield PlacesUtils.promiseItemId(bookmarks[2].guid)),
+ "keyword", false, "",
+ bookmarks[2].lastModified, bookmarks[2].type,
+ (yield PlacesUtils.promiseItemId(bookmarks[2].parentGuid)),
+ bookmarks[2].guid, bookmarks[2].parentGuid, "",
+ Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
+ ]);
+
+ check_keyword(URI1, null);
+ check_keyword(URI2, null);
+ Assert.equal((yield foreign_count(URI2)), fc - 1); // + 1 bookmark - 2 keyword
+
+ yield PlacesTestUtils.promiseAsyncUpdates();
+ check_orphans();
+});
+
+add_task(function* test_addRemoveBookmark() {
+ let observer = expectNotifications();
+
+ let itemId =
+ PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
+ URI3,
+ PlacesUtils.bookmarks.DEFAULT_INDEX,
+ "test3");
+
+ PlacesUtils.bookmarks.setKeywordForBookmark(itemId, "keyword");
+ let bookmark = yield PlacesUtils.bookmarks.fetch({ url: URI3 });
+ let parentId = yield PlacesUtils.promiseItemId(bookmark.parentGuid);
+ PlacesUtils.bookmarks.removeItem(itemId);
+
+ observer.check([ { name: "onItemChanged",
+ arguments: [ itemId,
+ "keyword", false, "keyword",
+ bookmark.lastModified, bookmark.type,
+ parentId,
+ bookmark.guid, bookmark.parentGuid, "",
+ Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
+ ]);
+
+ check_keyword(URI3, null);
+ // Don't check the foreign count since the process is async.
+ // The new test_keywords.js in unit is checking this though.
+
+ yield PlacesTestUtils.promiseAsyncUpdates();
+ check_orphans();
+});
+
+function run_test() {
+ run_next_test();
+}