mirror of
https://github.com/zotero/zotero.git
synced 2026-08-28 05:25:31 +00:00
Multi-collection selection left .collectionTreeRow and similar in place to reduce breakage, but that would just leave plugins and other callers potentially broken when multiple rows were selected. All singular getters now throw and say what to use instead. getSelectedLibraryIDs() was added to replace getSelectedLibraryID().
153 lines
No EOL
4.5 KiB
JavaScript
153 lines
No EOL
4.5 KiB
JavaScript
describe("CollectionTreeRow", function () {
|
|
var win, zp, cv, userLibraryID;
|
|
|
|
before(async function () {
|
|
win = await loadZoteroPane();
|
|
zp = win.ZoteroPane;
|
|
cv = zp.collectionsView;
|
|
userLibraryID = Zotero.Libraries.userLibraryID;
|
|
});
|
|
|
|
beforeEach(function () {
|
|
return selectLibrary(win);
|
|
});
|
|
|
|
after(function () {
|
|
win.close();
|
|
});
|
|
|
|
describe("Search cache", function () {
|
|
var collectionTreeRow;
|
|
|
|
// Stub getSearchObject on a collectionTreeRow so that the search's .search() throws,
|
|
// simulating a broken saved search (e.g., "too many SQL variables").
|
|
function stubBrokenSearch(ctr) {
|
|
return sinon.stub(ctr, 'getSearchObject').resolves({
|
|
search: () => { throw new Error('simulated search failure'); }
|
|
});
|
|
}
|
|
|
|
beforeEach(function () {
|
|
collectionTreeRow = zp.getCollectionTreeRows()[0];
|
|
collectionTreeRow.clearCache();
|
|
});
|
|
|
|
afterEach(function () {
|
|
collectionTreeRow.setSearch('');
|
|
collectionTreeRow.setTags([]);
|
|
});
|
|
|
|
it("should memoize getSearchResults() within a refresh cycle", async function () {
|
|
var results1 = await collectionTreeRow.getSearchResults();
|
|
var results2 = await collectionTreeRow.getSearchResults();
|
|
assert.strictEqual(results1, results2, 'should return same cached array');
|
|
});
|
|
|
|
it("should memoize getSearchObject() within a refresh cycle", async function () {
|
|
var search1 = await collectionTreeRow.getSearchObject();
|
|
var search2 = await collectionTreeRow.getSearchObject();
|
|
assert.strictEqual(search1, search2, 'should return same cached search');
|
|
});
|
|
|
|
it("should invalidate cache on clearCache()", async function () {
|
|
var results1 = await collectionTreeRow.getSearchResults();
|
|
collectionTreeRow.clearCache();
|
|
var results2 = await collectionTreeRow.getSearchResults();
|
|
assert.notStrictEqual(results1, results2, 'should return new array after clearCache()');
|
|
});
|
|
|
|
it("should invalidate cache when setSearch() changes filters", async function () {
|
|
await collectionTreeRow.getSearchResults();
|
|
assert.isNotNull(collectionTreeRow._cachedResults);
|
|
|
|
collectionTreeRow.setSearch('test-query');
|
|
assert.isNull(collectionTreeRow._cachedResults);
|
|
assert.isNull(collectionTreeRow._cachedSearch);
|
|
});
|
|
|
|
it("should not invalidate cache when setSearch() is called with same value", async function () {
|
|
collectionTreeRow.setSearch('same');
|
|
|
|
await collectionTreeRow.getSearchResults();
|
|
var cached = collectionTreeRow._cachedResults;
|
|
assert.isNotNull(cached);
|
|
|
|
collectionTreeRow.setSearch('same');
|
|
assert.strictEqual(collectionTreeRow._cachedResults, cached,
|
|
'cache should survive idempotent setSearch()');
|
|
});
|
|
|
|
it("should throw SearchError on search failure", async function () {
|
|
var stub = stubBrokenSearch(collectionTreeRow);
|
|
try {
|
|
var err;
|
|
try {
|
|
await collectionTreeRow.getSearchResults();
|
|
}
|
|
catch (e) {
|
|
err = e;
|
|
}
|
|
assert.ok(err, 'getSearchResults() should throw');
|
|
assert.instanceOf(err, Zotero.CollectionTreeRow.SearchError);
|
|
}
|
|
finally {
|
|
stub.restore();
|
|
}
|
|
});
|
|
|
|
it("should propagate SearchError through getItems()", async function () {
|
|
var stub = stubBrokenSearch(collectionTreeRow);
|
|
try {
|
|
var err;
|
|
try {
|
|
await collectionTreeRow.getItems();
|
|
}
|
|
catch (e) {
|
|
err = e;
|
|
}
|
|
assert.ok(err, 'getItems() should throw');
|
|
assert.instanceOf(err, Zotero.CollectionTreeRow.SearchError);
|
|
}
|
|
finally {
|
|
stub.restore();
|
|
}
|
|
});
|
|
|
|
it("should propagate SearchError through getTags()", async function () {
|
|
var stub = stubBrokenSearch(collectionTreeRow);
|
|
try {
|
|
var err;
|
|
try {
|
|
await collectionTreeRow.getTags();
|
|
}
|
|
catch (e) {
|
|
err = e;
|
|
}
|
|
assert.ok(err, 'getTags() should throw');
|
|
assert.instanceOf(err, Zotero.CollectionTreeRow.SearchError);
|
|
}
|
|
finally {
|
|
stub.restore();
|
|
}
|
|
});
|
|
});
|
|
|
|
describe("Unfiled Items", function () {
|
|
// https://github.com/zotero/zotero/issues/2771
|
|
it("shouldn't show filed attachments with annotations", async function () {
|
|
var item1 = await createDataObject('item');
|
|
|
|
var collection = await createDataObject('collection');
|
|
var item2 = await createDataObject('item', { collections: [collection.id] });
|
|
var attachment = await importPDFAttachment(item2);
|
|
var annotation = await createAnnotation('highlight', attachment);
|
|
|
|
cv.selectByID("U" + userLibraryID);
|
|
await waitForItemsLoad(win);
|
|
var itemsView = zp.itemsView;
|
|
|
|
assert.isNumber(itemsView.getRowIndexByID(item1.id));
|
|
assert.isFalse(itemsView.getRowIndexByID(item2.id));
|
|
});
|
|
});
|
|
}); |