diff --git a/packages/component-fixture-manager/src/fixtures/collectionIDs.js b/packages/component-fixture-manager/src/fixtures/collectionIDs.js index 5b0da41bf1758f75c2b1394ca7f42ef812761ccc..e66bb71a232758a7de0746033ba2493745157250 100644 --- a/packages/component-fixture-manager/src/fixtures/collectionIDs.js +++ b/packages/component-fixture-manager/src/fixtures/collectionIDs.js @@ -7,4 +7,5 @@ module.exports = { collectionReviewCompletedID: chance.guid(), collectionNoInvitesID: chance.guid(), twoVersionsCollectionId: chance.guid(), + noEditorRecomedationCollectionID: chance.guid(), } diff --git a/packages/component-fixture-manager/src/fixtures/collections.js b/packages/component-fixture-manager/src/fixtures/collections.js index d982f643c675c55a73ce3a1a4b57289935a9556b..7d1df81e4f6379f9bb4d21bc243a2ed97a9e9e2d 100644 --- a/packages/component-fixture-manager/src/fixtures/collections.js +++ b/packages/component-fixture-manager/src/fixtures/collections.js @@ -1,16 +1,23 @@ const Chance = require('chance') -const { user, handlingEditor, answerHE } = require('./userData') +const { + user, + handlingEditor, + answerHE, + noRecommendationHE, +} = require('./userData') const { fragment, fragment1, reviewCompletedFragment, noInvitesFragment, + noEditorRecomedationFragment, } = require('./fragments') const { standardCollID, collectionReviewCompletedID, collectionNoInvitesID, twoVersionsCollectionId, + noEditorRecomedationCollectionID, } = require('./collectionIDs') const chance = new Chance() @@ -214,6 +221,48 @@ const collections = { save: jest.fn(() => collections.collection), customId: chance.natural({ min: 999999, max: 9999999 }), }, + noEditorRecomedationCollection: { + id: noEditorRecomedationCollectionID, + title: chance.sentence(), + type: 'collection', + fragments: [noEditorRecomedationFragment.id], + owners: [user.id], + save: jest.fn(() => collections.noEditorRecomedationCollection), + invitations: [ + { + id: chance.guid(), + role: 'handlingEditor', + hasAnswer: true, + isAccepted: true, + userId: noRecommendationHE.id, + invitedOn: chance.timestamp(), + respondedOn: null, + }, + { + id: chance.guid(), + role: 'handlingEditor', + hasAnswer: false, + isAccepted: false, + userId: answerHE.id, + invitedOn: chance.timestamp(), + respondedOn: chance.timestamp(), + }, + ], + handlingEditor: { + id: handlingEditor.id, + hasAnswer: true, + isAccepted: true, + email: handlingEditor.email, + invitedOn: chance.timestamp(), + respondedOn: chance.timestamp(), + name: `${handlingEditor.firstName} ${handlingEditor.lastName}`, + }, + customId: chance.natural({ min: 999999, max: 9999999 }), + technicalChecks: { + token: chance.guid(), + }, + status: 'reviewCompleted', + }, } module.exports = collections diff --git a/packages/component-fixture-manager/src/fixtures/fragments.js b/packages/component-fixture-manager/src/fixtures/fragments.js index 77e771572f61bc2219da320f7afa07e660f0bbe3..85465027c31f377649ccd1d533626e03f895cfd2 100644 --- a/packages/component-fixture-manager/src/fixtures/fragments.js +++ b/packages/component-fixture-manager/src/fixtures/fragments.js @@ -8,11 +8,13 @@ const { admin, inactiveReviewer, reviewer1, + newReviewer, } = require('./userData') const { standardCollID, collectionReviewCompletedID, collectionNoInvitesID, + noEditorRecomedationCollectionID, } = require('./collectionIDs') const { user } = require('./userData') @@ -427,6 +429,61 @@ const fragments = { type: 'fragment', }, }, + noEditorRecomedationFragment: { + id: chance.guid(), + collectionId: noEditorRecomedationCollectionID, + metadata: { + title: chance.sentence(), + abstract: chance.paragraph(), + }, + recommendations: [ + { + recommendation: 'publish', + recommendationType: 'review', + comments: [ + { + content: chance.paragraph(), + public: chance.bool(), + files: [ + { + id: chance.guid(), + name: 'file.pdf', + size: chance.natural(), + }, + ], + }, + ], + id: chance.guid(), + userId: newReviewer.id, + createdOn: chance.timestamp(), + updatedOn: chance.timestamp(), + submittedOn: chance.timestamp(), + }, + ], + authors: [ + { + email: chance.email(), + id: submittingAuthor.id, + isSubmitting: true, + isCorresponding: false, + }, + ], + invitations: [ + { + id: chance.guid(), + role: 'reviewer', + hasAnswer: true, + isAccepted: true, + userId: newReviewer.id, + invitedOn: chance.timestamp(), + respondedOn: chance.timestamp(), + type: 'invitation', + }, + ], + save: jest.fn(() => fragments.fragment), + owners: [user.id], + type: 'fragment', + }, } fragments.noInvitesFragment = { diff --git a/packages/component-fixture-manager/src/fixtures/teamIDs.js b/packages/component-fixture-manager/src/fixtures/teamIDs.js index ab1eae10948701757d3d0e745a307204a14b7f4e..162cdb391585ed6789018579dbb1469271f8d2f2 100644 --- a/packages/component-fixture-manager/src/fixtures/teamIDs.js +++ b/packages/component-fixture-manager/src/fixtures/teamIDs.js @@ -8,4 +8,6 @@ module.exports = { authorTeamID: chance.guid(), revRecommendationTeamID: chance.guid(), rev1TeamID: chance.guid(), + heNoRecommendationTeamID: chance.guid(), + revNoEditorRecommendationTeamID: chance.guid(), } diff --git a/packages/component-fixture-manager/src/fixtures/teams.js b/packages/component-fixture-manager/src/fixtures/teams.js index 370a9c0e988c6c886454314b76173613d898bf25..dbd51a4aca783c1315e45fe3749b7c2bd1f8145c 100644 --- a/packages/component-fixture-manager/src/fixtures/teams.js +++ b/packages/component-fixture-manager/src/fixtures/teams.js @@ -8,11 +8,18 @@ const { authorTeamID, revRecommendationTeamID, rev1TeamID, + heNoRecommendationTeamID, + revNoEditorRecommendationTeamID, } = require('./teamIDs') const { submittingAuthor } = require('./userData') -const { collection } = collections -const { fragment, reviewCompletedFragment, fragment1 } = fragments +const { collection, noEditorRecomedationCollection } = collections +const { + fragment, + reviewCompletedFragment, + fragment1, + noEditorRecomedationFragment, +} = fragments const { handlingEditor, reviewer, @@ -20,6 +27,8 @@ const { answerReviewer, recReviewer, reviewer1, + newReviewer, + noRecommendationHE, } = users const teams = { heTeam: { @@ -39,6 +48,23 @@ const teams = { updateProperties: jest.fn(() => teams.heTeam), id: heTeamID, }, + heNoRecommendationTeam: { + teamType: { + name: 'handlingEditor', + permissions: 'handlingEditor', + }, + group: 'handlingEditor', + name: 'HandlingEditor', + object: { + type: 'collection', + id: noEditorRecomedationCollection.id, + }, + members: [noRecommendationHE.id], + save: jest.fn(() => teams.heNoRecommendationTeam), + delete: jest.fn(), + updateProperties: jest.fn(() => teams.heNoRecommendationTeam), + id: heNoRecommendationTeamID, + }, revTeam: { teamType: { name: 'reviewer', @@ -106,5 +132,21 @@ const teams = { updateProperties: jest.fn(() => teams.authorTeam), id: authorTeamID, }, + revNoEditorRecommendationTeam: { + teamType: { + name: 'reviewer', + permissions: 'reviewer', + }, + group: 'reviewer', + name: 'reviewer', + object: { + type: 'fragment', + id: noEditorRecomedationFragment.id, + }, + members: [newReviewer.id], + save: jest.fn(() => teams.revNoEditorRecommendationTeam), + updateProperties: jest.fn(() => teams.revNoEditorRecommendationTeam), + id: revNoEditorRecommendationTeamID, + }, } module.exports = teams diff --git a/packages/component-fixture-manager/src/fixtures/userData.js b/packages/component-fixture-manager/src/fixtures/userData.js index 2335d630e32ce34e6ffc521956dfcd079deaaf94..448301d410f6fb514bad7850c7285671aa235042 100644 --- a/packages/component-fixture-manager/src/fixtures/userData.js +++ b/packages/component-fixture-manager/src/fixtures/userData.js @@ -10,11 +10,13 @@ const generateUserData = () => ({ module.exports = { handlingEditor: generateUserData(), + noRecommendationHE: generateUserData(), user: generateUserData(), admin: generateUserData(), author: generateUserData(), reviewer: generateUserData(), reviewer1: generateUserData(), + newReviewer: generateUserData(), answerReviewer: generateUserData(), submittingAuthor: generateUserData(), recReviewer: generateUserData(), diff --git a/packages/component-fixture-manager/src/fixtures/users.js b/packages/component-fixture-manager/src/fixtures/users.js index f0a6737c38eb46d4990c4131828b75e7af74ee4b..1a6353768eb68a4dc1d37dcb500d44cba6d41cc3 100644 --- a/packages/component-fixture-manager/src/fixtures/users.js +++ b/packages/component-fixture-manager/src/fixtures/users.js @@ -8,6 +8,8 @@ const { authorTeamID, revRecommendationTeamID, rev1TeamID, + heNoRecommendationTeamID, + revNoEditorRecommendationTeamID, } = require('./teamIDs') const keys = Object.keys(usersData) @@ -20,6 +22,9 @@ users = keys.reduce((obj, item) => { if (isHE) { teams = [heTeamID] } + if (item === 'noRecommendationHE') { + teams = [heNoRecommendationTeamID] + } if (item === 'author') { teams = [authorTeamID] } @@ -33,6 +38,9 @@ users = keys.reduce((obj, item) => { if (item === 'reviewer1') { teams = [rev1TeamID] } + if (item === 'newReviewer') { + teams = [revNoEditorRecommendationTeamID] + } obj[item] = { ...userData, diff --git a/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js b/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js index e5b462d57c66b24789b7f78de214c1c40ad46e4a..60cbb6a90175cce2ff1ec2a224c9f7da35197721 100644 --- a/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js +++ b/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js @@ -41,7 +41,9 @@ module.exports = models => async (req, res) => { }) } - const fragmentRecommendations = get(fragment, 'recommendations', []) + const currentUserRecommendation = get(fragment, 'recommendations', []).filter( + r => r.userId === req.user, + ) const authsome = authsomeHelper.getAuthsome(models) const target = { @@ -74,14 +76,17 @@ module.exports = models => async (req, res) => { } if ( - (recommendationType === recommendations.type.review || - recommendationType === recommendations.type.editor) && last(collection.fragments) === fragmentId && - !isEmpty(fragmentRecommendations.filter(r => r.userId === req.user)) + !isEmpty(currentUserRecommendation) ) { + if (recommendationType === recommendations.type.review) { + return res + .status(400) + .json({ error: 'Cannot write another review on this version.' }) + } return res .status(400) - .json({ error: 'Cannot write another review on this version.' }) + .json({ error: 'Cannot make another recommendation on this version.' }) } if ( diff --git a/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/post.test.js b/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/post.test.js index 05ae4193c249185b9c160ed1a1c74cbba2fbbf72..9f67766c989813e767b6d32299d1d9f5b9e4d85e 100644 --- a/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/post.test.js +++ b/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/post.test.js @@ -81,25 +81,24 @@ describe('Post fragments recommendations route handler', () => { expect(data.userId).toEqual(reviewer.id) }) it('should return success when creating a recommendation as a HE', async () => { - const { handlingEditor } = testFixtures.users - const { collection } = testFixtures.collections - const { fragment } = testFixtures.fragments + const { noRecommendationHE } = testFixtures.users + const { noEditorRecomedationCollection } = testFixtures.collections + const { noEditorRecomedationFragment } = testFixtures.fragments const res = await requests.sendRequest({ body, - userId: handlingEditor.id, + userId: noRecommendationHE.id, models, route, path, params: { - collectionId: collection.id, - fragmentId: fragment.id, + collectionId: noEditorRecomedationCollection.id, + fragmentId: noEditorRecomedationFragment.id, }, }) - expect(res.statusCode).toBe(200) const data = JSON.parse(res._getData()) - expect(data.userId).toEqual(handlingEditor.id) + expect(data.userId).toEqual(noRecommendationHE.id) }) it('should return an error when the fragmentId does not match the collectionId', async () => { const { reviewer } = testFixtures.users @@ -163,28 +162,28 @@ describe('Post fragments recommendations route handler', () => { expect(data.error).toEqual('Unauthorized.') }) it('should return success when a HE recommends to reject', async () => { - const { handlingEditor } = testFixtures.users - const { collection } = testFixtures.collections - const { fragment } = testFixtures.fragments + const { noRecommendationHE } = testFixtures.users + const { noEditorRecomedationCollection } = testFixtures.collections + const { noEditorRecomedationFragment } = testFixtures.fragments body.recommendation = 'reject' body.recommendationType = 'editorRecommendation' const res = await requests.sendRequest({ body, - userId: handlingEditor.id, + userId: noRecommendationHE.id, models, route, path, params: { - collectionId: collection.id, - fragmentId: fragment.id, + collectionId: noEditorRecomedationCollection.id, + fragmentId: noEditorRecomedationFragment.id, }, }) expect(res.statusCode).toBe(200) const data = JSON.parse(res._getData()) - expect(data.userId).toEqual(handlingEditor.id) + expect(data.userId).toEqual(noRecommendationHE.id) expect(data.recommendation).toBe('reject') }) it('should return an error when the user is inactive', async () => { @@ -357,7 +356,6 @@ describe('Post fragments recommendations route handler', () => { 'Cannot publish without at least one reviewer report.', ) }) - it('should return an error when a HE makes a recommendation on an older version of a manuscript', async () => { const { handlingEditor } = testFixtures.users const { twoVersionsCollection } = testFixtures.collections @@ -407,6 +405,28 @@ describe('Post fragments recommendations route handler', () => { expect(data.error).toEqual('Cannot write a review on an older version.') }) + it('should return an error when a reviewer writes another review on the current version of a manuscript', async () => { + const { newReviewer } = testFixtures.users + const { noEditorRecomedationCollection } = testFixtures.collections + const { noEditorRecomedationFragment } = testFixtures.fragments + body.recommendationType = 'review' + + const res = await requests.sendRequest({ + body, + userId: newReviewer.id, + models, + route, + path, + params: { + collectionId: noEditorRecomedationCollection.id, + fragmentId: noEditorRecomedationFragment.id, + }, + }) + expect(res.statusCode).toBe(400) + const data = JSON.parse(res._getData()) + + expect(data.error).toEqual('Cannot write another review on this version.') + }) it('should return an error when an EiC makes a decision on an older version of a manuscript', async () => { const { editorInChief } = testFixtures.users