summaryrefslogtreecommitdiffstats
path: root/browser/components/places/tests/browser/browser_library_views_liveupdate.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/places/tests/browser/browser_library_views_liveupdate.js')
-rw-r--r--browser/components/places/tests/browser/browser_library_views_liveupdate.js255
1 files changed, 255 insertions, 0 deletions
diff --git a/browser/components/places/tests/browser/browser_library_views_liveupdate.js b/browser/components/places/tests/browser/browser_library_views_liveupdate.js
new file mode 100644
index 0000000000..593b0bd243
--- /dev/null
+++ b/browser/components/places/tests/browser/browser_library_views_liveupdate.js
@@ -0,0 +1,255 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * Tests Library Left pane view for liveupdate.
+ */
+
+let gLibrary = null;
+
+add_setup(async function () {
+ gLibrary = await promiseLibrary();
+
+ await PlacesUtils.bookmarks.eraseEverything();
+
+ registerCleanupFunction(async () => {
+ await PlacesUtils.bookmarks.eraseEverything();
+ await promiseLibraryClosed(gLibrary);
+ });
+});
+
+async function testInFolder(folderGuid, prefix) {
+ let addedBookmarks = [];
+
+ let item = await insertAndCheckItem({
+ parentGuid: folderGuid,
+ title: `${prefix}1`,
+ url: `http://${prefix}1.mozilla.org/`,
+ });
+ item.title = `${prefix}1_edited`;
+ await updateAndCheckItem(item);
+ addedBookmarks.push(item);
+
+ item = await insertAndCheckItem(
+ {
+ parentGuid: folderGuid,
+ title: `${prefix}2`,
+ url: "place:",
+ },
+ 0
+ );
+
+ item.title = `${prefix}2_edited`;
+ await updateAndCheckItem(item, 0);
+ addedBookmarks.push(item);
+
+ item = await insertAndCheckItem({
+ parentGuid: folderGuid,
+ type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
+ });
+ addedBookmarks.push(item);
+
+ item = await insertAndCheckItem(
+ {
+ parentGuid: folderGuid,
+ title: `${prefix}f`,
+ type: PlacesUtils.bookmarks.TYPE_FOLDER,
+ },
+ 1
+ );
+
+ item.title = `${prefix}f_edited`;
+ await updateAndCheckItem(item, 1);
+
+ item.index = 0;
+ await updateAndCheckItem(item, 0);
+ addedBookmarks.push(item);
+
+ let folderGuid1 = item.guid;
+
+ item = await insertAndCheckItem({
+ parentGuid: folderGuid1,
+ title: `${prefix}f1`,
+ url: `http://${prefix}f1.mozilla.org/`,
+ });
+ addedBookmarks.push(item);
+
+ item = await insertAndCheckItem({
+ parentGuid: folderGuid1,
+ title: `${prefix}f12`,
+ url: `http://${prefix}f12.mozilla.org/`,
+ });
+ addedBookmarks.push(item);
+
+ item.index = 0;
+ await updateAndCheckItem(item);
+
+ return addedBookmarks;
+}
+
+add_task(async function test() {
+ let addedBookmarks = [];
+
+ info("*** Acting on menu bookmarks");
+ addedBookmarks = addedBookmarks.concat(
+ await testInFolder(PlacesUtils.bookmarks.menuGuid, "bm")
+ );
+
+ info("*** Acting on toolbar bookmarks");
+ addedBookmarks = addedBookmarks.concat(
+ await testInFolder(PlacesUtils.bookmarks.toolbarGuid, "tb")
+ );
+
+ info("*** Acting on unsorted bookmarks");
+ addedBookmarks = addedBookmarks.concat(
+ await testInFolder(PlacesUtils.bookmarks.unfiledGuid, "ub")
+ );
+
+ // Remove bookmarks in reverse order, so that the effects are correct.
+ for (let i = addedBookmarks.length - 1; i >= 0; i--) {
+ await removeAndCheckItem(addedBookmarks[i]);
+ }
+});
+
+async function insertAndCheckItem(itemData, expectedIndex) {
+ let item = await PlacesUtils.bookmarks.insert(itemData);
+
+ let [node, index, title] = getNodeForTreeItem(
+ item.guid,
+ gLibrary.PlacesOrganizer._places
+ );
+ // Left pane should not be updated for normal bookmarks or separators.
+ switch (itemData.type || PlacesUtils.bookmarks.TYPE_BOOKMARK) {
+ case PlacesUtils.bookmarks.TYPE_BOOKMARK:
+ let uriString = itemData.url;
+ let isQuery = uriString.substr(0, 6) == "place:";
+ if (isQuery) {
+ Assert.ok(node, "Should have a new query in the left pane.");
+ break;
+ }
+ // Fallthrough if this isn't a query
+ case PlacesUtils.bookmarks.TYPE_SEPARATOR:
+ Assert.ok(
+ !node,
+ "Should not have added a bookmark or separator to the left pane."
+ );
+ break;
+ default:
+ Assert.ok(
+ node,
+ "Should have added a new node in the left pane for a folder."
+ );
+ }
+
+ if (node) {
+ Assert.equal(title, itemData.title, "Should have the correct title");
+ Assert.equal(index, expectedIndex, "Should have the expected index");
+ }
+
+ return item;
+}
+
+async function updateAndCheckItem(newItemData, expectedIndex) {
+ await PlacesUtils.bookmarks.update(newItemData);
+
+ let [node, index, title] = getNodeForTreeItem(
+ newItemData.guid,
+ gLibrary.PlacesOrganizer._places
+ );
+
+ // Left pane should not be updated for normal bookmarks or separators.
+ switch (newItemData.type || PlacesUtils.bookmarks.TYPE_BOOKMARK) {
+ case PlacesUtils.bookmarks.TYPE_BOOKMARK:
+ let isQuery = newItemData.url.protocol == "place:";
+ if (isQuery) {
+ Assert.ok(node, "Should be able to find the updated node");
+ break;
+ }
+ // Fallthrough if this isn't a query
+ case PlacesUtils.bookmarks.TYPE_SEPARATOR:
+ Assert.ok(!node, "Should not be able to find the updated node");
+ break;
+ default:
+ Assert.ok(node, "Should be able to find the updated node");
+ }
+
+ if (node) {
+ Assert.equal(title, newItemData.title, "Should have the correct title");
+ Assert.equal(index, expectedIndex, "Should have the expected index");
+ }
+}
+
+async function removeAndCheckItem(itemData) {
+ await PlacesUtils.bookmarks.remove(itemData);
+ let [node] = getNodeForTreeItem(
+ itemData.guid,
+ gLibrary.PlacesOrganizer._places
+ );
+ Assert.ok(!node, "Should not be able to find the removed node");
+}
+
+/**
+ * Get places node, index and cell text for a guid in a tree view.
+ *
+ * @param {string} aItemGuid
+ * item guid of the item to search.
+ * @param {object} aTree
+ * Tree to search in.
+ * @returns {Array}
+ * [node, index, cellText] or [null, null, ""] if not found.
+ */
+function getNodeForTreeItem(aItemGuid, aTree) {
+ function findNode(aContainerIndex) {
+ if (aTree.view.isContainerEmpty(aContainerIndex)) {
+ return [null, null, ""];
+ }
+
+ // The rowCount limit is just for sanity, but we will end looping when
+ // we have checked the last child of this container or we have found node.
+ for (let i = aContainerIndex + 1; i < aTree.view.rowCount; i++) {
+ let node = aTree.view.nodeForTreeIndex(i);
+
+ if (node.bookmarkGuid == aItemGuid) {
+ // Minus one because we want relative index inside the container.
+ let tree = gLibrary.PlacesOrganizer._places;
+ let cellText = tree.view.getCellText(i, tree.columns.getColumnAt(0));
+ return [node, i - aContainerIndex - 1, cellText];
+ }
+
+ if (PlacesUtils.nodeIsFolder(node)) {
+ // Open container.
+ aTree.view.toggleOpenState(i);
+ // Search inside it.
+ let foundNode = findNode(i);
+ // Close container.
+ aTree.view.toggleOpenState(i);
+ // Return node if found.
+ if (foundNode[0] != null) {
+ return foundNode;
+ }
+ }
+
+ // We have finished walking this container.
+ if (!aTree.view.hasNextSibling(aContainerIndex + 1, i)) {
+ break;
+ }
+ }
+ return [null, null, ""];
+ }
+
+ // Root node is hidden, so we need to manually walk the first level.
+ for (let i = 0; i < aTree.view.rowCount; i++) {
+ // Open container.
+ aTree.view.toggleOpenState(i);
+ // Search inside it.
+ let foundNode = findNode(i);
+ // Close container.
+ aTree.view.toggleOpenState(i);
+ // Return node if found.
+ if (foundNode[0] != null) {
+ return foundNode;
+ }
+ }
+ return [null, null, ""];
+}