diff --git a/packages/component-helper-service/src/services/Fragment.js b/packages/component-helper-service/src/services/Fragment.js index 174067efdfe0cbb7e7e7f627f5a8fd53884bd7f0..4b9e5edd4fefe8c3864698ba2ea205be4c3ecbac 100644 --- a/packages/component-helper-service/src/services/Fragment.js +++ b/packages/component-helper-service/src/services/Fragment.js @@ -1,4 +1,4 @@ -const get = require('lodash/get') +const { get, remove } = require('lodash') const User = require('./User') class Fragment { @@ -92,14 +92,14 @@ class Fragment { getInvitations({ isAccepted = true, role = 'reviewer', type }) { const { fragment: { invitations = [], recommendations = [] } } = this - let filteredInvitations = isAccepted + const filteredInvitations = isAccepted ? invitations.filter( inv => inv.role === role && inv.hasAnswer && inv.isAccepted, ) : invitations.filter(inv => inv.role === role && !inv.hasAnswer) if (type === 'submitted') { - filteredInvitations = filteredInvitations.filter(inv => + return filteredInvitations.filter(inv => recommendations.find( rec => rec.recommendationType === 'review' && @@ -108,12 +108,11 @@ class Fragment { ), ) } else if (type === 'accepted') { - filteredInvitations = filteredInvitations.filter(inv => - recommendations.find( - rec => - rec.recommendationType === 'review' && inv.userId !== rec.userId, - ), - ) + recommendations.forEach(rec => { + if (rec.recommendationType === 'review' && rec.submittedOn) { + remove(filteredInvitations, inv => inv.userId === rec.userId) + } + }) } return filteredInvitations diff --git a/packages/component-helper-service/src/tests/fragment.test.js b/packages/component-helper-service/src/tests/fragment.test.js index 3b5875eaf284e315ce1e3dd8a8792769e545e9c4..61e86748001df9b64466c7ed461bd1cf0c27c918 100644 --- a/packages/component-helper-service/src/tests/fragment.test.js +++ b/packages/component-helper-service/src/tests/fragment.test.js @@ -3,27 +3,238 @@ process.env.SUPPRESS_NO_CONFIG_WARNING = true const { cloneDeep } = require('lodash') const fixturesService = require('pubsweet-component-fixture-service') +const Chance = require('chance') +const chance = new Chance() const { fixtures } = fixturesService const { Fragment } = require('../Helper') +const acceptedReviewerId = chance.guid() +const submittedReviewerId1 = chance.guid() +const submittedReviewerId2 = chance.guid() +const fragment = { + invitations: [ + { + id: chance.guid(), + role: 'reviewer', + hasAnswer: true, + isAccepted: true, + userId: acceptedReviewerId, + invitedOn: chance.timestamp(), + respondedOn: chance.timestamp(), + type: 'invitation', + }, + { + id: chance.guid(), + role: 'reviewer', + hasAnswer: true, + isAccepted: true, + userId: submittedReviewerId1, + invitedOn: chance.timestamp(), + respondedOn: chance.timestamp(), + type: 'invitation', + }, + { + id: chance.guid(), + role: 'reviewer', + hasAnswer: true, + isAccepted: true, + userId: submittedReviewerId2, + invitedOn: chance.timestamp(), + respondedOn: chance.timestamp(), + type: 'invitation', + }, + ], + 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: submittedReviewerId1, + createdOn: chance.timestamp(), + updatedOn: chance.timestamp(), + submittedOn: chance.timestamp(), + }, + { + 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: submittedReviewerId2, + createdOn: chance.timestamp(), + updatedOn: chance.timestamp(), + submittedOn: chance.timestamp(), + }, + { + 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: acceptedReviewerId, + createdOn: chance.timestamp(), + updatedOn: chance.timestamp(), + }, + ], +} + describe('Fragment helper', () => { let testFixtures = {} + let testFragment = {} beforeEach(() => { testFixtures = cloneDeep(fixtures) + testFragment = cloneDeep(fragment) }) - it('hasReviewReport - should return true if the fragment has a review report', () => { - const { fragment } = testFixtures.fragments - const fragmentHelper = new Fragment({ fragment }) + describe('hasReviewReport', () => { + it('should return true if the fragment has a review report', () => { + const { fragment } = testFixtures.fragments + const fragmentHelper = new Fragment({ fragment }) + + expect(fragmentHelper.hasReviewReport()).toBeTruthy() + }) + it('should return false if the fragment does not have a review report', () => { + const { fragment } = testFixtures.fragments + fragment.recommendations = [] + const fragmentHelper = new Fragment({ fragment }) - expect(fragmentHelper.hasReviewReport()).toBeTruthy() + expect(fragmentHelper.hasReviewReport()).toBeFalsy() + }) }) - it('hasReviewReport - should return false if the fragment does not have a review report', () => { - const { fragment } = testFixtures.fragments - fragment.recommendations = [] - const fragmentHelper = new Fragment({ fragment }) - expect(fragmentHelper.hasReviewReport()).toBeFalsy() + describe('getInvitations', () => { + it('should return accepted invitations if type is accepted and a review report has been started', () => { + const fragmentHelper = new Fragment({ fragment: testFragment }) + + const acceptedInvitations = fragmentHelper.getInvitations({ + isAccepted: true, + type: 'accepted', + }) + + expect(acceptedInvitations).toHaveLength(1) + }) + it('should return accepted invitations if type is accepted and no review report has been started', () => { + testFragment.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: submittedReviewerId1, + createdOn: chance.timestamp(), + updatedOn: chance.timestamp(), + submittedOn: chance.timestamp(), + }, + { + 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: submittedReviewerId2, + createdOn: chance.timestamp(), + updatedOn: chance.timestamp(), + submittedOn: chance.timestamp(), + }, + ] + + const fragmentHelper = new Fragment({ fragment: testFragment }) + + const acceptedInvitations = fragmentHelper.getInvitations({ + isAccepted: true, + type: 'accepted', + }) + + expect(acceptedInvitations).toHaveLength(1) + }) + it('should return invitations of submitted reviewers if type is submitted', () => { + const fragmentHelper = new Fragment({ fragment: testFragment }) + + const submittedInvitations = fragmentHelper.getInvitations({ + isAccepted: true, + type: 'submitted', + }) + + expect(submittedInvitations).toHaveLength(2) + }) + it('should return invitations of pending reviewers if type is pending and isAccepted is false', () => { + testFragment.invitations.push({ + id: chance.guid(), + role: 'reviewer', + hasAnswer: false, + isAccepted: false, + userId: chance.guid(), + invitedOn: chance.timestamp(), + respondedOn: chance.timestamp(), + type: 'invitation', + }) + const fragmentHelper = new Fragment({ fragment: testFragment }) + + const pendingInvitations = fragmentHelper.getInvitations({ + isAccepted: false, + type: 'pending', + }) + + expect(pendingInvitations).toHaveLength(1) + }) }) })