diff options
Diffstat (limited to 'toolkit/components/places/tests/unit/test_placesTxn.js')
-rw-r--r-- | toolkit/components/places/tests/unit/test_placesTxn.js | 937 |
1 files changed, 937 insertions, 0 deletions
diff --git a/toolkit/components/places/tests/unit/test_placesTxn.js b/toolkit/components/places/tests/unit/test_placesTxn.js new file mode 100644 index 000000000..3cc9809bb --- /dev/null +++ b/toolkit/components/places/tests/unit/test_placesTxn.js @@ -0,0 +1,937 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* 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/. */ + +var bmsvc = PlacesUtils.bookmarks; +var tagssvc = PlacesUtils.tagging; +var annosvc = PlacesUtils.annotations; +var txnManager = PlacesUtils.transactionManager; +const DESCRIPTION_ANNO = "bookmarkProperties/description"; + +function* promiseKeyword(keyword, href, postData) { + while (true) { + let entry = yield PlacesUtils.keywords.fetch(keyword); + if (href == null && !entry) + break; + if (entry && entry.url.href == href && entry.postData == postData) { + break; + } + + yield new Promise(resolve => do_timeout(100, resolve)); + } +} + +// create and add bookmarks observer +var observer = { + + onBeginUpdateBatch: function() { + this._beginUpdateBatch = true; + }, + _beginUpdateBatch: false, + + onEndUpdateBatch: function() { + this._endUpdateBatch = true; + }, + _endUpdateBatch: false, + + onItemAdded: function(id, folder, index, itemType, uri) { + this._itemAddedId = id; + this._itemAddedParent = folder; + this._itemAddedIndex = index; + this._itemAddedType = itemType; + }, + _itemAddedId: null, + _itemAddedParent: null, + _itemAddedIndex: null, + _itemAddedType: null, + + onItemRemoved: function(id, folder, index, itemType) { + this._itemRemovedId = id; + this._itemRemovedFolder = folder; + this._itemRemovedIndex = index; + }, + _itemRemovedId: null, + _itemRemovedFolder: null, + _itemRemovedIndex: null, + + onItemChanged: function(id, property, isAnnotationProperty, newValue, + lastModified, itemType) { + // The transaction manager is being rewritten in bug 891303, so just + // skip checking this for now. + if (property == "tags") + return; + this._itemChangedId = id; + this._itemChangedProperty = property; + this._itemChanged_isAnnotationProperty = isAnnotationProperty; + this._itemChangedValue = newValue; + }, + _itemChangedId: null, + _itemChangedProperty: null, + _itemChanged_isAnnotationProperty: null, + _itemChangedValue: null, + + onItemVisited: function(id, visitID, time) { + this._itemVisitedId = id; + this._itemVisitedVistId = visitID; + this._itemVisitedTime = time; + }, + _itemVisitedId: null, + _itemVisitedVistId: null, + _itemVisitedTime: null, + + onItemMoved: function(id, oldParent, oldIndex, newParent, newIndex, + itemType) { + this._itemMovedId = id; + this._itemMovedOldParent = oldParent; + this._itemMovedOldIndex = oldIndex; + this._itemMovedNewParent = newParent; + this._itemMovedNewIndex = newIndex; + }, + _itemMovedId: null, + _itemMovedOldParent: null, + _itemMovedOldIndex: null, + _itemMovedNewParent: null, + _itemMovedNewIndex: null, + + QueryInterface: function(iid) { + if (iid.equals(Ci.nsINavBookmarkObserver) || + iid.equals(Ci.nsISupports)) { + return this; + } + throw Cr.NS_ERROR_NO_INTERFACE; + } +}; + +// index at which items should begin +var bmStartIndex = 0; + +// get bookmarks root id +var root = PlacesUtils.bookmarksMenuFolderId; + +add_task(function* init() { + bmsvc.addObserver(observer, false); + do_register_cleanup(function () { + bmsvc.removeObserver(observer); + }); +}); + +add_task(function* test_create_folder_with_description() { + const TEST_FOLDERNAME = "Test creating a folder with a description"; + const TEST_DESCRIPTION = "this is my test description"; + + let annos = [{ name: DESCRIPTION_ANNO, + type: annosvc.TYPE_STRING, + flags: 0, + value: TEST_DESCRIPTION, + expires: annosvc.EXPIRE_NEVER }]; + let txn = new PlacesCreateFolderTransaction(TEST_FOLDERNAME, root, bmStartIndex, annos); + txnManager.doTransaction(txn); + + // This checks that calling undoTransaction on an "empty batch" doesn't + // undo the previous transaction (getItemTitle will fail) + txnManager.beginBatch(null); + txnManager.endBatch(false); + txnManager.undoTransaction(); + + let folderId = observer._itemAddedId; + do_check_eq(bmsvc.getItemTitle(folderId), TEST_FOLDERNAME); + do_check_eq(observer._itemAddedIndex, bmStartIndex); + do_check_eq(observer._itemAddedParent, root); + do_check_eq(observer._itemAddedId, folderId); + do_check_eq(TEST_DESCRIPTION, annosvc.getItemAnnotation(folderId, DESCRIPTION_ANNO)); + + txn.undoTransaction(); + do_check_eq(observer._itemRemovedId, folderId); + do_check_eq(observer._itemRemovedFolder, root); + do_check_eq(observer._itemRemovedIndex, bmStartIndex); + + txn.redoTransaction(); + do_check_eq(observer._itemAddedIndex, bmStartIndex); + do_check_eq(observer._itemAddedParent, root); + do_check_eq(observer._itemAddedId, folderId); + + txn.undoTransaction(); + do_check_eq(observer._itemRemovedId, folderId); + do_check_eq(observer._itemRemovedFolder, root); + do_check_eq(observer._itemRemovedIndex, bmStartIndex); +}); + +add_task(function* test_create_item() { + let testURI = NetUtil.newURI("http://test_create_item.com"); + + let txn = new PlacesCreateBookmarkTransaction(testURI, root, bmStartIndex, + "Test creating an item"); + + txnManager.doTransaction(txn); + let id = bmsvc.getBookmarkIdsForURI(testURI)[0]; + do_check_eq(observer._itemAddedId, id); + do_check_eq(observer._itemAddedIndex, bmStartIndex); + do_check_true(bmsvc.isBookmarked(testURI)); + + txn.undoTransaction(); + do_check_eq(observer._itemRemovedId, id); + do_check_eq(observer._itemRemovedIndex, bmStartIndex); + do_check_false(bmsvc.isBookmarked(testURI)); + + txn.redoTransaction(); + do_check_true(bmsvc.isBookmarked(testURI)); + let newId = bmsvc.getBookmarkIdsForURI(testURI)[0]; + do_check_eq(observer._itemAddedIndex, bmStartIndex); + do_check_eq(observer._itemAddedParent, root); + do_check_eq(observer._itemAddedId, newId); + + txn.undoTransaction(); + do_check_eq(observer._itemRemovedId, newId); + do_check_eq(observer._itemRemovedFolder, root); + do_check_eq(observer._itemRemovedIndex, bmStartIndex); +}); + +add_task(function* test_create_item_to_folder() { + const TEST_FOLDERNAME = "Test creating item to a folder"; + let testURI = NetUtil.newURI("http://test_create_item_to_folder.com"); + let folderId = bmsvc.createFolder(root, TEST_FOLDERNAME, bmsvc.DEFAULT_INDEX); + + let txn = new PlacesCreateBookmarkTransaction(testURI, folderId, bmStartIndex, + "Test creating item"); + txnManager.doTransaction(txn); + let bkmId = bmsvc.getBookmarkIdsForURI(testURI)[0]; + do_check_eq(observer._itemAddedId, bkmId); + do_check_eq(observer._itemAddedIndex, bmStartIndex); + do_check_true(bmsvc.isBookmarked(testURI)); + + txn.undoTransaction(); + do_check_eq(observer._itemRemovedId, bkmId); + do_check_eq(observer._itemRemovedIndex, bmStartIndex); + + txn.redoTransaction(); + let newBkmId = bmsvc.getBookmarkIdsForURI(testURI)[0]; + do_check_eq(observer._itemAddedIndex, bmStartIndex); + do_check_eq(observer._itemAddedParent, folderId); + do_check_eq(observer._itemAddedId, newBkmId); + + txn.undoTransaction(); + do_check_eq(observer._itemRemovedId, newBkmId); + do_check_eq(observer._itemRemovedFolder, folderId); + do_check_eq(observer._itemRemovedIndex, bmStartIndex); +}); + +add_task(function* test_move_items_to_folder() { + let testFolderId = bmsvc.createFolder(root, "Test move items", bmsvc.DEFAULT_INDEX); + let testURI = NetUtil.newURI("http://test_move_items.com"); + let testBkmId = bmsvc.insertBookmark(testFolderId, testURI, bmsvc.DEFAULT_INDEX, "1: Test move items"); + bmsvc.insertBookmark(testFolderId, testURI, bmsvc.DEFAULT_INDEX, "2: Test move items"); + + // Moving items between the same folder + let sameTxn = new PlacesMoveItemTransaction(testBkmId, testFolderId, bmsvc.DEFAULT_INDEX); + + sameTxn.doTransaction(); + do_check_eq(observer._itemMovedId, testBkmId); + do_check_eq(observer._itemMovedOldParent, testFolderId); + do_check_eq(observer._itemMovedOldIndex, 0); + do_check_eq(observer._itemMovedNewParent, testFolderId); + do_check_eq(observer._itemMovedNewIndex, 1); + + sameTxn.undoTransaction(); + do_check_eq(observer._itemMovedId, testBkmId); + do_check_eq(observer._itemMovedOldParent, testFolderId); + do_check_eq(observer._itemMovedOldIndex, 1); + do_check_eq(observer._itemMovedNewParent, testFolderId); + do_check_eq(observer._itemMovedNewIndex, 0); + + sameTxn.redoTransaction(); + do_check_eq(observer._itemMovedId, testBkmId); + do_check_eq(observer._itemMovedOldParent, testFolderId); + do_check_eq(observer._itemMovedOldIndex, 0); + do_check_eq(observer._itemMovedNewParent, testFolderId); + do_check_eq(observer._itemMovedNewIndex, 1); + + sameTxn.undoTransaction(); + do_check_eq(observer._itemMovedId, testBkmId); + do_check_eq(observer._itemMovedOldParent, testFolderId); + do_check_eq(observer._itemMovedOldIndex, 1); + do_check_eq(observer._itemMovedNewParent, testFolderId); + do_check_eq(observer._itemMovedNewIndex, 0); + + // Moving items between different folders + let folderId = bmsvc.createFolder(testFolderId, + "Test move items between different folders", + bmsvc.DEFAULT_INDEX); + let diffTxn = new PlacesMoveItemTransaction(testBkmId, folderId, bmsvc.DEFAULT_INDEX); + + diffTxn.doTransaction(); + do_check_eq(observer._itemMovedId, testBkmId); + do_check_eq(observer._itemMovedOldParent, testFolderId); + do_check_eq(observer._itemMovedOldIndex, 0); + do_check_eq(observer._itemMovedNewParent, folderId); + do_check_eq(observer._itemMovedNewIndex, 0); + + sameTxn.undoTransaction(); + do_check_eq(observer._itemMovedId, testBkmId); + do_check_eq(observer._itemMovedOldParent, folderId); + do_check_eq(observer._itemMovedOldIndex, 0); + do_check_eq(observer._itemMovedNewParent, testFolderId); + do_check_eq(observer._itemMovedNewIndex, 0); + + diffTxn.redoTransaction(); + do_check_eq(observer._itemMovedId, testBkmId); + do_check_eq(observer._itemMovedOldParent, testFolderId); + do_check_eq(observer._itemMovedOldIndex, 0); + do_check_eq(observer._itemMovedNewParent, folderId); + do_check_eq(observer._itemMovedNewIndex, 0); + + sameTxn.undoTransaction(); + do_check_eq(observer._itemMovedId, testBkmId); + do_check_eq(observer._itemMovedOldParent, folderId); + do_check_eq(observer._itemMovedOldIndex, 0); + do_check_eq(observer._itemMovedNewParent, testFolderId); + do_check_eq(observer._itemMovedNewIndex, 0); +}); + +add_task(function* test_remove_folder() { + let testFolder = bmsvc.createFolder(root, "Test Removing a Folder", bmsvc.DEFAULT_INDEX); + let folderId = bmsvc.createFolder(testFolder, "Removed Folder", bmsvc.DEFAULT_INDEX); + + let txn = new PlacesRemoveItemTransaction(folderId); + + txn.doTransaction(); + do_check_eq(observer._itemRemovedId, folderId); + do_check_eq(observer._itemRemovedFolder, testFolder); + do_check_eq(observer._itemRemovedIndex, 0); + + txn.undoTransaction(); + do_check_eq(observer._itemAddedId, folderId); + do_check_eq(observer._itemAddedParent, testFolder); + do_check_eq(observer._itemAddedIndex, 0); + + txn.redoTransaction(); + do_check_eq(observer._itemRemovedId, folderId); + do_check_eq(observer._itemRemovedFolder, testFolder); + do_check_eq(observer._itemRemovedIndex, 0); + + txn.undoTransaction(); + do_check_eq(observer._itemAddedId, folderId); + do_check_eq(observer._itemAddedParent, testFolder); + do_check_eq(observer._itemAddedIndex, 0); +}); + +add_task(function* test_remove_item_with_tag() { + // Notice in this case the tag persists since other bookmarks have same uri. + let testFolder = bmsvc.createFolder(root, "Test removing an item with a tag", + bmsvc.DEFAULT_INDEX); + + const TAG_NAME = "tag-test_remove_item_with_tag"; + let testURI = NetUtil.newURI("http://test_remove_item_with_tag.com"); + let testBkmId = bmsvc.insertBookmark(testFolder, testURI, bmsvc.DEFAULT_INDEX, "test-item1"); + + // create bookmark for not removing tag. + bmsvc.insertBookmark(testFolder, testURI, bmsvc.DEFAULT_INDEX, "test-item2"); + + // set tag + tagssvc.tagURI(testURI, [TAG_NAME]); + + let txn = new PlacesRemoveItemTransaction(testBkmId); + + txn.doTransaction(); + do_check_eq(observer._itemRemovedId, testBkmId); + do_check_eq(observer._itemRemovedFolder, testFolder); + do_check_eq(observer._itemRemovedIndex, 0); + do_check_eq(tagssvc.getTagsForURI(testURI), TAG_NAME); + + txn.undoTransaction(); + let newbkmk2Id = observer._itemAddedId; + do_check_eq(observer._itemAddedParent, testFolder); + do_check_eq(observer._itemAddedIndex, 0); + do_check_eq(tagssvc.getTagsForURI(testURI)[0], TAG_NAME); + + txn.redoTransaction(); + do_check_eq(observer._itemRemovedId, newbkmk2Id); + do_check_eq(observer._itemRemovedFolder, testFolder); + do_check_eq(observer._itemRemovedIndex, 0); + do_check_eq(tagssvc.getTagsForURI(testURI)[0], TAG_NAME); + + txn.undoTransaction(); + do_check_eq(observer._itemAddedParent, testFolder); + do_check_eq(observer._itemAddedIndex, 0); + do_check_eq(tagssvc.getTagsForURI(testURI)[0], TAG_NAME); +}); + +add_task(function* test_remove_item_with_keyword() { + // Notice in this case the tag persists since other bookmarks have same uri. + let testFolder = bmsvc.createFolder(root, "Test removing an item with a keyword", + bmsvc.DEFAULT_INDEX); + + const KEYWORD = "test: test removing an item with a keyword"; + let testURI = NetUtil.newURI("http://test_remove_item_with_keyword.com"); + let testBkmId = bmsvc.insertBookmark(testFolder, testURI, bmsvc.DEFAULT_INDEX, "test-item1"); + + // set keyword + yield PlacesUtils.keywords.insert({ url: testURI.spec, keyword: KEYWORD}); + + let txn = new PlacesRemoveItemTransaction(testBkmId); + + txn.doTransaction(); + do_check_eq(observer._itemRemovedId, testBkmId); + do_check_eq(observer._itemRemovedFolder, testFolder); + do_check_eq(observer._itemRemovedIndex, 0); + yield promiseKeyword(KEYWORD, null); + + txn.undoTransaction(); + let newbkmk2Id = observer._itemAddedId; + do_check_eq(observer._itemAddedParent, testFolder); + do_check_eq(observer._itemAddedIndex, 0); + yield promiseKeyword(KEYWORD, testURI.spec); + + txn.redoTransaction(); + do_check_eq(observer._itemRemovedId, newbkmk2Id); + do_check_eq(observer._itemRemovedFolder, testFolder); + do_check_eq(observer._itemRemovedIndex, 0); + yield promiseKeyword(KEYWORD, null); + + txn.undoTransaction(); + do_check_eq(observer._itemAddedParent, testFolder); + do_check_eq(observer._itemAddedIndex, 0); +}); + +add_task(function* test_creating_separator() { + let testFolder = bmsvc.createFolder(root, "Test creating a separator", bmsvc.DEFAULT_INDEX); + + let txn = new PlacesCreateSeparatorTransaction(testFolder, 0); + txn.doTransaction(); + + let sepId = observer._itemAddedId; + do_check_eq(observer._itemAddedIndex, 0); + do_check_eq(observer._itemAddedParent, testFolder); + + txn.undoTransaction(); + do_check_eq(observer._itemRemovedId, sepId); + do_check_eq(observer._itemRemovedFolder, testFolder); + do_check_eq(observer._itemRemovedIndex, 0); + + txn.redoTransaction(); + let newSepId = observer._itemAddedId; + do_check_eq(observer._itemAddedIndex, 0); + do_check_eq(observer._itemAddedParent, testFolder); + + txn.undoTransaction(); + do_check_eq(observer._itemRemovedId, newSepId); + do_check_eq(observer._itemRemovedFolder, testFolder); + do_check_eq(observer._itemRemovedIndex, 0); +}); + +add_task(function* test_removing_separator() { + let testFolder = bmsvc.createFolder(root, "Test removing a separator", bmsvc.DEFAULT_INDEX); + + let sepId = bmsvc.insertSeparator(testFolder, 0); + let txn = new PlacesRemoveItemTransaction(sepId); + + txn.doTransaction(); + do_check_eq(observer._itemRemovedId, sepId); + do_check_eq(observer._itemRemovedFolder, testFolder); + do_check_eq(observer._itemRemovedIndex, 0); + + txn.undoTransaction(); + do_check_eq(observer._itemAddedId, sepId); // New separator created + do_check_eq(observer._itemAddedParent, testFolder); + do_check_eq(observer._itemAddedIndex, 0); + + txn.redoTransaction(); + do_check_eq(observer._itemRemovedId, sepId); + do_check_eq(observer._itemRemovedFolder, testFolder); + do_check_eq(observer._itemRemovedIndex, 0); + + txn.undoTransaction(); + do_check_eq(observer._itemAddedId, sepId); // New separator created + do_check_eq(observer._itemAddedParent, testFolder); + do_check_eq(observer._itemAddedIndex, 0); +}); + +add_task(function* test_editing_item_title() { + const TITLE = "Test editing item title"; + const MOD_TITLE = "Mod: Test editing item title"; + let testURI = NetUtil.newURI("http://www.test_editing_item_title.com"); + let testBkmId = bmsvc.insertBookmark(root, testURI, bmsvc.DEFAULT_INDEX, TITLE); + + let txn = new PlacesEditItemTitleTransaction(testBkmId, MOD_TITLE); + + txn.doTransaction(); + do_check_eq(observer._itemChangedId, testBkmId); + do_check_eq(observer._itemChangedProperty, "title"); + do_check_eq(observer._itemChangedValue, MOD_TITLE); + + txn.undoTransaction(); + do_check_eq(observer._itemChangedId, testBkmId); + do_check_eq(observer._itemChangedProperty, "title"); + do_check_eq(observer._itemChangedValue, TITLE); + + txn.redoTransaction(); + do_check_eq(observer._itemChangedId, testBkmId); + do_check_eq(observer._itemChangedProperty, "title"); + do_check_eq(observer._itemChangedValue, MOD_TITLE); + + txn.undoTransaction(); + do_check_eq(observer._itemChangedId, testBkmId); + do_check_eq(observer._itemChangedProperty, "title"); + do_check_eq(observer._itemChangedValue, TITLE); +}); + +add_task(function* test_editing_item_uri() { + const OLD_TEST_URI = NetUtil.newURI("http://old.test_editing_item_uri.com/"); + const NEW_TEST_URI = NetUtil.newURI("http://new.test_editing_item_uri.com/"); + let testBkmId = bmsvc.insertBookmark(root, OLD_TEST_URI, bmsvc.DEFAULT_INDEX, + "Test editing item title"); + tagssvc.tagURI(OLD_TEST_URI, ["tag"]); + + let txn = new PlacesEditBookmarkURITransaction(testBkmId, NEW_TEST_URI); + + txn.doTransaction(); + do_check_eq(observer._itemChangedId, testBkmId); + do_check_eq(observer._itemChangedProperty, "uri"); + do_check_eq(observer._itemChangedValue, NEW_TEST_URI.spec); + do_check_eq(JSON.stringify(tagssvc.getTagsForURI(NEW_TEST_URI)), JSON.stringify(["tag"])); + do_check_eq(JSON.stringify(tagssvc.getTagsForURI(OLD_TEST_URI)), JSON.stringify([])); + + txn.undoTransaction(); + do_check_eq(observer._itemChangedId, testBkmId); + do_check_eq(observer._itemChangedProperty, "uri"); + do_check_eq(observer._itemChangedValue, OLD_TEST_URI.spec); + do_check_eq(JSON.stringify(tagssvc.getTagsForURI(OLD_TEST_URI)), JSON.stringify(["tag"])); + do_check_eq(JSON.stringify(tagssvc.getTagsForURI(NEW_TEST_URI)), JSON.stringify([])); + + txn.redoTransaction(); + do_check_eq(observer._itemChangedId, testBkmId); + do_check_eq(observer._itemChangedProperty, "uri"); + do_check_eq(observer._itemChangedValue, NEW_TEST_URI.spec); + do_check_eq(JSON.stringify(tagssvc.getTagsForURI(NEW_TEST_URI)), JSON.stringify(["tag"])); + do_check_eq(JSON.stringify(tagssvc.getTagsForURI(OLD_TEST_URI)), JSON.stringify([])); + + txn.undoTransaction(); + do_check_eq(observer._itemChangedId, testBkmId); + do_check_eq(observer._itemChangedProperty, "uri"); + do_check_eq(observer._itemChangedValue, OLD_TEST_URI.spec); + do_check_eq(JSON.stringify(tagssvc.getTagsForURI(OLD_TEST_URI)), JSON.stringify(["tag"])); + do_check_eq(JSON.stringify(tagssvc.getTagsForURI(NEW_TEST_URI)), JSON.stringify([])); +}); + +add_task(function* test_edit_description_transaction() { + let testURI = NetUtil.newURI("http://test_edit_description_transaction.com"); + let testBkmId = bmsvc.insertBookmark(root, testURI, bmsvc.DEFAULT_INDEX, "Test edit description transaction"); + + let anno = { + name: DESCRIPTION_ANNO, + type: Ci.nsIAnnotationService.TYPE_STRING, + flags: 0, + value: "Test edit Description", + expires: Ci.nsIAnnotationService.EXPIRE_NEVER, + }; + let txn = new PlacesSetItemAnnotationTransaction(testBkmId, anno); + + txn.doTransaction(); + do_check_eq(observer._itemChangedId, testBkmId); + do_check_eq(observer._itemChangedProperty, DESCRIPTION_ANNO); +}); + +add_task(function* test_edit_keyword() { + const KEYWORD = "keyword-test_edit_keyword"; + + let testURI = NetUtil.newURI("http://test_edit_keyword.com"); + let testBkmId = bmsvc.insertBookmark(root, testURI, bmsvc.DEFAULT_INDEX, "Test edit keyword"); + + let txn = new PlacesEditBookmarkKeywordTransaction(testBkmId, KEYWORD, "postData"); + + txn.doTransaction(); + do_check_eq(observer._itemChangedId, testBkmId); + do_check_eq(observer._itemChangedProperty, "keyword"); + do_check_eq(observer._itemChangedValue, KEYWORD); + do_check_eq(PlacesUtils.getPostDataForBookmark(testBkmId), "postData"); + + txn.undoTransaction(); + do_check_eq(observer._itemChangedId, testBkmId); + do_check_eq(observer._itemChangedProperty, "keyword"); + do_check_eq(observer._itemChangedValue, ""); + do_check_eq(PlacesUtils.getPostDataForBookmark(testBkmId), null); +}); + +add_task(function* test_edit_specific_keyword() { + const KEYWORD = "keyword-test_edit_keyword2"; + + let testURI = NetUtil.newURI("http://test_edit_keyword2.com"); + let testBkmId = bmsvc.insertBookmark(root, testURI, bmsvc.DEFAULT_INDEX, "Test edit keyword"); + // Add multiple keyword to this uri. + yield PlacesUtils.keywords.insert({ keyword: "kw1", url: testURI.spec, postData: "postData1" }); + yield PlacesUtils.keywords.insert({keyword: "kw2", url: testURI.spec, postData: "postData2" }); + + // Try to change only kw2. + let txn = new PlacesEditBookmarkKeywordTransaction(testBkmId, KEYWORD, "postData2", "kw2"); + + txn.doTransaction(); + do_check_eq(observer._itemChangedId, testBkmId); + do_check_eq(observer._itemChangedProperty, "keyword"); + do_check_eq(observer._itemChangedValue, KEYWORD); + let entry = yield PlacesUtils.keywords.fetch("kw1"); + Assert.equal(entry.url.href, testURI.spec); + Assert.equal(entry.postData, "postData1"); + yield promiseKeyword(KEYWORD, testURI.spec, "postData2"); + yield promiseKeyword("kw2", null); + + txn.undoTransaction(); + do_check_eq(observer._itemChangedId, testBkmId); + do_check_eq(observer._itemChangedProperty, "keyword"); + do_check_eq(observer._itemChangedValue, "kw2"); + do_check_eq(PlacesUtils.getPostDataForBookmark(testBkmId), "postData1"); + entry = yield PlacesUtils.keywords.fetch("kw1"); + Assert.equal(entry.url.href, testURI.spec); + Assert.equal(entry.postData, "postData1"); + yield promiseKeyword("kw2", testURI.spec, "postData2"); + yield promiseKeyword("keyword", null); +}); + +add_task(function* test_LoadInSidebar_transaction() { + let testURI = NetUtil.newURI("http://test_LoadInSidebar_transaction.com"); + let testBkmId = bmsvc.insertBookmark(root, testURI, bmsvc.DEFAULT_INDEX, "Test LoadInSidebar transaction"); + + const LOAD_IN_SIDEBAR_ANNO = "bookmarkProperties/loadInSidebar"; + let anno = { name: LOAD_IN_SIDEBAR_ANNO, + type: Ci.nsIAnnotationService.TYPE_INT32, + flags: 0, + value: true, + expires: Ci.nsIAnnotationService.EXPIRE_NEVER }; + let txn = new PlacesSetItemAnnotationTransaction(testBkmId, anno); + + txn.doTransaction(); + do_check_eq(observer._itemChangedId, testBkmId); + do_check_eq(observer._itemChangedProperty, LOAD_IN_SIDEBAR_ANNO); + do_check_eq(observer._itemChanged_isAnnotationProperty, true); + + txn.undoTransaction(); + do_check_eq(observer._itemChangedId, testBkmId); + do_check_eq(observer._itemChangedProperty, LOAD_IN_SIDEBAR_ANNO); + do_check_eq(observer._itemChanged_isAnnotationProperty, true); +}); + +add_task(function* test_generic_item_annotation() { + let testURI = NetUtil.newURI("http://test_generic_item_annotation.com"); + let testBkmId = bmsvc.insertBookmark(root, testURI, bmsvc.DEFAULT_INDEX, "Test generic item annotation"); + + let itemAnnoObj = { name: "testAnno/testInt", + type: Ci.nsIAnnotationService.TYPE_INT32, + flags: 0, + value: 123, + expires: Ci.nsIAnnotationService.EXPIRE_NEVER }; + let txn = new PlacesSetItemAnnotationTransaction(testBkmId, itemAnnoObj); + + txn.doTransaction(); + do_check_eq(observer._itemChangedId, testBkmId); + do_check_eq(observer._itemChangedProperty, "testAnno/testInt"); + do_check_eq(observer._itemChanged_isAnnotationProperty, true); + + txn.undoTransaction(); + do_check_eq(observer._itemChangedId, testBkmId); + do_check_eq(observer._itemChangedProperty, "testAnno/testInt"); + do_check_eq(observer._itemChanged_isAnnotationProperty, true); + + txn.redoTransaction(); + do_check_eq(observer._itemChangedId, testBkmId); + do_check_eq(observer._itemChangedProperty, "testAnno/testInt"); + do_check_eq(observer._itemChanged_isAnnotationProperty, true); +}); + +add_task(function* test_editing_item_date_added() { + let testURI = NetUtil.newURI("http://test_editing_item_date_added.com"); + let testBkmId = bmsvc.insertBookmark(root, testURI, bmsvc.DEFAULT_INDEX, + "Test editing item date added"); + + let oldAdded = bmsvc.getItemDateAdded(testBkmId); + let newAdded = Date.now() * 1000 + 1000; + let txn = new PlacesEditItemDateAddedTransaction(testBkmId, newAdded); + + txn.doTransaction(); + do_check_eq(newAdded, bmsvc.getItemDateAdded(testBkmId)); + + txn.undoTransaction(); + do_check_eq(oldAdded, bmsvc.getItemDateAdded(testBkmId)); +}); + +add_task(function* test_edit_item_last_modified() { + let testURI = NetUtil.newURI("http://test_edit_item_last_modified.com"); + let testBkmId = bmsvc.insertBookmark(root, testURI, bmsvc.DEFAULT_INDEX, + "Test editing item last modified"); + + let oldModified = bmsvc.getItemLastModified(testBkmId); + let newModified = Date.now() * 1000 + 1000; + let txn = new PlacesEditItemLastModifiedTransaction(testBkmId, newModified); + + txn.doTransaction(); + do_check_eq(newModified, bmsvc.getItemLastModified(testBkmId)); + + txn.undoTransaction(); + do_check_eq(oldModified, bmsvc.getItemLastModified(testBkmId)); +}); + +add_task(function* test_generic_page_annotation() { + const TEST_ANNO = "testAnno/testInt"; + let testURI = NetUtil.newURI("http://www.mozilla.org/"); + PlacesTestUtils.addVisits(testURI).then(function () { + let pageAnnoObj = { name: TEST_ANNO, + type: Ci.nsIAnnotationService.TYPE_INT32, + flags: 0, + value: 123, + expires: Ci.nsIAnnotationService.EXPIRE_NEVER }; + let txn = new PlacesSetPageAnnotationTransaction(testURI, pageAnnoObj); + + txn.doTransaction(); + do_check_true(annosvc.pageHasAnnotation(testURI, TEST_ANNO)); + + txn.undoTransaction(); + do_check_false(annosvc.pageHasAnnotation(testURI, TEST_ANNO)); + + txn.redoTransaction(); + do_check_true(annosvc.pageHasAnnotation(testURI, TEST_ANNO)); + }); +}); + +add_task(function* test_sort_folder_by_name() { + let testFolder = bmsvc.createFolder(root, "Test PlacesSortFolderByNameTransaction", + bmsvc.DEFAULT_INDEX); + let testURI = NetUtil.newURI("http://test_sort_folder_by_name.com"); + + bmsvc.insertBookmark(testFolder, testURI, bmsvc.DEFAULT_INDEX, "bookmark3"); + bmsvc.insertBookmark(testFolder, testURI, bmsvc.DEFAULT_INDEX, "bookmark2"); + bmsvc.insertBookmark(testFolder, testURI, bmsvc.DEFAULT_INDEX, "bookmark1"); + + let bkmIds = bmsvc.getBookmarkIdsForURI(testURI); + bkmIds.sort(); + + let b1 = bkmIds[0]; + let b2 = bkmIds[1]; + let b3 = bkmIds[2]; + + do_check_eq(0, bmsvc.getItemIndex(b1)); + do_check_eq(1, bmsvc.getItemIndex(b2)); + do_check_eq(2, bmsvc.getItemIndex(b3)); + + let txn = new PlacesSortFolderByNameTransaction(testFolder); + + txn.doTransaction(); + do_check_eq(2, bmsvc.getItemIndex(b1)); + do_check_eq(1, bmsvc.getItemIndex(b2)); + do_check_eq(0, bmsvc.getItemIndex(b3)); + + txn.undoTransaction(); + do_check_eq(0, bmsvc.getItemIndex(b1)); + do_check_eq(1, bmsvc.getItemIndex(b2)); + do_check_eq(2, bmsvc.getItemIndex(b3)); + + txn.redoTransaction(); + do_check_eq(2, bmsvc.getItemIndex(b1)); + do_check_eq(1, bmsvc.getItemIndex(b2)); + do_check_eq(0, bmsvc.getItemIndex(b3)); + + txn.undoTransaction(); + do_check_eq(0, bmsvc.getItemIndex(b1)); + do_check_eq(1, bmsvc.getItemIndex(b2)); + do_check_eq(2, bmsvc.getItemIndex(b3)); +}); + +add_task(function* test_tagURI_untagURI() { + const TAG_1 = "tag-test_tagURI_untagURI-bar"; + const TAG_2 = "tag-test_tagURI_untagURI-foo"; + let tagURI = NetUtil.newURI("http://test_tagURI_untagURI.com"); + + // Test tagURI + let tagTxn = new PlacesTagURITransaction(tagURI, [TAG_1, TAG_2]); + + tagTxn.doTransaction(); + do_check_eq(JSON.stringify(tagssvc.getTagsForURI(tagURI)), JSON.stringify([TAG_1, TAG_2])); + + tagTxn.undoTransaction(); + do_check_eq(tagssvc.getTagsForURI(tagURI).length, 0); + + tagTxn.redoTransaction(); + do_check_eq(JSON.stringify(tagssvc.getTagsForURI(tagURI)), JSON.stringify([TAG_1, TAG_2])); + + // Test untagURI + let untagTxn = new PlacesUntagURITransaction(tagURI, [TAG_1]); + + untagTxn.doTransaction(); + do_check_eq(JSON.stringify(tagssvc.getTagsForURI(tagURI)), JSON.stringify([TAG_2])); + + untagTxn.undoTransaction(); + do_check_eq(JSON.stringify(tagssvc.getTagsForURI(tagURI)), JSON.stringify([TAG_1, TAG_2])); + + untagTxn.redoTransaction(); + do_check_eq(JSON.stringify(tagssvc.getTagsForURI(tagURI)), JSON.stringify([TAG_2])); +}); + +add_task(function* test_aggregate_removeItem_Txn() { + let testFolder = bmsvc.createFolder(root, "Test aggregate removeItem transaction", bmsvc.DEFAULT_INDEX); + + const TEST_URL = "http://test_aggregate_removeitem_txn.com/"; + const FOLDERNAME = "Folder"; + let testURI = NetUtil.newURI(TEST_URL); + + let bkmk1Id = bmsvc.insertBookmark(testFolder, testURI, 0, "Mozilla"); + let bkmk2Id = bmsvc.insertSeparator(testFolder, 1); + let bkmk3Id = bmsvc.createFolder(testFolder, FOLDERNAME, 2); + + let bkmk3_1Id = bmsvc.insertBookmark(bkmk3Id, testURI, 0, "Mozilla"); + let bkmk3_2Id = bmsvc.insertSeparator(bkmk3Id, 1); + let bkmk3_3Id = bmsvc.createFolder(bkmk3Id, FOLDERNAME, 2); + + let childTxn1 = new PlacesRemoveItemTransaction(bkmk1Id); + let childTxn2 = new PlacesRemoveItemTransaction(bkmk2Id); + let childTxn3 = new PlacesRemoveItemTransaction(bkmk3Id); + let transactions = [childTxn1, childTxn2, childTxn3]; + let txn = new PlacesAggregatedTransaction("RemoveItems", transactions); + + txn.doTransaction(); + do_check_eq(bmsvc.getItemIndex(bkmk1Id), -1); + do_check_eq(bmsvc.getItemIndex(bkmk2Id), -1); + do_check_eq(bmsvc.getItemIndex(bkmk3Id), -1); + do_check_eq(bmsvc.getItemIndex(bkmk3_1Id), -1); + do_check_eq(bmsvc.getItemIndex(bkmk3_2Id), -1); + do_check_eq(bmsvc.getItemIndex(bkmk3_3Id), -1); + // Check last removed item id. + do_check_eq(observer._itemRemovedId, bkmk3Id); + + txn.undoTransaction(); + let newBkmk1Id = bmsvc.getIdForItemAt(testFolder, 0); + let newBkmk2Id = bmsvc.getIdForItemAt(testFolder, 1); + let newBkmk3Id = bmsvc.getIdForItemAt(testFolder, 2); + let newBkmk3_1Id = bmsvc.getIdForItemAt(newBkmk3Id, 0); + let newBkmk3_2Id = bmsvc.getIdForItemAt(newBkmk3Id, 1); + let newBkmk3_3Id = bmsvc.getIdForItemAt(newBkmk3Id, 2); + do_check_eq(bmsvc.getItemType(newBkmk1Id), bmsvc.TYPE_BOOKMARK); + do_check_eq(bmsvc.getBookmarkURI(newBkmk1Id).spec, TEST_URL); + do_check_eq(bmsvc.getItemType(newBkmk2Id), bmsvc.TYPE_SEPARATOR); + do_check_eq(bmsvc.getItemType(newBkmk3Id), bmsvc.TYPE_FOLDER); + do_check_eq(bmsvc.getItemTitle(newBkmk3Id), FOLDERNAME); + do_check_eq(bmsvc.getFolderIdForItem(newBkmk3_1Id), newBkmk3Id); + do_check_eq(bmsvc.getItemType(newBkmk3_1Id), bmsvc.TYPE_BOOKMARK); + do_check_eq(bmsvc.getBookmarkURI(newBkmk3_1Id).spec, TEST_URL); + do_check_eq(bmsvc.getFolderIdForItem(newBkmk3_2Id), newBkmk3Id); + do_check_eq(bmsvc.getItemType(newBkmk3_2Id), bmsvc.TYPE_SEPARATOR); + do_check_eq(bmsvc.getFolderIdForItem(newBkmk3_3Id), newBkmk3Id); + do_check_eq(bmsvc.getItemType(newBkmk3_3Id), bmsvc.TYPE_FOLDER); + do_check_eq(bmsvc.getItemTitle(newBkmk3_3Id), FOLDERNAME); + // Check last added back item id. + // Notice items are restored in reverse order. + do_check_eq(observer._itemAddedId, newBkmk1Id); + + txn.redoTransaction(); + do_check_eq(bmsvc.getItemIndex(newBkmk1Id), -1); + do_check_eq(bmsvc.getItemIndex(newBkmk2Id), -1); + do_check_eq(bmsvc.getItemIndex(newBkmk3Id), -1); + do_check_eq(bmsvc.getItemIndex(newBkmk3_1Id), -1); + do_check_eq(bmsvc.getItemIndex(newBkmk3_2Id), -1); + do_check_eq(bmsvc.getItemIndex(newBkmk3_3Id), -1); + // Check last removed item id. + do_check_eq(observer._itemRemovedId, newBkmk3Id); + + txn.undoTransaction(); + newBkmk1Id = bmsvc.getIdForItemAt(testFolder, 0); + newBkmk2Id = bmsvc.getIdForItemAt(testFolder, 1); + newBkmk3Id = bmsvc.getIdForItemAt(testFolder, 2); + newBkmk3_1Id = bmsvc.getIdForItemAt(newBkmk3Id, 0); + newBkmk3_2Id = bmsvc.getIdForItemAt(newBkmk3Id, 1); + newBkmk3_3Id = bmsvc.getIdForItemAt(newBkmk3Id, 2); + do_check_eq(bmsvc.getItemType(newBkmk1Id), bmsvc.TYPE_BOOKMARK); + do_check_eq(bmsvc.getBookmarkURI(newBkmk1Id).spec, TEST_URL); + do_check_eq(bmsvc.getItemType(newBkmk2Id), bmsvc.TYPE_SEPARATOR); + do_check_eq(bmsvc.getItemType(newBkmk3Id), bmsvc.TYPE_FOLDER); + do_check_eq(bmsvc.getItemTitle(newBkmk3Id), FOLDERNAME); + do_check_eq(bmsvc.getFolderIdForItem(newBkmk3_1Id), newBkmk3Id); + do_check_eq(bmsvc.getItemType(newBkmk3_1Id), bmsvc.TYPE_BOOKMARK); + do_check_eq(bmsvc.getBookmarkURI(newBkmk3_1Id).spec, TEST_URL); + do_check_eq(bmsvc.getFolderIdForItem(newBkmk3_2Id), newBkmk3Id); + do_check_eq(bmsvc.getItemType(newBkmk3_2Id), bmsvc.TYPE_SEPARATOR); + do_check_eq(bmsvc.getFolderIdForItem(newBkmk3_3Id), newBkmk3Id); + do_check_eq(bmsvc.getItemType(newBkmk3_3Id), bmsvc.TYPE_FOLDER); + do_check_eq(bmsvc.getItemTitle(newBkmk3_3Id), FOLDERNAME); + // Check last added back item id. + // Notice items are restored in reverse order. + do_check_eq(observer._itemAddedId, newBkmk1Id); +}); + +add_task(function* test_create_item_with_childTxn() { + let testFolder = bmsvc.createFolder(root, "Test creating an item with childTxns", bmsvc.DEFAULT_INDEX); + + const BOOKMARK_TITLE = "parent item"; + let testURI = NetUtil.newURI("http://test_create_item_with_childTxn.com"); + let childTxns = []; + let newDateAdded = Date.now() * 1000 - 20000; + let editDateAdddedTxn = new PlacesEditItemDateAddedTransaction(null, newDateAdded); + childTxns.push(editDateAdddedTxn); + + let itemChildAnnoObj = { name: "testAnno/testInt", + type: Ci.nsIAnnotationService.TYPE_INT32, + flags: 0, + value: 123, + expires: Ci.nsIAnnotationService.EXPIRE_NEVER }; + let annoTxn = new PlacesSetItemAnnotationTransaction(null, itemChildAnnoObj); + childTxns.push(annoTxn); + + let itemWChildTxn = new PlacesCreateBookmarkTransaction(testURI, testFolder, bmStartIndex, + BOOKMARK_TITLE, null, null, + childTxns); + try { + txnManager.doTransaction(itemWChildTxn); + let itemId = bmsvc.getBookmarkIdsForURI(testURI)[0]; + do_check_eq(observer._itemAddedId, itemId); + do_check_eq(newDateAdded, bmsvc.getItemDateAdded(itemId)); + do_check_eq(observer._itemChangedProperty, "testAnno/testInt"); + do_check_eq(observer._itemChanged_isAnnotationProperty, true); + do_check_true(annosvc.itemHasAnnotation(itemId, itemChildAnnoObj.name)) + do_check_eq(annosvc.getItemAnnotation(itemId, itemChildAnnoObj.name), itemChildAnnoObj.value); + + itemWChildTxn.undoTransaction(); + do_check_eq(observer._itemRemovedId, itemId); + + itemWChildTxn.redoTransaction(); + do_check_true(bmsvc.isBookmarked(testURI)); + let newId = bmsvc.getBookmarkIdsForURI(testURI)[0]; + do_check_eq(newDateAdded, bmsvc.getItemDateAdded(newId)); + do_check_eq(observer._itemAddedId, newId); + do_check_eq(observer._itemChangedProperty, "testAnno/testInt"); + do_check_eq(observer._itemChanged_isAnnotationProperty, true); + do_check_true(annosvc.itemHasAnnotation(newId, itemChildAnnoObj.name)) + do_check_eq(annosvc.getItemAnnotation(newId, itemChildAnnoObj.name), itemChildAnnoObj.value); + + itemWChildTxn.undoTransaction(); + do_check_eq(observer._itemRemovedId, newId); + } + catch (ex) { + do_throw("Setting a child transaction in a createItem transaction did throw: " + ex); + } +}); + +add_task(function* test_create_folder_with_child_itemTxn() { + let childURI = NetUtil.newURI("http://test_create_folder_with_child_itemTxn.com"); + let childItemTxn = new PlacesCreateBookmarkTransaction(childURI, root, + bmStartIndex, "childItem"); + let txn = new PlacesCreateFolderTransaction("Test creating a folder with child itemTxns", + root, bmStartIndex, null, [childItemTxn]); + try { + txnManager.doTransaction(txn); + let childItemId = bmsvc.getBookmarkIdsForURI(childURI)[0]; + do_check_eq(observer._itemAddedId, childItemId); + do_check_eq(observer._itemAddedIndex, 0); + do_check_true(bmsvc.isBookmarked(childURI)); + + txn.undoTransaction(); + do_check_false(bmsvc.isBookmarked(childURI)); + + txn.redoTransaction(); + let newchildItemId = bmsvc.getBookmarkIdsForURI(childURI)[0]; + do_check_eq(observer._itemAddedIndex, 0); + do_check_eq(observer._itemAddedId, newchildItemId); + do_check_true(bmsvc.isBookmarked(childURI)); + + txn.undoTransaction(); + do_check_false(bmsvc.isBookmarked(childURI)); + } + catch (ex) { + do_throw("Setting a child item transaction in a createFolder transaction did throw: " + ex); + } +}); |