Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

add_task(async function invalid_input_rejects() {
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(),
/Should be provided a valid tree object./
);
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(null),
/Should be provided a valid tree object./
);
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree("foo"),
/Should be provided a valid tree object./
);
// All subsequent tests pass a valid parent guid.
let guid = PlacesUtils.bookmarks.unfiledGuid;
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree({ guid, children: [] }),
/Should have a non-zero number of children to insert./
);
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree({ guid }),
/Should have a non-zero number of children to insert./
);
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree({ children: [{}], guid }),
/The following properties were expected: url/
);
// Reuse another variable to make this easier to read:
let tree = { guid, children: [{ guid: "test" }] };
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(tree),
/Invalid value for property 'guid'/
);
tree.children = [{ guid: null }];
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(tree),
/Invalid value for property 'guid'/
);
tree.children = [{ guid: 123 }];
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(tree),
/Invalid value for property 'guid'/
);
tree.children = [{ dateAdded: -10 }];
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(tree),
/Invalid value for property 'dateAdded'/
);
tree.children = [{ dateAdded: "today" }];
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(tree),
/Invalid value for property 'dateAdded'/
);
tree.children = [{ dateAdded: Date.now() }];
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(tree),
/Invalid value for property 'dateAdded'/
);
tree.children = [{ dateAdded: new Date(NaN) }];
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(tree),
/Invalid value for property 'dateAdded'/
);
tree.children = [{ lastModified: -10 }];
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(tree),
/Invalid value for property 'lastModified'/
);
tree.children = [{ lastModified: "today" }];
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(tree),
/Invalid value for property 'lastModified'/
);
tree.children = [{ lastModified: Date.now() }];
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(tree),
/Invalid value for property 'lastModified'/
);
let time = Date.now();
let future = new Date(time + 86400000);
tree.children = [{ dateAdded: future, lastModified: time }];
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(tree),
/Invalid value for property 'dateAdded'/
);
let past = new Date(time - 86400000);
tree.children = [{ lastModified: past }];
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(tree),
/Invalid value for property 'lastModified'/
);
tree.children = [{ type: -1 }];
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(tree),
/Invalid value for property 'type'/
);
tree.children = [{ type: 100 }];
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(tree),
/Invalid value for property 'type'/
);
tree.children = [{ type: "bookmark" }];
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(tree),
/Invalid value for property 'type'/
);
tree.children = [{ type: PlacesUtils.bookmarks.TYPE_BOOKMARK, title: -1 }];
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(tree),
/Invalid value for property 'title'/
);
tree.children = [{ type: PlacesUtils.bookmarks.TYPE_BOOKMARK, url: 10 }];
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(tree),
/Invalid value for property 'url'/
);
let treeWithBrokenURL = {
children: [
{ type: PlacesUtils.bookmarks.TYPE_BOOKMARK, url: "http://te st" },
],
guid: PlacesUtils.bookmarks.unfiledGuid,
};
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(treeWithBrokenURL),
/Invalid value for property 'url'/
);
let longurl = "http://www.example.com/" + "a".repeat(65536);
let treeWithLongURL = {
children: [{ type: PlacesUtils.bookmarks.TYPE_BOOKMARK, url: longurl }],
guid: PlacesUtils.bookmarks.unfiledGuid,
};
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(treeWithLongURL),
/Invalid value for property 'url'/
);
let treeWithLongURI = {
children: [
{
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
url: NetUtil.newURI(longurl),
},
],
guid: PlacesUtils.bookmarks.unfiledGuid,
};
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(treeWithLongURI),
/Invalid value for property 'url'/
);
let treeWithOtherBrokenURL = {
children: [{ type: PlacesUtils.bookmarks.TYPE_BOOKMARK, url: "te st" }],
guid: PlacesUtils.bookmarks.unfiledGuid,
};
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(treeWithOtherBrokenURL),
/Invalid value for property 'url'/
);
});
add_task(async function invalid_properties_for_bookmark_type() {
let folderWithURL = {
children: [
{ type: PlacesUtils.bookmarks.TYPE_FOLDER, url: "http://www.moz.com/" },
],
guid: PlacesUtils.bookmarks.unfiledGuid,
};
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(folderWithURL),
/Invalid value for property 'url'/
);
let separatorWithURL = {
children: [
{
type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
},
],
guid: PlacesUtils.bookmarks.unfiledGuid,
};
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(separatorWithURL),
/Invalid value for property 'url'/
);
let separatorWithTitle = {
children: [{ type: PlacesUtils.bookmarks.TYPE_SEPARATOR, title: "test" }],
guid: PlacesUtils.bookmarks.unfiledGuid,
};
await Assert.throws(
() => PlacesUtils.bookmarks.insertTree(separatorWithTitle),
/Invalid value for property 'title'/
);
});
add_task(async function create_separator() {
let [bm] = await PlacesUtils.bookmarks.insertTree({
children: [
{
type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
},
],
guid: PlacesUtils.bookmarks.unfiledGuid,
});
checkBookmarkObject(bm);
Assert.equal(bm.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
Assert.equal(bm.index, 0);
Assert.equal(bm.dateAdded, bm.lastModified);
Assert.equal(bm.type, PlacesUtils.bookmarks.TYPE_SEPARATOR);
Assert.strictEqual(bm.title, "");
});
add_task(async function create_plain_bm() {
let [bm] = await PlacesUtils.bookmarks.insertTree({
children: [
{
title: "Test",
},
],
guid: PlacesUtils.bookmarks.unfiledGuid,
});
checkBookmarkObject(bm);
Assert.equal(bm.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
Assert.equal(bm.index, 1);
Assert.equal(bm.dateAdded, bm.lastModified);
Assert.equal(bm.type, PlacesUtils.bookmarks.TYPE_BOOKMARK);
Assert.equal(bm.title, "Test");
Assert.equal(bm.url.href, "http://www.example.com/");
});
add_task(async function create_folder() {
let [bm] = await PlacesUtils.bookmarks.insertTree({
children: [
{
type: PlacesUtils.bookmarks.TYPE_FOLDER,
title: "Test",
},
],
guid: PlacesUtils.bookmarks.unfiledGuid,
});
checkBookmarkObject(bm);
Assert.equal(bm.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
Assert.equal(bm.index, 2);
Assert.equal(bm.dateAdded, bm.lastModified);
Assert.equal(bm.type, PlacesUtils.bookmarks.TYPE_FOLDER);
Assert.equal(bm.title, "Test");
});
add_task(async function create_in_tags() {
await Assert.throws(
() =>
PlacesUtils.bookmarks.insertTree({
children: [
{
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
title: "Test adding a tag",
},
],
guid: PlacesUtils.bookmarks.tagsGuid,
}),
/Can't use insertTree to insert tags/
);
let guidForTag = (
await PlacesUtils.bookmarks.insert({
title: "test-tag",
parentGuid: PlacesUtils.bookmarks.tagsGuid,
})
).guid;
await Assert.rejects(
PlacesUtils.bookmarks.insertTree({
children: [
{
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
title: "Test adding an item to a tag",
},
],
guid: guidForTag,
}),
/Can't use insertTree to insert tags/
);
await PlacesUtils.bookmarks.remove(guidForTag);
await PlacesTestUtils.promiseAsyncUpdates();
});
add_task(async function insert_into_root() {
await Assert.throws(
() =>
PlacesUtils.bookmarks.insertTree({
children: [
{
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
title: "Test inserting into root",
},
],
guid: PlacesUtils.bookmarks.rootGuid,
}),
/Can't insert into the root/
);
});
add_task(async function tree_where_separator_or_folder_has_kids() {
await Assert.throws(
() =>
PlacesUtils.bookmarks.insertTree({
children: [
{
type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
children: [
{
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
title: "Test inserting into separator",
},
],
},
],
guid: PlacesUtils.bookmarks.unfiledGuid,
}),
/Invalid value for property 'children'/
);
await Assert.throws(
() =>
PlacesUtils.bookmarks.insertTree({
children: [
{
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
children: [
{
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
title: "Test inserting into separator",
},
],
},
],
guid: PlacesUtils.bookmarks.unfiledGuid,
}),
/Invalid value for property 'children'/
);
});
add_task(async function create_hierarchy() {
let obsInvoked = 0;
let listener = events => {
for (let event of events) {
obsInvoked++;
Assert.greater(event.id, 0, "Should have a valid itemId");
}
};
PlacesUtils.observers.addListener(["bookmark-added"], listener);
let bms = await PlacesUtils.bookmarks.insertTree({
children: [
{
type: PlacesUtils.bookmarks.TYPE_FOLDER,
title: "Root item",
children: [
{
title: "BM 1",
},
{
title: "BM 2",
},
{
title: "Sub",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
children: [
{
title: "Sub BM 1",
},
{
title: "Sub BM 2",
},
],
},
],
},
],
guid: PlacesUtils.bookmarks.unfiledGuid,
});
await PlacesFrecencyRecalculator.recalculateAnyOutdatedFrecencies();
PlacesUtils.observers.removeListener(["bookmark-added"], listener);
let parentFolder = null,
subFolder = null;
let prevBM = null;
for (let bm of bms) {
checkBookmarkObject(bm);
if (prevBM && prevBM.parentGuid == bm.parentGuid) {
Assert.equal(prevBM.index + 1, bm.index, "Indices should be subsequent");
Assert.equal(
(await PlacesUtils.bookmarks.fetch(bm.guid)).index,
bm.index,
"Index reflects inserted index"
);
}
prevBM = bm;
if (bm.type == PlacesUtils.bookmarks.TYPE_BOOKMARK) {
Assert.greater(
await PlacesTestUtils.getDatabaseValue("moz_places", "frecency", {
url: bm.url,
}),
0,
"Check frecency has been updated for bookmark " + bm.url
);
}
if (bm.title == "Root item") {
Assert.equal(bm.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
parentFolder = bm;
} else if (!bm.title.startsWith("Sub BM")) {
Assert.equal(bm.parentGuid, parentFolder.guid);
if (bm.type == PlacesUtils.bookmarks.TYPE_FOLDER) {
subFolder = bm;
}
} else {
Assert.equal(bm.parentGuid, subFolder.guid);
}
}
Assert.equal(obsInvoked, bms.length);
Assert.equal(obsInvoked, 6);
});
add_task(async function insert_many_non_nested() {
let obsInvoked = 0;
let listener = events => {
for (let event of events) {
obsInvoked++;
Assert.greater(event.id, 0, "Should have a valid itemId");
}
};
PlacesUtils.observers.addListener(["bookmark-added"], listener);
let bms = await PlacesUtils.bookmarks.insertTree({
children: [
{
title: "Item 1",
},
{
title: "Item 2",
},
{
title: "Item 3",
},
{
type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
},
{
title: "Item 4",
},
{
title: "Item 5",
},
],
guid: PlacesUtils.bookmarks.unfiledGuid,
});
await PlacesFrecencyRecalculator.recalculateAnyOutdatedFrecencies();
PlacesUtils.observers.removeListener(["bookmark-added"], listener);
let startIndex = -1;
for (let bm of bms) {
checkBookmarkObject(bm);
if (startIndex == -1) {
startIndex = bm.index;
} else {
Assert.equal(++startIndex, bm.index, "Indices should be subsequent");
}
Assert.equal(
(await PlacesUtils.bookmarks.fetch(bm.guid)).index,
bm.index,
"Index reflects inserted index"
);
if (bm.type == PlacesUtils.bookmarks.TYPE_BOOKMARK) {
Assert.greater(
await PlacesTestUtils.getDatabaseValue("moz_places", "frecency", {
url: bm.url,
}),
0,
"Check frecency has been updated for bookmark " + bm.url
);
}
Assert.equal(bm.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
}
Assert.equal(obsInvoked, bms.length);
Assert.equal(obsInvoked, 6);
});
add_task(async function create_in_folder() {
let mozFolder = await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.menuGuid,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
title: "Mozilla",
});
let notifications = [];
let listener = events => {
for (let event of events) {
notifications.push({
itemId: event.id,
parentId: event.parentId,
index: event.index,
title: event.title,
guid: event.guid,
parentGuid: event.parentGuid,
});
}
};
PlacesUtils.observers.addListener(["bookmark-added"], listener);
let bms = await PlacesUtils.bookmarks.insertTree({
children: [
{
title: "Get Firefox!",
},
{
type: PlacesUtils.bookmarks.TYPE_FOLDER,
title: "Community",
children: [
{
title: "Get Thunderbird!",
},
{
title: "SeaMonkey",
},
],
},
],
guid: mozFolder.guid,
});
await PlacesTestUtils.promiseAsyncUpdates();
PlacesUtils.observers.removeListener(["bookmark-added"], listener);
let mozFolderId = await PlacesTestUtils.promiseItemId(mozFolder.guid);
let commFolderId = await PlacesTestUtils.promiseItemId(bms[1].guid);
deepEqual(notifications, [
{
itemId: await PlacesTestUtils.promiseItemId(bms[0].guid),
parentId: mozFolderId,
index: 0,
title: "Get Firefox!",
guid: bms[0].guid,
parentGuid: mozFolder.guid,
},
{
itemId: commFolderId,
parentId: mozFolderId,
index: 1,
title: "Community",
guid: bms[1].guid,
parentGuid: mozFolder.guid,
},
{
itemId: await PlacesTestUtils.promiseItemId(bms[2].guid),
parentId: commFolderId,
index: 0,
title: "Get Thunderbird!",
guid: bms[2].guid,
parentGuid: bms[1].guid,
},
{
itemId: await PlacesTestUtils.promiseItemId(bms[3].guid),
parentId: commFolderId,
index: 1,
title: "SeaMonkey",
guid: bms[3].guid,
parentGuid: bms[1].guid,
},
]);
});