Skip to content
Snippets Groups Projects
fragment.test.js 11.1 KiB
Newer Older
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 { 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 models = {}
  beforeEach(() => {
    testFixtures = cloneDeep(fixtures)
    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(),
          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(),
          createdOn: chance.timestamp(),
          updatedOn: 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)
    })
  })