From 96022847d7163f1925a7d214a99c57340919704e Mon Sep 17 00:00:00 2001 From: Tom Najdek Date: Wed, 8 Mar 2023 01:40:42 +0100 Subject: [PATCH] Mendeley importer: Fix issue with empty creators (#3016) It does not appear to be possible to create a creator with no values in Mendeley, however we got reports of these causing the imports to fail. This tweak makes the importer more resilient by discarding empty/invalid creators. --- .../zotero/import/mendeley/mendeleyImport.js | 7 +- .../mendeleyMock/items-empty-creators.json | 69 +++++++++++++++++++ test/tests/mendeleyImportTest.js | 34 +++++++++ 3 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 test/tests/data/mendeleyMock/items-empty-creators.json diff --git a/chrome/content/zotero/import/mendeley/mendeleyImport.js b/chrome/content/zotero/import/mendeley/mendeleyImport.js index 90f93822e1..4c3436c08c 100644 --- a/chrome/content/zotero/import/mendeley/mendeleyImport.js +++ b/chrome/content/zotero/import/mendeley/mendeleyImport.js @@ -636,7 +636,12 @@ Zotero_Import_Mendeley.prototype._getDocumentCreatorsAPI = async function (docum const authors = (doc.authors || []).map(c => this._makeCreator('author', c.first_name, c.last_name)); const editors = (doc.editors || []).map(c => this._makeCreator('editor', c.first_name, c.last_name)); const translators = (doc.translators || []).map(c => this._makeCreator('translator', c.first_name, c.last_name)); - map.set(doc.id, [...authors, ...editors, ...translators]); + const creators = [...authors, ...editors, ...translators]; + const validCreators = creators.filter(c => c.name || c.firstName || c.lastName); + if (creators.length !== validCreators.length) { + Zotero.debug(`Discarding ${creators.length - validCreators.length} invalid creators for document ${doc.id}`); + } + map.set(doc.id, validCreators); } return map; }; diff --git a/test/tests/data/mendeleyMock/items-empty-creators.json b/test/tests/data/mendeleyMock/items-empty-creators.json new file mode 100644 index 0000000000..c93c0d99eb --- /dev/null +++ b/test/tests/data/mendeleyMock/items-empty-creators.json @@ -0,0 +1,69 @@ +[ + { + "authored": false, + "confirmed": true, + "created": "2023-03-07T13:30:46.353Z", + "file_attached": false, + "hidden": false, + "id": "b7b1023f-5072-4608-8fd5-87b045b77887", + "client_data": "{\"desktop_id\":\"9c03fca4-ee5b-435e-abdd-fb6d7d11cd02\"}", + "last_modified": "2023-03-07T13:30:46.025Z", + "private_publication": false, + "profile_id": "8dbf0832-8723-4c48-b532-20c0b7f6e01a", + "read": false, + "source": "something wrong", + "identifiers": { + "doi": "10.1111", + "pmid": "PMID: 11111111", + "arxiv": "1111.2222" + }, + "starred": false, + "title": "This one has no authors", + "type": "journal", + "folder_uuids": [ + "8d2f262d-49b3-4dfc-8968-0bb71bcd92ea" + ], + "year": 1987 + }, + { + "authored": false, + "confirmed": true, + "created": "2023-03-07T13:30:46.353Z", + "file_attached": false, + "hidden": false, + "id": "a15698a9-6214-4fac-81c5-5ac62b2d06b5", + "client_data": "{\"desktop_id\":\"fd86e48e-1931-4282-b72d-78c535b0398c\"}", + "last_modified": "2023-03-07T13:30:46.025Z", + "private_publication": false, + "profile_id": "8dbf0832-8723-4c48-b532-20c0b7f6e01a", + "read": false, + "source": "something wrong", + "identifiers": + { + "doi": "10.1111", + "pmid": "PMID: 11111111", + "arxiv": "1111.2222" + }, + "starred": false, + "title": "This one has empty authors", + "authors": + [ + { + "first_name": "", + "last_name": "" + }, + { + "first_name": "", + "last_name": "" + }, + { + + } + ], + "type": "journal", + "folder_uuids": [ + "8d2f262d-49b3-4dfc-8968-0bb71bcd92ea" + ], + "year": 1987 + } +] \ No newline at end of file diff --git a/test/tests/mendeleyImportTest.js b/test/tests/mendeleyImportTest.js index 8c257cf9af..d160c2dcb4 100644 --- a/test/tests/mendeleyImportTest.js +++ b/test/tests/mendeleyImportTest.js @@ -451,7 +451,41 @@ describe('Zotero_Import_Mendeley', function () { const noNewItemHere = await Zotero.Relations.getByPredicateAndObject('item', 'mendeleyDB:documentUUID', '86e56a00-5ae5-4fe8-a977-9298a03b16d6'); assert.lengthOf(noNewItemHere, 0); + }); + it("should handle empty creators", async () => { + setHTTPResponse(server, 'https://api.mendeley.com/', { + method: 'GET', + url: `documents?view=all&limit=500`, + status: 200, + headers: {}, + json: JSON.parse( + await Zotero.File.getContentsFromURLAsync('resource://zotero-unit-tests/data/mendeleyMock/items-empty-creators.json') + ) + }); + + const importer = getImporter(); + await importer.translate({ + libraryID: Zotero.Libraries.userLibraryID, + collections: null, + linkFiles: false, + }); + + const journalNoAuthors = (await Zotero.Relations + .getByPredicateAndObject('item', 'mendeleyDB:documentUUID', '9c03fca4-ee5b-435e-abdd-fb6d7d11cd02')) + .filter(item => item.libraryID == Zotero.Libraries.userLibraryID && !item.deleted) + .shift(); + + assert.equal(journalNoAuthors.getField('title'), 'This one has no authors'); + assert.equal(journalNoAuthors.getCreators().length, 0); + + const journalEmptyAuthors = (await Zotero.Relations + .getByPredicateAndObject('item', 'mendeleyDB:documentUUID', 'fd86e48e-1931-4282-b72d-78c535b0398c')) + .filter(item => item.libraryID == Zotero.Libraries.userLibraryID && !item.deleted) + .shift(); + + assert.equal(journalEmptyAuthors.getField('title'), 'This one has empty authors'); + assert.equal(journalEmptyAuthors.getCreators().length, 0); }); }); });