Skip to content

Commit

Permalink
[ADD] more tests for util
Browse files Browse the repository at this point in the history
  • Loading branch information
af-ofr committed Apr 29, 2024
1 parent 69e2717 commit 4d5d144
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 55 deletions.
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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<void> {
Expand Down Expand Up @@ -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();
Expand Down
170 changes: 126 additions & 44 deletions src/modules/proposal/utils/__tests__/handle-location-vote.util.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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(),
Expand All @@ -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();
Expand Down Expand Up @@ -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]);
});
});
});
23 changes: 13 additions & 10 deletions src/modules/proposal/utils/handle-location-vote.util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand All @@ -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<void> {
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);
};

0 comments on commit 4d5d144

Please sign in to comment.