
E.g., moving 3,600 items to the trash now takes 4 seconds instead of 62 Instead of saving each item, update internal state and database directly (which is more brittle but worth it). Also avoid unnecessary sorting after removing an item from the items tree.
166 lines
5.4 KiB
JavaScript
166 lines
5.4 KiB
JavaScript
describe("Zotero.Items", function () {
|
|
var win, collectionsView, zp;
|
|
|
|
before(function* () {
|
|
this.timeout(10000);
|
|
win = yield loadZoteroPane();
|
|
collectionsView = win.ZoteroPane.collectionsView;
|
|
zp = win.ZoteroPane;
|
|
})
|
|
beforeEach(function () {
|
|
return selectLibrary(win);
|
|
})
|
|
after(function () {
|
|
win.close();
|
|
})
|
|
|
|
|
|
describe("#merge()", function () {
|
|
it("should merge two items", function* () {
|
|
var item1 = yield createDataObject('item');
|
|
var item2 = yield createDataObject('item');
|
|
var item2URI = Zotero.URI.getItemURI(item2);
|
|
|
|
yield Zotero.Items.merge(item1, [item2]);
|
|
|
|
assert.isFalse(item1.deleted);
|
|
assert.isTrue(item2.deleted);
|
|
|
|
// Check for merge-tracking relation
|
|
assert.isFalse(item1.hasChanged());
|
|
var rels = item1.getRelationsByPredicate(Zotero.Relations.replacedItemPredicate);
|
|
assert.lengthOf(rels, 1);
|
|
assert.equal(rels[0], item2URI);
|
|
})
|
|
|
|
it("should move merge-tracking relation from replaced item to master", function* () {
|
|
var item1 = yield createDataObject('item');
|
|
var item2 = yield createDataObject('item');
|
|
var item2URI = Zotero.URI.getItemURI(item2);
|
|
var item3 = yield createDataObject('item');
|
|
var item3URI = Zotero.URI.getItemURI(item3);
|
|
|
|
yield Zotero.Items.merge(item2, [item3]);
|
|
yield Zotero.Items.merge(item1, [item2]);
|
|
|
|
// Check for merge-tracking relation from 1 to 3
|
|
var rels = item1.getRelationsByPredicate(Zotero.Relations.replacedItemPredicate);
|
|
assert.lengthOf(rels, 2);
|
|
assert.sameMembers(rels, [item2URI, item3URI]);
|
|
})
|
|
|
|
it("should update relations pointing to replaced item to point to master", function* () {
|
|
var item1 = yield createDataObject('item');
|
|
var item1URI = Zotero.URI.getItemURI(item1);
|
|
var item2 = yield createDataObject('item');
|
|
var item2URI = Zotero.URI.getItemURI(item2);
|
|
var item3 = createUnsavedDataObject('item');
|
|
var predicate = Zotero.Relations.relatedItemPredicate;
|
|
item3.addRelation(predicate, item2URI);
|
|
yield item3.saveTx();
|
|
|
|
yield Zotero.Items.merge(item1, [item2]);
|
|
|
|
// Check for related-item relation from 3 to 1
|
|
var rels = item3.getRelationsByPredicate(predicate);
|
|
assert.deepEqual(rels, [item1URI]);
|
|
})
|
|
|
|
it("should not update relations pointing to replaced item in other libraries", function* () {
|
|
var group1 = yield createGroup();
|
|
var group2 = yield createGroup();
|
|
|
|
var item1 = yield createDataObject('item', { libraryID: group1.libraryID });
|
|
var item1URI = Zotero.URI.getItemURI(item1);
|
|
var item2 = yield createDataObject('item', { libraryID: group1.libraryID });
|
|
var item2URI = Zotero.URI.getItemURI(item2);
|
|
var item3 = createUnsavedDataObject('item', { libraryID: group2.libraryID });
|
|
var predicate = Zotero.Relations.linkedObjectPredicate;
|
|
item3.addRelation(predicate, item2URI);
|
|
yield item3.saveTx();
|
|
|
|
yield Zotero.Items.merge(item1, [item2]);
|
|
|
|
// Check for related-item relation from 3 to 2
|
|
var rels = item3.getRelationsByPredicate(predicate);
|
|
assert.deepEqual(rels, [item2URI]);
|
|
})
|
|
})
|
|
|
|
|
|
describe("#trash()", function () {
|
|
it("should send items to the trash", function* () {
|
|
var items = [];
|
|
items.push(
|
|
(yield createDataObject('item')),
|
|
(yield createDataObject('item')),
|
|
(yield createDataObject('item'))
|
|
);
|
|
var ids = items.map(item => item.id);
|
|
yield Zotero.Items.trashTx(ids);
|
|
items.forEach(item => {
|
|
assert.isTrue(item.deleted);
|
|
assert.isFalse(item.hasChanged());
|
|
});
|
|
assert.equal((yield Zotero.DB.valueQueryAsync(
|
|
`SELECT COUNT(*) FROM deletedItems WHERE itemID IN (${ids})`
|
|
)), 3);
|
|
});
|
|
});
|
|
|
|
|
|
describe("#emptyTrash()", function () {
|
|
it("should delete items in the trash", function* () {
|
|
var item1 = createUnsavedDataObject('item');
|
|
item1.setField('title', 'a');
|
|
item1.deleted = true;
|
|
var id1 = yield item1.saveTx();
|
|
|
|
var item2 = createUnsavedDataObject('item');
|
|
item2.setField('title', 'b');
|
|
item2.deleted = true;
|
|
var id2 = yield item2.saveTx();
|
|
|
|
var item3 = createUnsavedDataObject('item', { itemType: 'attachment', parentID: id2 });
|
|
item3.attachmentLinkMode = Zotero.Attachments.LINK_MODE_IMPORTED_URL;
|
|
item3.deleted = true;
|
|
var id3 = yield item3.saveTx();
|
|
|
|
yield collectionsView.selectTrash(Zotero.Libraries.userLibraryID);
|
|
|
|
yield Zotero.Items.emptyTrash(Zotero.Libraries.userLibraryID);
|
|
|
|
assert.isFalse(yield Zotero.Items.getAsync(id1));
|
|
assert.isFalse(yield Zotero.Items.getAsync(id2));
|
|
assert.isFalse(yield Zotero.Items.getAsync(id3));
|
|
|
|
// TEMP: This is failing on Travis due to a race condition
|
|
//assert.equal(zp.itemsView.rowCount, 0)
|
|
})
|
|
})
|
|
|
|
describe("#getAsync()", function() {
|
|
it("should return Zotero.Item for item ID", function* () {
|
|
let item = new Zotero.Item('journalArticle');
|
|
let id = yield item.saveTx();
|
|
item = yield Zotero.Items.getAsync(id);
|
|
assert.notOk(item.isFeedItem);
|
|
assert.instanceOf(item, Zotero.Item);
|
|
assert.notInstanceOf(item, Zotero.FeedItem);
|
|
});
|
|
it("should return Zotero.FeedItem for feed item ID", function* () {
|
|
let feed = new Zotero.Feed({ name: 'foo', url: 'http://www.' + Zotero.randomString() + '.com' });
|
|
yield feed.saveTx();
|
|
|
|
let feedItem = new Zotero.FeedItem('journalArticle', { guid: Zotero.randomString() });
|
|
feedItem.libraryID = feed.libraryID;
|
|
let id = yield feedItem.saveTx();
|
|
|
|
feedItem = yield Zotero.Items.getAsync(id);
|
|
|
|
assert.isTrue(feedItem.isFeedItem);
|
|
assert.instanceOf(feedItem, Zotero.FeedItem);
|
|
});
|
|
});
|
|
});
|