diff --git a/src/modules/proposal/utils/__tests__/handle-location-vote.util.spec.ts b/src/modules/proposal/utils/__tests__/handle-location-vote.util.spec.ts index 18f9012..24d16a5 100644 --- a/src/modules/proposal/utils/__tests__/handle-location-vote.util.spec.ts +++ b/src/modules/proposal/utils/__tests__/handle-location-vote.util.spec.ts @@ -1,3 +1,4 @@ +import { getLocationState } from './../validate-access.util'; import { MiiLocation } from 'src/shared/constants/mii-locations'; import { Role } from 'src/shared/enums/role.enum'; import { FdpgRequest } from 'src/shared/types/request-user.interface'; @@ -7,6 +8,7 @@ import { UploadDto } from '../../dto/upload.dto'; import { FdpgTaskType } from '../../enums/fdpg-task-type.enum'; import { ProposalStatus } from '../../enums/proposal-status.enum'; import { ProposalDocument } from '../../schema/proposal.schema'; +import { DeclineType } from '../../enums/decline-type.enum'; import { ConditionalApproval } from '../../schema/sub-schema/conditional-approval.schema'; import { addFdpgTaskAndReturnId, removeFdpgTask } from '../add-fdpg-task.util'; import { @@ -14,11 +16,13 @@ import { addUacApproval, addUacApprovalWithCondition, addUacConditionReview, + handleLocationDecision, } from '../handle-location-vote.util'; import { clearLocationsVotes } from '../location-flow.util'; jest.mock('../location-flow.util', () => ({ clearLocationsVotes: jest.fn(), + deleteConditionalUpload: jest.fn(), })); jest.mock('../add-fdpg-task.util', () => ({ @@ -26,6 +30,10 @@ jest.mock('../add-fdpg-task.util', () => ({ removeFdpgTask: jest.fn(), })); +jest.mock('../validate-access.util', () => ({ + getLocationState: jest.fn(), +})); + describe('addLocationVoteUtil', () => { beforeEach(() => { jest.clearAllMocks(); @@ -229,4 +237,95 @@ describe('addLocationVoteUtil', () => { expect(proposal.requestedButExcludedLocations).toEqual([condition.location]); }); }); + + const locationStateDefault: ReturnType = { + isDizCheck: false, + dizApproved: false, + uacApproved: false, + isConditionalApproval: false, + conditionalApprovalAccepted: false, + conditionalApprovalDeclined: false, + contractAcceptedByResearcher: false, + contractRejectedByResearcher: false, + signedContract: false, + signedContractAndContractingDone: false, + requestedButExcluded: false, + }; + describe('handleLocationDecision', () => { + const getLocationStateMock = jest.mocked(getLocationState); + it('should delete the declineReason object', () => { + const proposal = getProposalDocument(); + proposal.declineReasons = [{ location: MiiLocation.UKRUB, createdAt: new Date(), type: DeclineType.DizApprove }]; + const request = getRequest(); + + getLocationStateMock.mockReturnValue({ + ...locationStateDefault, + requestedButExcluded: true, + }); + + handleLocationDecision(proposal, request.user.miiLocation, request.user); + expect(getLocationStateMock).toBeCalledWith(proposal, request.user); + expect(proposal.declineReasons).not.toEqual([request.user.miiLocation]); + }); + + it('should delete the uac approval object', () => { + const proposal = getProposalDocument(); + proposal.uacApprovals = [ + { + location: MiiLocation.UKRUB, + createdAt: new Date(), + dataAmount: 100, + isContractSigned: false, + _id: 'id', + signedAt: new Date(), + signedByOwnerId: 'userId', + }, + ]; + const request = getRequest(); + + getLocationStateMock.mockReturnValue({ + ...locationStateDefault, + uacApproved: true, + }); + + handleLocationDecision(proposal, request.user.miiLocation, request.user); + expect(getLocationStateMock).toBeCalledWith(proposal, request.user); + expect(proposal.uacApprovals).not.toEqual([request.user.miiLocation]); + }); + + it('should handle all actions in case of conditional approval', () => { + const proposal = getProposalDocument(); + proposal.conditionalApprovals = [ + { + location: MiiLocation.UKRUB, + createdAt: new Date(), + dataAmount: 100, + isContractSigned: false, + _id: 'id', + signedAt: new Date(), + signedByOwnerId: 'userId', + isAccepted: true, + uploadId: 'uploadId', + fdpgTaskId: 'fdpgTaskId', + reviewedAt: new Date(), + reviewedByOwnerId: 'userId', + }, + ]; + const request = getRequest(); + const isDataAmountReached = false; + + getLocationStateMock.mockReturnValue({ + ...locationStateDefault, + conditionalApprovalAccepted: true, + }); + + handleLocationDecision(proposal, request.user.miiLocation, request.user); + expect(getLocationStateMock).toBeCalledWith(proposal, request.user); + expect(removeFdpgTask).toBeCalledWith(proposal, 'fdpgTaskId'); + expect(proposal.conditionalApprovals).not.toEqual([request.user.miiLocation]); + expect(proposal.totalPromisedDataAmount).toEqual( + proposal.totalPromisedDataAmount - proposal.conditionalApprovals[0].dataAmount, + ); + }); + }); }); diff --git a/src/modules/proposal/utils/handle-location-vote.util.ts b/src/modules/proposal/utils/handle-location-vote.util.ts index 2c12c27..4bb354b 100644 --- a/src/modules/proposal/utils/handle-location-vote.util.ts +++ b/src/modules/proposal/utils/handle-location-vote.util.ts @@ -152,39 +152,32 @@ export const addUacConditionReview = ( export const handleLocationDecision = (proposal: Proposal, location: MiiLocation, user: IRequestUser) => { const locationState = getLocationState(proposal, user); - // delete declineReasons of location from declineReasons array if (locationState.requestedButExcluded) { proposal.declineReasons = proposal.declineReasons.filter((reason) => reason.location !== location); } - // delete uac approval object in case of vote=true and no conditions + if (locationState.uacApproved) { proposal.uacApprovals = proposal.uacApprovals.filter((approval) => approval.location !== location); } - // handle all actions in case of conditional approval if (locationState.conditionalApprovalAccepted) { - // delete the task with this type removeFdpgTask(proposal, FdpgTaskType.ConditionApproval); - // delete uac approval object in case of vote=true and conditions proposal.conditionalApprovals = proposal.conditionalApprovals.filter( (condition) => condition.location !== location, ); - // update dataAmount by substracting the dataAmount from this location const locationDataAmount = proposal.uacApprovals.find((approval) => approval.location === location)?.dataAmount; proposal.totalPromisedDataAmount ? proposal.totalPromisedDataAmount === proposal.totalPromisedDataAmount - locationDataAmount : proposal.totalPromisedDataAmount === 0; - // check if desiredDataAmount is now reached. if not, delete a Task with this type const isDataAmountReached = proposal.totalPromisedDataAmount >= (proposal.requestedData.desiredDataAmount ?? 0); if (!isDataAmountReached) { removeFdpgTask(proposal, FdpgTaskType.DataAmountReached); } - // delete the upload from conditional approval async function deleteConditionalUpload(proposal: Proposal, revert: MiiLocation, user: IRequestUser): Promise { const uploadId = proposal.conditionalApprovals.find((approval) => approval.location === revert)?.uploadId; return await this.proposalUploadService.deleteUpload(proposal._id, uploadId, user); @@ -193,7 +186,6 @@ export const handleLocationDecision = (proposal: Proposal, location: MiiLocation deleteConditionalUpload(proposal, location, user); } - // delete location from arrays: dizApprovedLocations, uacApprovedLocations, requestedButExcludedLocations and add back to openDizChecks clearLocationsVotes(proposal, location); proposal.openDizChecks.push(location); };