michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: // Tests that each nsINavBookmarksObserver method gets the correct input. michael@0: michael@0: let gBookmarksObserver = { michael@0: expected: [], michael@0: validate: function (aMethodName, aArguments) { michael@0: do_check_eq(this.expected[0].name, aMethodName); michael@0: michael@0: let args = this.expected.shift().args; michael@0: do_check_eq(aArguments.length, args.length); michael@0: for (let i = 0; i < aArguments.length; i++) { michael@0: do_log_info(aMethodName + "(args[" + i + "]: " + args[i].name + ")"); michael@0: do_check_true(args[i].check(aArguments[i])); michael@0: } michael@0: michael@0: if (this.expected.length == 0) { michael@0: run_next_test(); michael@0: } michael@0: }, michael@0: michael@0: // nsINavBookmarkObserver michael@0: onBeginUpdateBatch: function onBeginUpdateBatch() michael@0: this.validate(arguments.callee.name, arguments), michael@0: onEndUpdateBatch: function onEndUpdateBatch() michael@0: this.validate(arguments.callee.name, arguments), michael@0: onItemAdded: function onItemAdded() michael@0: this.validate(arguments.callee.name, arguments), michael@0: onItemRemoved: function onItemRemoved() michael@0: this.validate(arguments.callee.name, arguments), michael@0: onItemChanged: function onItemChanged() michael@0: this.validate(arguments.callee.name, arguments), michael@0: onItemVisited: function onItemVisited() michael@0: this.validate(arguments.callee.name, arguments), michael@0: onItemMoved: function onItemMoved() michael@0: this.validate(arguments.callee.name, arguments), michael@0: michael@0: // nsISupports michael@0: QueryInterface: XPCOMUtils.generateQI([Ci.nsINavBookmarkObserver]), michael@0: } michael@0: michael@0: add_test(function batch() { michael@0: gBookmarksObserver.expected = [ michael@0: { name: "onBeginUpdateBatch", michael@0: args: [] }, michael@0: { name: "onEndUpdateBatch", michael@0: args: [] }, michael@0: ]; michael@0: PlacesUtils.bookmarks.runInBatchMode({ michael@0: runBatched: function () { michael@0: // Nothing. michael@0: } michael@0: }, null); michael@0: }); michael@0: michael@0: add_test(function onItemAdded_bookmark() { michael@0: const TITLE = "Bookmark 1"; michael@0: let uri = NetUtil.newURI("http://1.mozilla.org/"); michael@0: gBookmarksObserver.expected = [ michael@0: { name: "onItemAdded", michael@0: args: [ michael@0: { name: "itemId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "parentId", check: function (v) v === PlacesUtils.unfiledBookmarksFolderId }, michael@0: { name: "index", check: function (v) v === 0 }, michael@0: { name: "itemType", check: function (v) v === PlacesUtils.bookmarks.TYPE_BOOKMARK }, michael@0: { name: "uri", check: function (v) v instanceof Ci.nsIURI && v.equals(uri) }, michael@0: { name: "title", check: function (v) v === TITLE }, michael@0: { name: "dateAdded", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "guid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: { name: "parentGuid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: ] }, michael@0: ]; michael@0: PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId, michael@0: uri, PlacesUtils.bookmarks.DEFAULT_INDEX, michael@0: TITLE); michael@0: }); michael@0: michael@0: add_test(function onItemAdded_separator() { michael@0: gBookmarksObserver.expected = [ michael@0: { name: "onItemAdded", michael@0: args: [ michael@0: { name: "itemId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "parentId", check: function (v) v === PlacesUtils.unfiledBookmarksFolderId }, michael@0: { name: "index", check: function (v) v === 1 }, michael@0: { name: "itemType", check: function (v) v === PlacesUtils.bookmarks.TYPE_SEPARATOR }, michael@0: { name: "uri", check: function (v) v === null }, michael@0: { name: "title", check: function (v) v === null }, michael@0: { name: "dateAdded", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "guid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: { name: "parentGuid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: ] }, michael@0: ]; michael@0: PlacesUtils.bookmarks.insertSeparator(PlacesUtils.unfiledBookmarksFolderId, michael@0: PlacesUtils.bookmarks.DEFAULT_INDEX); michael@0: }); michael@0: michael@0: add_test(function onItemAdded_folder() { michael@0: const TITLE = "Folder 1"; michael@0: gBookmarksObserver.expected = [ michael@0: { name: "onItemAdded", michael@0: args: [ michael@0: { name: "itemId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "parentId", check: function (v) v === PlacesUtils.unfiledBookmarksFolderId }, michael@0: { name: "index", check: function (v) v === 2 }, michael@0: { name: "itemType", check: function (v) v === PlacesUtils.bookmarks.TYPE_FOLDER }, michael@0: { name: "uri", check: function (v) v === null }, michael@0: { name: "title", check: function (v) v === TITLE }, michael@0: { name: "dateAdded", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "guid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: { name: "parentGuid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: ] }, michael@0: ]; michael@0: PlacesUtils.bookmarks.createFolder(PlacesUtils.unfiledBookmarksFolderId, michael@0: TITLE, michael@0: PlacesUtils.bookmarks.DEFAULT_INDEX); michael@0: }); michael@0: michael@0: add_test(function onItemChanged_title_bookmark() { michael@0: let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0); michael@0: let uri = PlacesUtils.bookmarks.getBookmarkURI(id); michael@0: const TITLE = "New title"; michael@0: gBookmarksObserver.expected = [ michael@0: { name: "onItemChanged", // This is an unfortunate effect of bug 653910. michael@0: args: [ michael@0: { name: "itemId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "property", check: function (v) v === "title" }, michael@0: { name: "isAnno", check: function (v) v === false }, michael@0: { name: "newValue", check: function (v) v === TITLE }, michael@0: { name: "lastModified", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "itemType", check: function (v) v === PlacesUtils.bookmarks.TYPE_BOOKMARK }, michael@0: { name: "parentId", check: function (v) v === PlacesUtils.unfiledBookmarksFolderId }, michael@0: { name: "guid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: { name: "parentGuid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: ] }, michael@0: ]; michael@0: PlacesUtils.bookmarks.setItemTitle(id, TITLE); michael@0: }); michael@0: michael@0: add_test(function onItemChanged_tags_bookmark() { michael@0: let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0); michael@0: let uri = PlacesUtils.bookmarks.getBookmarkURI(id); michael@0: const TITLE = "New title"; michael@0: const TAG = "tag" michael@0: gBookmarksObserver.expected = [ michael@0: { name: "onBeginUpdateBatch", // Tag addition uses a batch. michael@0: args: [] }, michael@0: { name: "onItemAdded", // This is the tag folder. michael@0: args: [ michael@0: { name: "itemId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "parentId", check: function (v) v === PlacesUtils.tagsFolderId }, michael@0: { name: "index", check: function (v) v === 0 }, michael@0: { name: "itemType", check: function (v) v === PlacesUtils.bookmarks.TYPE_FOLDER }, michael@0: { name: "uri", check: function (v) v === null }, michael@0: { name: "title", check: function (v) v === TAG }, michael@0: { name: "dateAdded", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "guid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: { name: "parentGuid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: ] }, michael@0: { name: "onItemAdded", // This is the tag. michael@0: args: [ michael@0: { name: "itemId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "parentId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "index", check: function (v) v === 0 }, michael@0: { name: "itemType", check: function (v) v === PlacesUtils.bookmarks.TYPE_BOOKMARK }, michael@0: { name: "uri", check: function (v) v instanceof Ci.nsIURI && v.equals(uri) }, michael@0: { name: "title", check: function (v) v === null }, michael@0: { name: "dateAdded", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "guid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: { name: "parentGuid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: ] }, michael@0: { name: "onItemChanged", michael@0: args: [ michael@0: { name: "itemId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "property", check: function (v) v === "tags" }, michael@0: { name: "isAnno", check: function (v) v === false }, michael@0: { name: "newValue", check: function (v) v === "" }, michael@0: { name: "lastModified", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "itemType", check: function (v) v === PlacesUtils.bookmarks.TYPE_BOOKMARK }, michael@0: { name: "parentId", check: function (v) v === PlacesUtils.unfiledBookmarksFolderId }, michael@0: { name: "guid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: { name: "parentGuid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: ] }, michael@0: { name: "onEndUpdateBatch", michael@0: args: [] }, michael@0: { name: "onBeginUpdateBatch", // Tag removal uses a batch. michael@0: args: [] }, michael@0: { name: "onItemRemoved", // This is the tag. michael@0: args: [ michael@0: { name: "itemId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "parentId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "index", check: function (v) v === 0 }, michael@0: { name: "itemType", check: function (v) v === PlacesUtils.bookmarks.TYPE_BOOKMARK }, michael@0: { name: "uri", check: function (v) v instanceof Ci.nsIURI && v.equals(uri) }, michael@0: { name: "guid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: { name: "parentGuid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: ] }, michael@0: { name: "onItemRemoved", // This is the tag folder. michael@0: args: [ michael@0: { name: "itemId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "parentId", check: function (v) v === PlacesUtils.tagsFolderId }, michael@0: { name: "index", check: function (v) v === 0 }, michael@0: { name: "itemType", check: function (v) v === PlacesUtils.bookmarks.TYPE_FOLDER }, michael@0: { name: "uri", check: function (v) v === null }, michael@0: { name: "guid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: { name: "parentGuid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: ] }, michael@0: { name: "onItemChanged", michael@0: args: [ michael@0: { name: "itemId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "property", check: function (v) v === "tags" }, michael@0: { name: "isAnno", check: function (v) v === false }, michael@0: { name: "newValue", check: function (v) v === "" }, michael@0: { name: "lastModified", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "itemType", check: function (v) v === PlacesUtils.bookmarks.TYPE_BOOKMARK }, michael@0: { name: "parentId", check: function (v) v === PlacesUtils.unfiledBookmarksFolderId }, michael@0: { name: "guid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: { name: "parentGuid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: ] }, michael@0: { name: "onEndUpdateBatch", michael@0: args: [] }, michael@0: ]; michael@0: PlacesUtils.tagging.tagURI(uri, [TAG]); michael@0: PlacesUtils.tagging.untagURI(uri, [TAG]); michael@0: }); michael@0: michael@0: add_test(function onItemMoved_bookmark() { michael@0: let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0); michael@0: let uri = PlacesUtils.bookmarks.getBookmarkURI(id); michael@0: gBookmarksObserver.expected = [ michael@0: { name: "onItemMoved", michael@0: args: [ michael@0: { name: "itemId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "oldParentId", check: function (v) v === PlacesUtils.unfiledBookmarksFolderId }, michael@0: { name: "oldIndex", check: function (v) v === 0 }, michael@0: { name: "newParentId", check: function (v) v === PlacesUtils.toolbarFolderId }, michael@0: { name: "newIndex", check: function (v) v === 0 }, michael@0: { name: "itemType", check: function (v) v === PlacesUtils.bookmarks.TYPE_BOOKMARK }, michael@0: { name: "guid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: { name: "oldParentGuid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: { name: "newParentGuid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: ] }, michael@0: { name: "onItemMoved", michael@0: args: [ michael@0: { name: "itemId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "oldParentId", check: function (v) v === PlacesUtils.toolbarFolderId }, michael@0: { name: "oldIndex", check: function (v) v === 0 }, michael@0: { name: "newParentId", check: function (v) v === PlacesUtils.unfiledBookmarksFolderId }, michael@0: { name: "newIndex", check: function (v) v === 0 }, michael@0: { name: "itemType", check: function (v) v === PlacesUtils.bookmarks.TYPE_BOOKMARK }, michael@0: { name: "guid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: { name: "oldParentGuid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: { name: "newParentGuid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: ] }, michael@0: ]; michael@0: PlacesUtils.bookmarks.moveItem(id, PlacesUtils.toolbarFolderId, 0); michael@0: PlacesUtils.bookmarks.moveItem(id, PlacesUtils.unfiledBookmarksFolderId, 0); michael@0: }); michael@0: michael@0: add_test(function onItemMoved_bookmark() { michael@0: let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0); michael@0: let uri = PlacesUtils.bookmarks.getBookmarkURI(id); michael@0: gBookmarksObserver.expected = [ michael@0: { name: "onItemVisited", michael@0: args: [ michael@0: { name: "itemId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "visitId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "time", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "transitionType", check: function (v) v === PlacesUtils.history.TRANSITION_TYPED }, michael@0: { name: "uri", check: function (v) v instanceof Ci.nsIURI && v.equals(uri) }, michael@0: { name: "parentId", check: function (v) v === PlacesUtils.unfiledBookmarksFolderId }, michael@0: { name: "guid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: { name: "parentGuid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: ] }, michael@0: ]; michael@0: promiseAddVisits({ uri: uri, transition: TRANSITION_TYPED }); michael@0: }); michael@0: michael@0: add_test(function onItemRemoved_bookmark() { michael@0: let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0); michael@0: let uri = PlacesUtils.bookmarks.getBookmarkURI(id); michael@0: gBookmarksObserver.expected = [ michael@0: { name: "onItemChanged", // This is an unfortunate effect of bug 653910. michael@0: args: [ michael@0: { name: "itemId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "property", check: function (v) v === "" }, michael@0: { name: "isAnno", check: function (v) v === true }, michael@0: { name: "newValue", check: function (v) v === "" }, michael@0: { name: "lastModified", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "itemType", check: function (v) v === PlacesUtils.bookmarks.TYPE_BOOKMARK }, michael@0: { name: "parentId", check: function (v) v === PlacesUtils.unfiledBookmarksFolderId }, michael@0: { name: "guid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: { name: "parentGuid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: ] }, michael@0: { name: "onItemRemoved", michael@0: args: [ michael@0: { name: "itemId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "parentId", check: function (v) v === PlacesUtils.unfiledBookmarksFolderId }, michael@0: { name: "index", check: function (v) v === 0 }, michael@0: { name: "itemType", check: function (v) v === PlacesUtils.bookmarks.TYPE_BOOKMARK }, michael@0: { name: "uri", check: function (v) v instanceof Ci.nsIURI && v.equals(uri) }, michael@0: { name: "guid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: { name: "parentGuid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: ] }, michael@0: ]; michael@0: PlacesUtils.bookmarks.removeItem(id); michael@0: }); michael@0: michael@0: add_test(function onItemRemoved_separator() { michael@0: let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0); michael@0: gBookmarksObserver.expected = [ michael@0: { name: "onItemChanged", // This is an unfortunate effect of bug 653910. michael@0: args: [ michael@0: { name: "itemId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "property", check: function (v) v === "" }, michael@0: { name: "isAnno", check: function (v) v === true }, michael@0: { name: "newValue", check: function (v) v === "" }, michael@0: { name: "lastModified", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "itemType", check: function (v) v === PlacesUtils.bookmarks.TYPE_SEPARATOR }, michael@0: { name: "parentId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "guid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: { name: "parentGuid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: ] }, michael@0: { name: "onItemRemoved", michael@0: args: [ michael@0: { name: "itemId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "parentId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "index", check: function (v) v === 0 }, michael@0: { name: "itemType", check: function (v) v === PlacesUtils.bookmarks.TYPE_SEPARATOR }, michael@0: { name: "uri", check: function (v) v === null }, michael@0: { name: "guid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: { name: "parentGuid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: ] }, michael@0: ]; michael@0: PlacesUtils.bookmarks.removeItem(id); michael@0: }); michael@0: michael@0: add_test(function onItemRemoved_folder() { michael@0: let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0); michael@0: const TITLE = "Folder 2"; michael@0: gBookmarksObserver.expected = [ michael@0: { name: "onItemChanged", // This is an unfortunate effect of bug 653910. michael@0: args: [ michael@0: { name: "itemId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "property", check: function (v) v === "" }, michael@0: { name: "isAnno", check: function (v) v === true }, michael@0: { name: "newValue", check: function (v) v === "" }, michael@0: { name: "lastModified", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "itemType", check: function (v) v === PlacesUtils.bookmarks.TYPE_FOLDER }, michael@0: { name: "parentId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "guid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: { name: "parentGuid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: ] }, michael@0: { name: "onItemRemoved", michael@0: args: [ michael@0: { name: "itemId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "parentId", check: function (v) typeof(v) == "number" && v > 0 }, michael@0: { name: "index", check: function (v) v === 0 }, michael@0: { name: "itemType", check: function (v) v === PlacesUtils.bookmarks.TYPE_FOLDER }, michael@0: { name: "uri", check: function (v) v === null }, michael@0: { name: "guid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: { name: "parentGuid", check: function (v) typeof(v) == "string" && /^[a-zA-Z0-9\-_]{12}$/.test(v) }, michael@0: ] }, michael@0: ]; michael@0: PlacesUtils.bookmarks.removeItem(id); michael@0: }); michael@0: michael@0: function run_test() { michael@0: PlacesUtils.bookmarks.addObserver(gBookmarksObserver, false); michael@0: run_next_test(); michael@0: } michael@0: michael@0: do_register_cleanup(function () { michael@0: PlacesUtils.bookmarks.removeObserver(gBookmarksObserver); michael@0: });