From 4d5d1445b458f9fba10135d0a65cbae02bc95153 Mon Sep 17 00:00:00 2001 From: Aleksandra Frost Date: Mon, 29 Apr 2024 14:00:15 +0200 Subject: [PATCH] [ADD] more tests for util --- .../services/proposal-contracting.service.ts | 4 +- .../handle-location-vote.util.spec.ts | 170 +++++++++++++----- .../utils/handle-location-vote.util.ts | 23 +-- 3 files changed, 142 insertions(+), 55 deletions(-) diff --git a/src/modules/proposal/services/proposal-contracting.service.ts b/src/modules/proposal/services/proposal-contracting.service.ts index 23bddd8..d4f9de9 100644 --- a/src/modules/proposal/services/proposal-contracting.service.ts +++ b/src/modules/proposal/services/proposal-contracting.service.ts @@ -1,3 +1,4 @@ +import { ProposalUploadService } from './proposal-upload.service'; import { ForbiddenException, Injectable, NotFoundException } from '@nestjs/common'; import { plainToClass } from 'class-transformer'; import { isNotEmptyObject } from 'class-validator'; @@ -49,6 +50,7 @@ export class ProposalContractingService { private eventEngineService: EventEngineService, private storageService: StorageService, private statusChangeService: StatusChangeService, + private proposalUploadService: ProposalUploadService, ) {} async setDizApproval(proposalId: string, vote: SetDizApprovalDto, user: IRequestUser): Promise { @@ -93,7 +95,7 @@ export class ProposalContractingService { const toBeUpdated = await this.proposalCrudService.findDocument(proposalId, user, undefined, true); validateRevertLocationDecision(toBeUpdated); - handleLocationDecision(toBeUpdated, location, user); + await handleLocationDecision(toBeUpdated, location, user, this.proposalUploadService); addHistoryItemForRevertLocationDecision(toBeUpdated, user, location); await toBeUpdated.save(); 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 24d16a5..0888583 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 @@ -8,8 +8,9 @@ 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 { DeclineReason } from '../../schema/sub-schema/decline-reason.schema'; +import { UacApproval } from '../../schema/sub-schema/uac-approval.schema'; import { addFdpgTaskAndReturnId, removeFdpgTask } from '../add-fdpg-task.util'; import { addDizApproval, @@ -19,6 +20,7 @@ import { handleLocationDecision, } from '../handle-location-vote.util'; import { clearLocationsVotes } from '../location-flow.util'; +import { ProposalUploadService } from '../../services/proposal-upload.service'; jest.mock('../location-flow.util', () => ({ clearLocationsVotes: jest.fn(), @@ -34,6 +36,10 @@ jest.mock('../validate-access.util', () => ({ getLocationState: jest.fn(), })); +const proposalUploadServiceMock = { + deleteUpload: jest.fn(), +} as any as ProposalUploadService; + describe('addLocationVoteUtil', () => { beforeEach(() => { jest.clearAllMocks(); @@ -251,81 +257,157 @@ describe('addLocationVoteUtil', () => { signedContractAndContractingDone: false, requestedButExcluded: false, }; + describe('handleLocationDecision', () => { const getLocationStateMock = jest.mocked(getLocationState); - it('should delete the declineReason object', () => { + + it('should delete the declineReason object', async () => { + const declineReason = new DeclineReason(); + declineReason.location = MiiLocation.UKRUB; const proposal = getProposalDocument(); - proposal.declineReasons = [{ location: MiiLocation.UKRUB, createdAt: new Date(), type: DeclineType.DizApprove }]; + proposal.declineReasons = [declineReason]; + proposal.openDizChecks = []; const request = getRequest(); - getLocationStateMock.mockReturnValue({ + getLocationStateMock.mockReturnValueOnce({ ...locationStateDefault, requestedButExcluded: true, }); - handleLocationDecision(proposal, request.user.miiLocation, request.user); + expect(proposal.declineReasons).toEqual([declineReason]); + await handleLocationDecision(proposal, declineReason.location, request.user, proposalUploadServiceMock); + expect(getLocationStateMock).toBeCalledWith(proposal, request.user); - expect(proposal.declineReasons).not.toEqual([request.user.miiLocation]); + expect(proposal.declineReasons).not.toEqual([declineReason]); + expect(proposal.declineReasons.length).toEqual(0); + expect(clearLocationsVotes).toBeCalledWith(proposal, declineReason.location); + expect(proposal.requestedButExcludedLocations).not.toEqual([request.user.miiLocation]); + expect(proposal.openDizChecks).toEqual([declineReason.location]); }); - it('should delete the uac approval object', () => { + it('should delete the uac approval object', async () => { + const uacApproval = new UacApproval(); + uacApproval.location = MiiLocation.UKRUB; const proposal = getProposalDocument(); - proposal.uacApprovals = [ - { - location: MiiLocation.UKRUB, - createdAt: new Date(), - dataAmount: 100, - isContractSigned: false, - _id: 'id', - signedAt: new Date(), - signedByOwnerId: 'userId', - }, - ]; + proposal.uacApprovals = [uacApproval]; + proposal.openDizChecks = []; + const request = getRequest(); - getLocationStateMock.mockReturnValue({ + getLocationStateMock.mockReturnValueOnce({ ...locationStateDefault, uacApproved: true, }); - handleLocationDecision(proposal, request.user.miiLocation, request.user); + expect(proposal.uacApprovals).toEqual([uacApproval]); + await handleLocationDecision(proposal, uacApproval.location, request.user, proposalUploadServiceMock); expect(getLocationStateMock).toBeCalledWith(proposal, request.user); - expect(proposal.uacApprovals).not.toEqual([request.user.miiLocation]); + expect(proposal.uacApprovals.length).toEqual(0); + expect(proposal.uacApprovals).not.toEqual([uacApproval]); + expect(clearLocationsVotes).toBeCalledWith(proposal, uacApproval.location); + expect(proposal.requestedButExcludedLocations).not.toEqual([request.user.miiLocation]); + expect(proposal.openDizChecks).toEqual([uacApproval.location]); }); - it('should handle all actions in case of conditional approval', () => { - const proposal = getProposalDocument(); - proposal.conditionalApprovals = [ + describe('should remove Fdpg Task in case of expected data amount reached', () => { + const testCases = [ { - 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', + name: 'expected data amount is reached even withouth the location data amount', + dataAmount: 10, + expectedDataAmountReached: true, + }, + { + name: 'expected data amount is not reached withouth the location data amount', + dataAmount: 12, + expectedDataAmountReached: false, }, ]; + + test.each(testCases)('%s', async ({ dataAmount, expectedDataAmountReached }) => { + const approval = new UacApproval(); + approval.location = MiiLocation.UKRUB; + approval.dataAmount = dataAmount; + const condition = new ConditionalApproval(); + condition.location = MiiLocation.UKRUB; + condition.fdpgTaskId = FdpgTaskType.ConditionApproval; + condition.dataAmount = 10; + const proposal = getProposalDocument(); + proposal.conditionalApprovals = [condition]; + proposal.uacApprovals = [approval]; + proposal.totalPromisedDataAmount = 21; + proposal.requestedData.desiredDataAmount = 11; + proposal.openDizChecks = []; + + const request = getRequest(); + + getLocationStateMock.mockReturnValueOnce({ + ...locationStateDefault, + conditionalApprovalAccepted: true, + }); + + expect(proposal.uacApprovals).toEqual([approval]); + await handleLocationDecision(proposal, approval.location, request.user, proposalUploadServiceMock); + expect(getLocationStateMock).toBeCalledWith(proposal, request.user); + if (expectedDataAmountReached) { + expect(removeFdpgTask).not.toBeCalledWith(proposal, FdpgTaskType.DataAmountReached); + } else { + expect(removeFdpgTask).toBeCalledWith(proposal, FdpgTaskType.DataAmountReached); + } + expect(clearLocationsVotes).toBeCalledWith(proposal, condition.location); + expect(proposal.requestedButExcludedLocations).not.toEqual([request.user.miiLocation]); + expect(proposal.openDizChecks).toEqual([condition.location]); + }); + }); + + it('should delete conditional approval object and fdpg task', async () => { + const condition = new ConditionalApproval(); + condition.location = MiiLocation.UKRUB; + condition.fdpgTaskId = FdpgTaskType.ConditionApproval; + condition.dataAmount = 10; + const proposal = getProposalDocument(); + proposal.conditionalApprovals = [condition]; + proposal.totalPromisedDataAmount = condition.dataAmount + 1; + proposal.requestedData.desiredDataAmount = 11; + proposal.openDizChecks = []; + const request = getRequest(); - const isDataAmountReached = false; - getLocationStateMock.mockReturnValue({ + getLocationStateMock.mockReturnValueOnce({ ...locationStateDefault, conditionalApprovalAccepted: true, }); - handleLocationDecision(proposal, request.user.miiLocation, request.user); + expect(proposal.conditionalApprovals).toEqual([condition]); + await handleLocationDecision(proposal, condition.location, request.user, proposalUploadServiceMock); + expect(getLocationStateMock).toBeCalledWith(proposal, request.user); + expect(removeFdpgTask).toBeCalledWith(proposal, condition.fdpgTaskId); + expect(proposal.conditionalApprovals).not.toEqual([condition]); + expect(clearLocationsVotes).toBeCalledWith(proposal, condition.location); + expect(proposal.requestedButExcludedLocations).not.toEqual([request.user.miiLocation]); + expect(proposal.openDizChecks).toEqual([condition.location]); + }); + + it('should delete the upload blob', async () => { + const condition = new ConditionalApproval(); + condition.location = MiiLocation.UKRUB; + condition.uploadId = 'uploadId'; + const proposal = getProposalDocument(); + proposal.conditionalApprovals = [condition]; + proposal.openDizChecks = []; + const request = getRequest(); + + getLocationStateMock.mockReturnValueOnce({ + ...locationStateDefault, + isConditionalApproval: true, + }); + + await handleLocationDecision(proposal, condition.location, request.user, proposalUploadServiceMock); 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, - ); + expect(proposalUploadServiceMock.deleteUpload).toBeCalledTimes(1); + expect(proposalUploadServiceMock.deleteUpload).toBeCalledWith(proposal._id, condition.uploadId, request.user); + expect(clearLocationsVotes).toBeCalledWith(proposal, condition.location); + expect(proposal.requestedButExcludedLocations).not.toEqual([request.user.miiLocation]); + expect(proposal.openDizChecks).toEqual([condition.location]); }); }); }); diff --git a/src/modules/proposal/utils/handle-location-vote.util.ts b/src/modules/proposal/utils/handle-location-vote.util.ts index 4bb354b..73c8d84 100644 --- a/src/modules/proposal/utils/handle-location-vote.util.ts +++ b/src/modules/proposal/utils/handle-location-vote.util.ts @@ -13,6 +13,7 @@ import { addFdpgTaskAndReturnId, removeFdpgTask } from './add-fdpg-task.util'; import { clearLocationsVotes } from './location-flow.util'; import { getLocationState } from './validate-access.util'; import { RevertLocationDecisionDto } from '../dto/revert-location-decision.dto'; +import { ProposalUploadService } from '../services/proposal-upload.service'; export const addDizApproval = (proposal: Proposal, user: IRequestUser, vote: SetDizApprovalDto) => { clearLocationsVotes(proposal, user.miiLocation); @@ -149,7 +150,12 @@ export const addUacConditionReview = ( } }; -export const handleLocationDecision = (proposal: Proposal, location: MiiLocation, user: IRequestUser) => { +export const handleLocationDecision = async ( + proposal: Proposal, + location: MiiLocation, + user: IRequestUser, + proposalUploadService: ProposalUploadService, +) => { const locationState = getLocationState(proposal, user); if (locationState.requestedButExcluded) { @@ -169,23 +175,20 @@ export const handleLocationDecision = (proposal: Proposal, location: MiiLocation const locationDataAmount = proposal.uacApprovals.find((approval) => approval.location === location)?.dataAmount; - proposal.totalPromisedDataAmount - ? proposal.totalPromisedDataAmount === proposal.totalPromisedDataAmount - locationDataAmount - : proposal.totalPromisedDataAmount === 0; + proposal.totalPromisedDataAmount = proposal.totalPromisedDataAmount - locationDataAmount; const isDataAmountReached = proposal.totalPromisedDataAmount >= (proposal.requestedData.desiredDataAmount ?? 0); if (!isDataAmountReached) { removeFdpgTask(proposal, FdpgTaskType.DataAmountReached); } + } + if (locationState.isConditionalApproval) { + const uploadId = proposal.conditionalApprovals.find((approval) => approval.location === location)?.uploadId; - 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); + if (uploadId) { + await proposalUploadService.deleteUpload(proposal._id, uploadId, user); } - - deleteConditionalUpload(proposal, location, user); } - clearLocationsVotes(proposal, location); proposal.openDizChecks.push(location); };