Dactyloidae/toolkit/components/places/tests/bookmarks/test_keywords.js

310 lines
13 KiB
JavaScript

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();
}