summaryrefslogtreecommitdiffstats
path: root/toolkit/components/places/tests/bookmarks/test_bookmarks_reorder.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/places/tests/bookmarks/test_bookmarks_reorder.js')
-rw-r--r--toolkit/components/places/tests/bookmarks/test_bookmarks_reorder.js310
1 files changed, 310 insertions, 0 deletions
diff --git a/toolkit/components/places/tests/bookmarks/test_bookmarks_reorder.js b/toolkit/components/places/tests/bookmarks/test_bookmarks_reorder.js
new file mode 100644
index 0000000000..7df909c704
--- /dev/null
+++ b/toolkit/components/places/tests/bookmarks/test_bookmarks_reorder.js
@@ -0,0 +1,310 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+add_task(async function invalid_input_throws() {
+ Assert.throws(
+ () => PlacesUtils.bookmarks.reorder(),
+ /Invalid value for property 'guid'/
+ );
+ Assert.throws(
+ () => PlacesUtils.bookmarks.reorder(null),
+ /Invalid value for property 'guid'/
+ );
+
+ Assert.throws(
+ () => PlacesUtils.bookmarks.reorder("test"),
+ /Invalid value for property 'guid'/
+ );
+ Assert.throws(
+ () => PlacesUtils.bookmarks.reorder(123),
+ /Invalid value for property 'guid'/
+ );
+
+ Assert.throws(
+ () => PlacesUtils.bookmarks.reorder({ guid: "test" }),
+ /Invalid value for property 'guid'/
+ );
+
+ Assert.throws(
+ () => PlacesUtils.bookmarks.reorder("123456789012"),
+ /Must provide a sorted array of children GUIDs./
+ );
+ Assert.throws(
+ () => PlacesUtils.bookmarks.reorder("123456789012", {}),
+ /Must provide a sorted array of children GUIDs./
+ );
+ Assert.throws(
+ () => PlacesUtils.bookmarks.reorder("123456789012", null),
+ /Must provide a sorted array of children GUIDs./
+ );
+ Assert.throws(
+ () => PlacesUtils.bookmarks.reorder("123456789012", []),
+ /Must provide a sorted array of children GUIDs./
+ );
+
+ Assert.throws(
+ () => PlacesUtils.bookmarks.reorder("123456789012", [null]),
+ /Invalid GUID found in the sorted children array/
+ );
+ Assert.throws(
+ () => PlacesUtils.bookmarks.reorder("123456789012", [""]),
+ /Invalid GUID found in the sorted children array/
+ );
+ Assert.throws(
+ () => PlacesUtils.bookmarks.reorder("123456789012", [{}]),
+ /Invalid GUID found in the sorted children array/
+ );
+ Assert.throws(
+ () => PlacesUtils.bookmarks.reorder("123456789012", ["012345678901", null]),
+ /Invalid GUID found in the sorted children array/
+ );
+});
+
+add_task(async function reorder_nonexistent_guid() {
+ await Assert.rejects(
+ PlacesUtils.bookmarks.reorder("123456789012", ["012345678901"]),
+ /No folder found for the provided GUID/,
+ "Should throw for nonexisting guid"
+ );
+});
+
+add_task(async function reorder() {
+ let bookmarks = [
+ {
+ url: "http://example1.com/",
+ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
+ },
+ {
+ type: PlacesUtils.bookmarks.TYPE_FOLDER,
+ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
+ },
+ {
+ type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
+ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
+ },
+ {
+ url: "http://example2.com/",
+ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
+ },
+ {
+ url: "http://example3.com/",
+ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
+ },
+ ];
+
+ let sorted = [];
+ for (let bm of bookmarks) {
+ sorted.push(await PlacesUtils.bookmarks.insert(bm));
+ }
+
+ // Check the initial append sorting.
+ Assert.ok(
+ sorted.every((bm, i) => bm.index == i),
+ "Initial bookmarks sorting is correct"
+ );
+
+ // Apply random sorting and run multiple tests.
+ for (let t = 0; t < 4; t++) {
+ sorted.sort(() => 0.5 - Math.random());
+ let sortedGuids = sorted.map(child => child.guid);
+ dump("Expected order: " + sortedGuids.join() + "\n");
+ // Add a nonexisting guid to the array, to ensure nothing will break.
+ sortedGuids.push("123456789012");
+ await PlacesUtils.bookmarks.reorder(
+ PlacesUtils.bookmarks.unfiledGuid,
+ sortedGuids
+ );
+ for (let i = 0; i < sorted.length; ++i) {
+ let item = await PlacesUtils.bookmarks.fetch(sorted[i].guid);
+ Assert.equal(item.index, i);
+ }
+ }
+
+ info("Test partial sorting");
+ {
+ // Try a partial sorting by passing 2 entries in same order as they
+ // currently have. No entries should change order.
+ let sortedGuids = [sorted[0].guid, sorted[3].guid];
+ dump("Expected order: " + sorted.map(b => b.guid).join() + "\n");
+ await PlacesUtils.bookmarks.reorder(
+ PlacesUtils.bookmarks.unfiledGuid,
+ sortedGuids
+ );
+ for (let i = 0; i < sorted.length; ++i) {
+ let item = await PlacesUtils.bookmarks.fetch(sorted[i].guid);
+ Assert.equal(item.index, i);
+ }
+ }
+
+ {
+ // Try a partial sorting by passing 2 entries out of order
+ // The unspecified entries should be appended and retain the original order
+ sorted = [sorted[1], sorted[0]].concat(sorted.slice(2));
+ let sortedGuids = [sorted[0].guid, sorted[1].guid];
+ dump("Expected order: " + sorted.map(b => b.guid).join() + "\n");
+ await PlacesUtils.bookmarks.reorder(
+ PlacesUtils.bookmarks.unfiledGuid,
+ sortedGuids
+ );
+ for (let i = 0; i < sorted.length; ++i) {
+ let item = await PlacesUtils.bookmarks.fetch(sorted[i].guid);
+ Assert.equal(item.index, i);
+ }
+ }
+ // Use triangular numbers to detect skipped position.
+ let db = await PlacesUtils.promiseDBConnection();
+ let rows = await db.execute(
+ `SELECT parent
+ FROM moz_bookmarks
+ GROUP BY parent
+ HAVING (SUM(DISTINCT position + 1) - (count(*) * (count(*) + 1) / 2)) <> 0`
+ );
+ Assert.equal(
+ rows.length,
+ 0,
+ "All the bookmarks should have consistent positions"
+ );
+});
+
+add_task(async function move_and_reorder() {
+ // Start clean.
+ await PlacesUtils.bookmarks.eraseEverything();
+
+ let bm1 = await PlacesUtils.bookmarks.insert({
+ url: "http://example1.com/",
+ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
+ });
+ let f1 = await PlacesUtils.bookmarks.insert({
+ type: PlacesUtils.bookmarks.TYPE_FOLDER,
+ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
+ });
+ let bm2 = await PlacesUtils.bookmarks.insert({
+ url: "http://example2.com/",
+ parentGuid: f1.guid,
+ });
+ let f2 = await PlacesUtils.bookmarks.insert({
+ type: PlacesUtils.bookmarks.TYPE_FOLDER,
+ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
+ });
+ let bm3 = await PlacesUtils.bookmarks.insert({
+ url: "http://example3.com/",
+ parentGuid: f2.guid,
+ });
+ let bm4 = await PlacesUtils.bookmarks.insert({
+ url: "http://example4.com/",
+ parentGuid: f2.guid,
+ });
+ let bm5 = await PlacesUtils.bookmarks.insert({
+ url: "http://example5.com/",
+ parentGuid: f2.guid,
+ });
+
+ // Invert f2 children.
+ // This is critical to reproduce the bug, cause it inverts the position
+ // compared to the natural insertion order.
+ await PlacesUtils.bookmarks.reorder(f2.guid, [bm5.guid, bm4.guid, bm3.guid]);
+
+ bm1.parentGuid = f1.guid;
+ bm1.index = 0;
+ await PlacesUtils.bookmarks.update(bm1);
+
+ bm1 = await PlacesUtils.bookmarks.fetch(bm1.guid);
+ Assert.equal(bm1.index, 0);
+ bm2 = await PlacesUtils.bookmarks.fetch(bm2.guid);
+ Assert.equal(bm2.index, 1);
+ bm3 = await PlacesUtils.bookmarks.fetch(bm3.guid);
+ Assert.equal(bm3.index, 2);
+ bm4 = await PlacesUtils.bookmarks.fetch(bm4.guid);
+ Assert.equal(bm4.index, 1);
+ bm5 = await PlacesUtils.bookmarks.fetch(bm5.guid);
+ Assert.equal(bm5.index, 0);
+
+ // No-op reorder on f1 children.
+ // Nothing should change. Though, due to bug 1293365 this was causing children
+ // of other folders to get messed up.
+ await PlacesUtils.bookmarks.reorder(f1.guid, [bm1.guid, bm2.guid]);
+
+ bm1 = await PlacesUtils.bookmarks.fetch(bm1.guid);
+ Assert.equal(bm1.index, 0);
+ bm2 = await PlacesUtils.bookmarks.fetch(bm2.guid);
+ Assert.equal(bm2.index, 1);
+ bm3 = await PlacesUtils.bookmarks.fetch(bm3.guid);
+ Assert.equal(bm3.index, 2);
+ bm4 = await PlacesUtils.bookmarks.fetch(bm4.guid);
+ Assert.equal(bm4.index, 1);
+ bm5 = await PlacesUtils.bookmarks.fetch(bm5.guid);
+ Assert.equal(bm5.index, 0);
+});
+
+add_task(async function reorder_empty_folder_invalid_children() {
+ // Start clean.
+ await PlacesUtils.bookmarks.eraseEverything();
+
+ let f1 = await PlacesUtils.bookmarks.insert({
+ type: PlacesUtils.bookmarks.TYPE_FOLDER,
+ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
+ });
+ // Specifying a child that doesn't exist should cause that to be ignored.
+ // However, before bug 1333304, doing this on an empty folder threw.
+ await PlacesUtils.bookmarks.reorder(f1.guid, ["123456789012"]);
+});
+
+add_task(async function reorder_lastModified() {
+ // Start clean.
+ await PlacesUtils.bookmarks.eraseEverything();
+
+ let lastModified = new Date(Date.now() - 1000);
+ await PlacesUtils.bookmarks.insertTree({
+ guid: PlacesUtils.bookmarks.menuGuid,
+ children: [
+ {
+ guid: "bookmarkAAAA",
+ url: "http://example.com/a",
+ title: "A",
+ dateAdded: lastModified,
+ lastModified,
+ },
+ {
+ guid: "bookmarkBBBB",
+ url: "http://example.com/b",
+ title: "B",
+ dateAdded: lastModified,
+ lastModified,
+ },
+ ],
+ });
+ await PlacesUtils.bookmarks.update({
+ guid: PlacesUtils.bookmarks.menuGuid,
+ lastModified,
+ });
+
+ info("Reorder and set explicit last modified time");
+ let newLastModified = new Date(lastModified.getTime() + 500);
+ await PlacesUtils.bookmarks.reorder(
+ PlacesUtils.bookmarks.menuGuid,
+ ["bookmarkBBBB", "bookmarkAAAA"],
+ { lastModified: newLastModified }
+ );
+ for (let guid of [
+ PlacesUtils.bookmarks.menuGuid,
+ "bookmarkAAAA",
+ "bookmarkBBBB",
+ ]) {
+ let info = await PlacesUtils.bookmarks.fetch(guid);
+ Assert.equal(info.lastModified.getTime(), newLastModified.getTime());
+ }
+
+ info("Reorder and set default last modified time");
+ await PlacesUtils.bookmarks.reorder(PlacesUtils.bookmarks.menuGuid, [
+ "bookmarkAAAA",
+ "bookmarkBBBB",
+ ]);
+ for (let guid of [
+ PlacesUtils.bookmarks.menuGuid,
+ "bookmarkAAAA",
+ "bookmarkBBBB",
+ ]) {
+ let info = await PlacesUtils.bookmarks.fetch(guid);
+ Assert.greater(info.lastModified.getTime(), newLastModified.getTime());
+ }
+});