/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const { Bookmark, BookmarkFolder, BookmarkQuery, PlacesItem } =
ChromeUtils.importESModule(
"resource://services-sync/engines/bookmarks.sys.mjs"
);
// `Service` is used as a global in head_helpers.js.
// eslint-disable-next-line no-unused-vars
const { Service } = ChromeUtils.importESModule(
"resource://services-sync/service.sys.mjs"
);
const BookmarksToolbarTitle =
"toolbar";
// apply some test records without going via a test server.
async
function apply_records(engine, records) {
for (record of records) {
await engine._store.applyIncoming(record);
}
await engine._apply();
}
add_bookmark_test(async
function test_ignore_specials(engine) {
_(
"Ensure that we can't delete bookmark roots.");
let store = engine._store;
// Belt...
let record =
new BookmarkFolder(
"bookmarks",
"toolbar",
"folder");
record.deleted =
true;
Assert.notEqual(
null,
await PlacesTestUtils.promiseItemId(PlacesUtils.bookmarks.toolbarGuid)
);
await apply_records(engine, [record]);
// Ensure that the toolbar exists.
Assert.notEqual(
null,
await PlacesTestUtils.promiseItemId(PlacesUtils.bookmarks.toolbarGuid)
);
await apply_records(engine, [record]);
Assert.notEqual(
null,
await PlacesTestUtils.promiseItemId(PlacesUtils.bookmarks.toolbarGuid)
);
await store.wipe();
});
add_bookmark_test(async
function test_bookmark_create(engine) {
let store = engine._store;
try {
_(
"Ensure the record isn't present yet.");
let item = await PlacesUtils.bookmarks.fetch({
url:
"http://getfirefox.com/",
});
Assert.equal(
null, item);
_(
"Let's create a new record.");
let fxrecord =
new Bookmark(
"bookmarks",
"get-firefox1");
fxrecord.bmkUri =
"http://getfirefox.com/";
fxrecord.title =
"Get Firefox!";
fxrecord.tags = [
"firefox",
"awesome",
"browser"];
fxrecord.keyword =
"awesome";
fxrecord.parentName = BookmarksToolbarTitle;
fxrecord.parentid =
"toolbar";
await apply_records(engine, [fxrecord]);
_(
"Verify it has been created correctly.");
item = await PlacesUtils.bookmarks.fetch(fxrecord.id);
Assert.equal(item.type, PlacesUtils.bookmarks.TYPE_BOOKMARK);
Assert.equal(item.url.href,
"http://getfirefox.com/");
Assert.equal(item.title, fxrecord.title);
Assert.equal(item.parentGuid, PlacesUtils.bookmarks.toolbarGuid);
let keyword = await PlacesUtils.keywords.fetch(fxrecord.keyword);
Assert.equal(keyword.url.href,
"http://getfirefox.com/");
_(
"Have the store create a new record object. Verify that it has the same data."
);
let newrecord = await store.createRecord(fxrecord.id);
Assert.ok(newrecord
instanceof Bookmark);
for (let property of [
"type",
"bmkUri",
"title",
"keyword",
"parentName",
"parentid",
]) {
Assert.equal(newrecord[property], fxrecord[property]);
}
Assert.ok(Utils.deepEquals(newrecord.tags.sort(), fxrecord.tags.sort()));
_(
"The calculated sort index is based on frecency data.");
Assert.ok(newrecord.sortindex >= 150);
_(
"Create a record with some values missing.");
let tbrecord =
new Bookmark(
"bookmarks",
"thunderbird1");
tbrecord.bmkUri =
"http://getthunderbird.com/";
tbrecord.parentName = BookmarksToolbarTitle;
tbrecord.parentid =
"toolbar";
await apply_records(engine, [tbrecord]);
_(
"Verify it has been created correctly.");
item = await PlacesUtils.bookmarks.fetch(tbrecord.id);
Assert.equal(item.type, PlacesUtils.bookmarks.TYPE_BOOKMARK);
Assert.equal(item.url.href,
"http://getthunderbird.com/");
Assert.equal(item.title,
"");
Assert.equal(item.parentGuid, PlacesUtils.bookmarks.toolbarGuid);
keyword = await PlacesUtils.keywords.fetch({
url:
"http://getthunderbird.com/",
});
Assert.equal(
null, keyword);
}
finally {
_(
"Clean up.");
await store.wipe();
}
});
add_bookmark_test(async
function test_bookmark_update(engine) {
let store = engine._store;
try {
_(
"Create a bookmark whose values we'll change.");
let bmk1 = await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
url:
"http://getfirefox.com/",
title:
"Get Firefox!",
});
await PlacesUtils.keywords.insert({
url:
"http://getfirefox.com/",
keyword:
"firefox",
});
_(
"Update the record with some null values.");
let record = await store.createRecord(bmk1.guid);
record.title =
null;
record.keyword =
null;
record.tags =
null;
await apply_records(engine, [record]);
_(
"Verify that the values have been cleared.");
let item = await PlacesUtils.bookmarks.fetch(bmk1.guid);
Assert.equal(item.title,
"");
let keyword = await PlacesUtils.keywords.fetch({
url:
"http://getfirefox.com/",
});
Assert.equal(
null, keyword);
}
finally {
_(
"Clean up.");
await store.wipe();
}
});
add_bookmark_test(async
function test_bookmark_createRecord(engine) {
let store = engine._store;
try {
_(
"Create a bookmark without a title.");
let bmk1 = await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
url:
"http://getfirefox.com/",
});
_(
"Verify that the record is created accordingly.");
let record = await store.createRecord(bmk1.guid);
Assert.equal(record.title,
"");
Assert.equal(record.keyword,
null);
}
finally {
_(
"Clean up.");
await store.wipe();
}
});
add_bookmark_test(async
function test_folder_create(engine) {
let store = engine._store;
try {
_(
"Create a folder.");
let folder =
new BookmarkFolder(
"bookmarks",
"testfolder-1");
folder.parentName = BookmarksToolbarTitle;
folder.parentid =
"toolbar";
folder.title =
"Test Folder";
await apply_records(engine, [folder]);
_(
"Verify it has been created correctly.");
let item = await PlacesUtils.bookmarks.fetch(folder.id);
Assert.equal(item.type, PlacesUtils.bookmarks.TYPE_FOLDER);
Assert.equal(item.title, folder.title);
Assert.equal(item.parentGuid, PlacesUtils.bookmarks.toolbarGuid);
_(
"Have the store create a new record object. Verify that it has the same data."
);
let newrecord = await store.createRecord(folder.id);
Assert.ok(newrecord
instanceof BookmarkFolder);
for (let property of [
"title",
"parentName",
"parentid"]) {
Assert.equal(newrecord[property], folder[property]);
}
_(
"Folders have high sort index to ensure they're synced first.");
Assert.equal(newrecord.sortindex, 1000000);
}
finally {
_(
"Clean up.");
await store.wipe();
}
});
add_bookmark_test(async
function test_folder_createRecord(engine) {
let store = engine._store;
try {
_(
"Create a folder.");
let folder1 = await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
title:
"Folder1",
});
_(
"Create two bookmarks in that folder without assigning them GUIDs.");
let bmk1 = await PlacesUtils.bookmarks.insert({
parentGuid: folder1.guid,
url:
"http://getfirefox.com/",
title:
"Get Firefox!",
});
let bmk2 = await PlacesUtils.bookmarks.insert({
parentGuid: folder1.guid,
url:
"http://getthunderbird.com/",
title:
"Get Thunderbird!",
});
_(
"Create a record for the folder and verify basic properties.");
let record = await store.createRecord(folder1.guid);
Assert.ok(record
instanceof BookmarkFolder);
Assert.equal(record.title,
"Folder1");
Assert.equal(record.parentid,
"toolbar");
Assert.equal(record.parentName, BookmarksToolbarTitle);
_(
"Verify the folder's children. Ensures that the bookmarks were given GUIDs."
);
Assert.deepEqual(record.children, [bmk1.guid, bmk2.guid]);
}
finally {
_(
"Clean up.");
await store.wipe();
}
});
add_bookmark_test(async
function test_deleted(engine) {
let store = engine._store;
try {
_(
"Create a bookmark that will be deleted.");
let bmk1 = await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
url:
"http://getfirefox.com/",
title:
"Get Firefox!",
});
// The engine needs to think we've previously synced it.
await PlacesTestUtils.markBookmarksAsSynced();
_(
"Delete the bookmark through the store.");
let record =
new PlacesItem(
"bookmarks", bmk1.guid);
record.deleted =
true;
await apply_records(engine, [record]);
_(
"Ensure it has been deleted.");
let item = await PlacesUtils.bookmarks.fetch(bmk1.guid);
let newrec = await store.createRecord(bmk1.guid);
Assert.equal(
null, item);
Assert.equal(newrec.deleted,
true);
_(
"Verify that the keyword has been cleared.");
let keyword = await PlacesUtils.keywords.fetch({
url:
"http://getfirefox.com/",
});
Assert.equal(
null, keyword);
}
finally {
_(
"Clean up.");
await store.wipe();
}
});
add_bookmark_test(async
function test_move_folder(engine) {
let store = engine._store;
store._childrenToOrder = {};
// *sob* - only needed for legacy.
try {
_(
"Create two folders and a bookmark in one of them.");
let folder1 = await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
title:
"Folder1",
});
let folder2 = await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
title:
"Folder2",
});
let bmk = await PlacesUtils.bookmarks.insert({
parentGuid: folder1.guid,
url:
"http://getfirefox.com/",
title:
"Get Firefox!",
});
// add records to the store that represent the current state.
await apply_records(engine, [
await store.createRecord(folder1.guid),
await store.createRecord(folder2.guid),
await store.createRecord(bmk.guid),
]);
_(
"Now simulate incoming records reparenting it.");
let bmkRecord = await store.createRecord(bmk.guid);
Assert.equal(bmkRecord.parentid, folder1.guid);
bmkRecord.parentid = folder2.guid;
let folder1Record = await store.createRecord(folder1.guid);
Assert.deepEqual(folder1Record.children, [bmk.guid]);
folder1Record.children = [];
let folder2Record = await store.createRecord(folder2.guid);
Assert.deepEqual(folder2Record.children, []);
folder2Record.children = [bmk.guid];
await apply_records(engine, [bmkRecord, folder1Record, folder2Record]);
_(
"Verify the new parent.");
let movedBmk = await PlacesUtils.bookmarks.fetch(bmk.guid);
Assert.equal(movedBmk.parentGuid, folder2.guid);
}
finally {
_(
"Clean up.");
await store.wipe();
}
});
add_bookmark_test(async
function test_move_order(engine) {
let store = engine._store;
let tracker = engine._tracker;
// Make sure the tracker is turned on.
tracker.start();
try {
_(
"Create two bookmarks");
let bmk1 = await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
url:
"http://getfirefox.com/",
title:
"Get Firefox!",
});
let bmk2 = await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
url:
"http://getthunderbird.com/",
title:
"Get Thunderbird!",
});
_(
"Verify order.");
let childIds =
await PlacesSyncUtils.bookmarks.fetchChildRecordIds(
"toolbar");
Assert.deepEqual(childIds, [bmk1.guid, bmk2.guid]);
let toolbar = await store.createRecord(
"toolbar");
Assert.deepEqual(toolbar.children, [bmk1.guid, bmk2.guid]);
_(
"Move bookmarks around.");
store._childrenToOrder = {};
toolbar.children = [bmk2.guid, bmk1.guid];
await apply_records(engine, [
toolbar,
await store.createRecord(bmk1.guid),
await store.createRecord(bmk2.guid),
]);
delete store._childrenToOrder;
_(
"Verify new order.");
let newChildIds =
await PlacesSyncUtils.bookmarks.fetchChildRecordIds(
"toolbar");
Assert.deepEqual(newChildIds, [bmk2.guid, bmk1.guid]);
}
finally {
await tracker.stop();
_(
"Clean up.");
await store.wipe();
}
});
// Tests Bug 806460, in which query records arrive with empty folder
// names and missing bookmark URIs.
add_bookmark_test(async
function test_empty_query_doesnt_die(engine) {
let record =
new BookmarkQuery(
"bookmarks",
"8xoDGqKrXf1P");
record.folderName =
"";
record.queryId =
"";
record.parentName =
"Toolbar";
record.parentid =
"toolbar";
// These should not throw.
await apply_records(engine, [record]);
delete record.folderName;
await apply_records(engine, [record]);
});
add_bookmark_test(async
function test_calculateIndex_for_invalid_url(engine) {
let store = engine._store;
let folderIndex = await store._calculateIndex({
type:
"folder",
});
equal(folderIndex, 1000000,
"Should use high sort index for folders");
let toolbarIndex = await store._calculateIndex({
parentid:
"toolbar",
});
equal(toolbarIndex, 150,
"Should bump sort index for toolbar bookmarks");
let validURLIndex = await store._calculateIndex({
bmkUri:
"http://example.com/a",
});
greaterOrEqual(validURLIndex, 0,
"Should use frecency for index");
let invalidURLIndex = await store._calculateIndex({
bmkUri:
"!@#$%",
});
equal(invalidURLIndex, 0,
"Should not throw for invalid URLs");
});