diff options
Diffstat (limited to 'toolkit/components/places/tests/bookmarks/test_keywords.js')
-rw-r--r-- | toolkit/components/places/tests/bookmarks/test_keywords.js | 310 |
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(); +} |