summaryrefslogtreecommitdiffstats
path: root/toolkit/components/places/tests/bookmarks/test_bookmarks_insertTree.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/places/tests/bookmarks/test_bookmarks_insertTree.js')
-rw-r--r--toolkit/components/places/tests/bookmarks/test_bookmarks_insertTree.js590
1 files changed, 590 insertions, 0 deletions
diff --git a/toolkit/components/places/tests/bookmarks/test_bookmarks_insertTree.js b/toolkit/components/places/tests/bookmarks/test_bookmarks_insertTree.js
new file mode 100644
index 0000000000..0fad7d4b31
--- /dev/null
+++ b/toolkit/components/places/tests/bookmarks/test_bookmarks_insertTree.js
@@ -0,0 +1,590 @@
+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,
+ url: "http://www.moz.com/",
+ },
+ ],
+ 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: [
+ {
+ url: "http://www.example.com/",
+ 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,
+ url: "http://www.example.com/",
+ 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",
+ url: "http://www.unused.com/",
+ parentGuid: PlacesUtils.bookmarks.tagsGuid,
+ })
+ ).guid;
+ await Assert.rejects(
+ PlacesUtils.bookmarks.insertTree({
+ children: [
+ {
+ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
+ url: "http://www.example.com/",
+ 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,
+ url: "http://www.example.com/",
+ 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,
+ url: "http://www.example.com/",
+ 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,
+ url: "http://www.example.com/",
+ 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: [
+ {
+ url: "http://www.example.com/1",
+ title: "BM 1",
+ },
+ {
+ url: "http://www.example.com/2",
+ title: "BM 2",
+ },
+ {
+ title: "Sub",
+ type: PlacesUtils.bookmarks.TYPE_FOLDER,
+ children: [
+ {
+ title: "Sub BM 1",
+ url: "http://www.example.com/sub/1",
+ },
+ {
+ title: "Sub BM 2",
+ url: "http://www.example.com/sub/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: [
+ {
+ url: "http://www.example.com/1",
+ title: "Item 1",
+ },
+ {
+ url: "http://www.example.com/2",
+ title: "Item 2",
+ },
+ {
+ url: "http://www.example.com/3",
+ title: "Item 3",
+ },
+ {
+ type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
+ },
+ {
+ title: "Item 4",
+ url: "http://www.example.com/4",
+ },
+ {
+ title: "Item 5",
+ url: "http://www.example.com/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: [
+ {
+ url: "http://getfirefox.com",
+ title: "Get Firefox!",
+ },
+ {
+ type: PlacesUtils.bookmarks.TYPE_FOLDER,
+ title: "Community",
+ children: [
+ {
+ url: "http://getthunderbird.com",
+ title: "Get Thunderbird!",
+ },
+ {
+ url: "https://www.seamonkey-project.org",
+ title: "SeaMonkey",
+ },
+ ],
+ },
+ ],
+ guid: mozFolder.guid,
+ });
+ await PlacesTestUtils.promiseAsyncUpdates();
+
+ PlacesUtils.observers.removeListener(["bookmark-added"], listener);
+
+ let mozFolderId = await PlacesUtils.promiseItemId(mozFolder.guid);
+ let commFolderId = await PlacesUtils.promiseItemId(bms[1].guid);
+ deepEqual(notifications, [
+ {
+ itemId: await PlacesUtils.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 PlacesUtils.promiseItemId(bms[2].guid),
+ parentId: commFolderId,
+ index: 0,
+ title: "Get Thunderbird!",
+ guid: bms[2].guid,
+ parentGuid: bms[1].guid,
+ },
+ {
+ itemId: await PlacesUtils.promiseItemId(bms[3].guid),
+ parentId: commFolderId,
+ index: 1,
+ title: "SeaMonkey",
+ guid: bms[3].guid,
+ parentGuid: bms[1].guid,
+ },
+ ]);
+});