process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' process.env.SUPPRESS_NO_CONFIG_WARNING = true const Chance = require('chance') const config = require('config') const { cloneDeep } = require('lodash') const fixturesService = require('pubsweet-component-fixture-service') const chance = new Chance() const { fixtures, Model } = fixturesService const { Fragment } = require('../Helper') const { recommendations: configRecommendations } = config const acceptedReviewerId = chance.guid() const submittedReviewerId1 = chance.guid() const submittedReviewerId2 = chance.guid() const handlingEditorId = chance.guid() const editorInChiefId = 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 = {} let models = {} beforeEach(() => { testFixtures = cloneDeep(fixtures) testFragment = cloneDeep(fragment) models = Model.build(testFixtures) }) 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()).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) }) }) describe('getReviewersAndEditorsData', () => { it('should return an array of users (reviewers, editors) that have submitted a review', async () => { const { collection } = testFixtures.collections const { fragment } = testFixtures.fragments const fragmentHelper = new Fragment({ fragment }) const fragmentUsers = await fragmentHelper.getReviewersAndEditorsData({ collection, UserModel: models.User, }) expect(fragmentUsers.length).toBeGreaterThan(0) const submittedRecommendations = fragment.recommendations.filter( rec => rec.recommendationType === configRecommendations.type.editor || (rec.recommendationType === configRecommendations.type.review && rec.submittedOn), ) expect(fragmentUsers).toHaveLength(submittedRecommendations.length) }) it('should return an error when the collection does not have a handling editor', async () => { const { collection } = testFixtures.collections const { fragment } = testFixtures.fragments const fragmentHelper = new Fragment({ fragment }) delete collection.handlingEditor try { await fragmentHelper.getReviewersAndEditorsData({ collection, UserModel: models.User, }) } catch (e) { expect(e.message).toEqual( `Collection ${collection.id} does not have a Handling Editor`, ) } }) }) describe('canHEMakeAnotherRecommendation', () => { it('should return true when He makes a recommendation after EIC decision was to return to HE', async () => { testFragment.recommendations = [ { recommendation: 'publish', recommendationType: 'editorRecommendation', comments: [ { content: chance.paragraph(), public: true, files: [ { id: chance.guid(), name: 'file.pdf', size: chance.natural(), }, ], }, ], id: chance.guid(), userId: handlingEditorId, createdOn: 1542361074012, updatedOn: chance.timestamp(), }, { recommendation: 'return-to-handling-editor', recommendationType: 'editorRecommendation', comments: [ { content: chance.paragraph(), public: true, files: [ { id: chance.guid(), name: 'file.pdf', size: chance.natural(), }, ], }, ], id: chance.guid(), userId: editorInChiefId, createdOn: 1542361115749, updatedOn: chance.timestamp(), }, ] const currentUserRecommendations = testFragment.recommendations.filter( r => r.userId === handlingEditorId, ) const fragmentHelper = new Fragment({ fragment: testFragment }) const canHEMakeAnotherRecommendation = await fragmentHelper.canHEMakeAnotherRecommendation( currentUserRecommendations, ) expect(canHEMakeAnotherRecommendation).toBe(true) }) it('should return false when He makes another recommendation', async () => { testFragment.recommendations = [ { recommendation: 'publish', recommendationType: 'editorRecommendation', comments: [ { content: chance.paragraph(), public: true, files: [ { id: chance.guid(), name: 'file.pdf', size: chance.natural(), }, ], }, ], id: chance.guid(), userId: handlingEditorId, createdOn: 1542361074012, updatedOn: chance.timestamp(), }, ] const currentUserRecommendations = testFragment.recommendations.filter( r => r.userId === handlingEditorId, ) const fragmentHelper = new Fragment({ fragment: testFragment }) const canHEMakeAnotherRecommendation = await fragmentHelper.canHEMakeAnotherRecommendation( currentUserRecommendations, ) expect(canHEMakeAnotherRecommendation).toBe(false) }) }) })