diff --git a/packages/component-fixture-manager/src/fixtures/collections.js b/packages/component-fixture-manager/src/fixtures/collections.js index c6d401815491578a0262f7cb8cb06b2e3ed66c56..84583485feff68c50c532e4a5f4a396147177df2 100644 --- a/packages/component-fixture-manager/src/fixtures/collections.js +++ b/packages/component-fixture-manager/src/fixtures/collections.js @@ -11,7 +11,7 @@ const collections = { type: 'collection', fragments: [fragment.id], owners: [user.id], - save: jest.fn(), + save: jest.fn(() => collections.collection), invitations: [ { id: chance.guid(), @@ -44,6 +44,7 @@ const collections = { technicalChecks: { token: chance.guid(), }, + status: 'pendingApproval', }, } diff --git a/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js b/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js index 37010631d8164ca49b2692580a63ba4330385d97..f67754387a6deef1b7dd8f2d93f31221c7bd52d5 100644 --- a/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js +++ b/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js @@ -1,5 +1,5 @@ const uuid = require('uuid') -const { pick, get, set } = require('lodash') +const { pick, get, set, has } = require('lodash') const config = require('config') const { v4 } = require('uuid') @@ -98,6 +98,19 @@ module.exports = models => async (req, res) => { await collection.save() } + /* if the EiC returns the manuscript to the HE after the EQA has been performed + then remove all properties from the technicalChecks property so that the manuscript + can go through the EQA process again + */ + if ( + isEditorInChief && + recommendation === 'return-to-handling-editor' && + has(collection.technicalChecks, 'hasEQA') + ) { + collection.technicalChecks = {} + await collection.save() + } + notifications.sendNotifications({ hasEQA, fragment, diff --git a/packages/component-manuscript-manager/src/routes/technicalChecks/notifications/notifications.js b/packages/component-manuscript-manager/src/routes/technicalChecks/notifications/notifications.js index 5102aff7e058007aee527163380e23ddd43f2ba7..bff64b56eeed319129822fdad32cdd6a1faf8150 100644 --- a/packages/component-manuscript-manager/src/routes/technicalChecks/notifications/notifications.js +++ b/packages/component-manuscript-manager/src/routes/technicalChecks/notifications/notifications.js @@ -27,7 +27,10 @@ module.exports = { handlingEditor: collection.handlingEditor, }) - const { authors, submittingAuthor } = await fragmentHelper.getAuthorData({ + const { + activeAuthors: authors, + submittingAuthor, + } = await fragmentHelper.getAuthorData({ UserModel, }) @@ -55,6 +58,7 @@ module.exports = { if (isEQA && agree) { const eicName = await userHelper.getEiCName() email.content.signatureName = eicName + sendAuthorsEmail({ email, baseUrl, 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 0f0f048e62835ecbd5d6c9df1f36ad3de740b183..686124cb9518df27b9c722fae0f645c764a4d415 100644 --- a/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/post.test.js +++ b/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/post.test.js @@ -11,6 +11,7 @@ const chance = new Chance() jest.mock('@pubsweet/component-send-email', () => ({ send: jest.fn(), })) +jest.mock('pubsweet-component-mts-package') const reqBody = { recommendation: 'accept', @@ -206,4 +207,129 @@ describe('Post fragments recommendations route handler', () => { const data = JSON.parse(res._getData()) expect(data.error).toEqual('Unauthorized.') }) + it('should return success when the EiC recommends to reject without peer review', async () => { + const { editorInChief } = testFixtures.users + const { collection } = testFixtures.collections + const { fragment } = testFixtures.fragments + body.recommendation = 'reject' + body.recommendationType = 'editorRecommendation' + + delete fragment.recommendations + delete fragment.revision + delete fragment.invitations + delete collection.invitations + delete collection.handlingEditor + + const res = await requests.sendRequest({ + body, + userId: editorInChief.id, + models, + route, + path, + params: { + collectionId: collection.id, + fragmentId: fragment.id, + }, + }) + + expect(res.statusCode).toBe(200) + const data = JSON.parse(res._getData()) + + expect(data.userId).toEqual(editorInChief.id) + expect(data.recommendation).toBe('reject') + }) + it('should return success when the EiC recommends to publish without EQA', async () => { + const { editorInChief } = testFixtures.users + const { collection } = testFixtures.collections + const { fragment } = testFixtures.fragments + body.recommendation = 'publish' + body.recommendationType = 'editorRecommendation' + delete collection.technicalChecks + + const res = await requests.sendRequest({ + body, + userId: editorInChief.id, + models, + route, + path, + params: { + collectionId: collection.id, + fragmentId: fragment.id, + }, + }) + + expect(res.statusCode).toBe(200) + const data = JSON.parse(res._getData()) + + expect(collection.status).toBe('inQA') + expect(collection.technicalChecks).toHaveProperty('hasEQA') + expect(collection.technicalChecks.hasEQA).toBeFalsy() + expect(data.userId).toEqual(editorInChief.id) + expect(data.recommendation).toBe('publish') + }) + it('should return success when the EiC recommends to publish with EQA accepted', async () => { + const { editorInChief } = testFixtures.users + const { collection } = testFixtures.collections + const { fragment } = testFixtures.fragments + body.recommendation = 'publish' + body.recommendationType = 'editorRecommendation' + + collection.technicalChecks.hasEQA = true + + const res = await requests.sendRequest({ + body, + userId: editorInChief.id, + models, + route, + path, + params: { + collectionId: collection.id, + fragmentId: fragment.id, + }, + }) + + expect(res.statusCode).toBe(200) + const data = JSON.parse(res._getData()) + + expect(collection.status).toBe('accepted') + expect(data.userId).toEqual(editorInChief.id) + expect(data.recommendation).toBe('publish') + }) + it('should return success when the EiC returns the manuscript to HE with comments after EQA returned to EiC', async () => { + const { editorInChief } = testFixtures.users + const { collection } = testFixtures.collections + const { fragment } = testFixtures.fragments + body.recommendation = 'return-to-handling-editor' + body.recommendationType = 'editorRecommendation' + body.comments = 'This needs more work' + + delete fragment.recommendations + delete fragment.revision + delete fragment.invitations + delete collection.invitations + delete collection.handlingEditor + collection.technicalChecks.hasEQA = false + + const res = await requests.sendRequest({ + body, + userId: editorInChief.id, + models, + route, + path, + params: { + collectionId: collection.id, + fragmentId: fragment.id, + }, + }) + + expect(res.statusCode).toBe(200) + const data = JSON.parse(res._getData()) + + expect(collection.status).toBe('reviewCompleted') + expect(collection.technicalChecks).not.toHaveProperty('token') + expect(collection.technicalChecks).not.toHaveProperty('hasEQA') + + expect(data.userId).toEqual(editorInChief.id) + expect(data.recommendation).toBe('return-to-handling-editor') + }) }) diff --git a/packages/component-manuscript-manager/src/tests/technicalChecks/patch.test.js b/packages/component-manuscript-manager/src/tests/technicalChecks/patch.test.js index 37c2ca388c56320be9a1527db7aa22c6f310a002..f8b6ccd6bc92c2817aeb60b454c6347a7d6eb47b 100644 --- a/packages/component-manuscript-manager/src/tests/technicalChecks/patch.test.js +++ b/packages/component-manuscript-manager/src/tests/technicalChecks/patch.test.js @@ -29,7 +29,7 @@ describe('Patch technical checks route handler', () => { models = Model.build(testFixtures) }) - it('should return success when the parameters are correct', async () => { + it('should return success when the EQS is accepted', async () => { const { collection } = testFixtures.collections body.token = collection.technicalChecks.token @@ -46,6 +46,62 @@ describe('Patch technical checks route handler', () => { expect(res.statusCode).toBe(200) }) + it('should return success when the EQS is rejected', async () => { + const { collection } = testFixtures.collections + body.token = collection.technicalChecks.token + body.agree = false + + const res = await requests.sendRequest({ + body, + models, + route, + path, + params: { + collectionId: collection.id, + }, + }) + + expect(res.statusCode).toBe(200) + }) + + it('should return success when the EQA is accepted', async () => { + const { collection } = testFixtures.collections + body.token = collection.technicalChecks.token + body.step = 'eqa' + + const res = await requests.sendRequest({ + body, + models, + route, + path, + params: { + collectionId: collection.id, + }, + }) + + expect(res.statusCode).toBe(200) + }) + + it('should return success when the EQA is returned with comments', async () => { + const { collection } = testFixtures.collections + body.token = collection.technicalChecks.token + body.agree = false + body.step = 'eqa' + body.comments = 'suspicion of plagiarism' + + const res = await requests.sendRequest({ + body, + models, + route, + path, + params: { + collectionId: collection.id, + }, + }) + + expect(res.statusCode).toBe(200) + }) + it('should return an error when the collection does not exist', async () => { const res = await requests.sendRequest({ body,