diff --git a/chrome/content/zotero/collectionViewItemTree.jsx b/chrome/content/zotero/collectionViewItemTree.jsx index 294da21ae5..cb3661b200 100644 --- a/chrome/content/zotero/collectionViewItemTree.jsx +++ b/chrome/content/zotero/collectionViewItemTree.jsx @@ -632,18 +632,21 @@ class CollectionViewItemTreeRowProvider extends ItemTreeRowProvider { // 'collection-item' ids are in the form collectionID-itemID if (type == 'collection-item') { - if (!collectionTreeRow.isCollection()) { + // Collections can be selected alongside saved searches, which have no + // subcollections of their own + let selectedCollections = collectionTreeRows.filter(row => row.isCollection()); + if (!selectedCollections.length) { return; } var visibleSubcollections = Zotero.Prefs.get('recursiveCollections') - ? collectionTreeRows.map(row => row.ref.getDescendents(false, 'collection')).flat() + ? selectedCollections.map(row => row.ref.getDescendents(false, 'collection')).flat() : []; var splitIDs = []; for (let id of ids) { let [collectionID, itemID] = id.split('-'); // Include if an item in one of the selected collections or a visible subcollection - if (collectionTreeRows.some(row => row.ref.id == collectionID) + if (selectedCollections.some(row => row.ref.id == collectionID) || visibleSubcollections.some(c => collectionID == c.id)) { splitIDs.push(itemID); } diff --git a/test/tests/collectionViewItemTreeTest.js b/test/tests/collectionViewItemTreeTest.js index 55d98b49c2..97c5ac1db2 100644 --- a/test/tests/collectionViewItemTreeTest.js +++ b/test/tests/collectionViewItemTreeTest.js @@ -1233,6 +1233,33 @@ describe("CollectionViewItemTree", function () { assert.equal(quickSearch.value, "item"); }); + it("should add an item to a collection when a saved search is also selected", async function () { + Zotero.Prefs.set('recursiveCollections', true); + let logError = sinon.spy(Zotero, 'logError'); + try { + let collection = await createDataObject('collection'); + let subcollection = await createDataObject('collection', { parentID: collection.id }); + let search = await createDataObject('search'); + + await cv.selectByID("C" + collection.id); + await waitForItemsLoad(win); + cv.selection.toggleSelect(cv.getRowIndexByID("S" + search.id)); + await zp.onCollectionSelected(); + await zp.itemsView.waitForLoad(); + + // With recursiveCollections, an item added to a subcollection shows in + // the parent collection's view + let item = await createDataObject('item', { collections: [subcollection.id] }); + assert.isNumber(zp.itemsView.getRowIndexByID(item.id)); + assert.deepEqual(logError.getCalls().map(call => String(call.args[0])), []); + } + finally { + logError.restore(); + Zotero.Prefs.clear('recursiveCollections'); + await selectLibrary(win); + } + }); + describe("Change parent item", function () { let item1, item2, attachment1, highlight1;