From f968a38e95d86a59208b34198a167ea5be1e56bc Mon Sep 17 00:00:00 2001 From: Andres Pinto Date: Tue, 10 Dec 2024 01:09:36 -0400 Subject: [PATCH] chore: added tests for usage repository --- src/modules/file/file.usecase.spec.ts | 67 +++++++++ src/modules/usage/usage.repository.spec.ts | 154 +++++++++++++++++++++ src/modules/usage/usage.usecase.spec.ts | 2 +- 3 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 src/modules/usage/usage.repository.spec.ts diff --git a/src/modules/file/file.usecase.spec.ts b/src/modules/file/file.usecase.spec.ts index 161d97bf..62604902 100644 --- a/src/modules/file/file.usecase.spec.ts +++ b/src/modules/file/file.usecase.spec.ts @@ -36,6 +36,7 @@ import { SharingService } from '../sharing/sharing.service'; import { SharingItemType } from '../sharing/sharing.domain'; import { CreateFileDto } from './dto/create-file.dto'; import { UpdateFileMetaDto } from './dto/update-file-meta.dto'; +import { UsageUseCases } from '../usage/usage.usecase'; const fileId = '6295c99a241bb000083f1c6a'; const userId = 1; @@ -48,6 +49,8 @@ describe('FileUseCases', () => { let sharingService: SharingService; let bridgeService: BridgeService; let cryptoService: CryptoService; + let usageUsecases: UsageUseCases; + let networkService: BridgeService; const userMocked = User.build({ id: 1, @@ -94,6 +97,8 @@ describe('FileUseCases', () => { bridgeService = module.get(BridgeService); cryptoService = module.get(CryptoService); sharingService = module.get(SharingService); + usageUsecases = module.get(UsageUseCases); + networkService = module.get(BridgeService); }); afterEach(() => { @@ -1114,4 +1119,66 @@ describe('FileUseCases', () => { ); }); }); + + describe('replaceFile', () => { + const originalFile = newFile({ + attributes: { + size: BigInt(500), + status: FileStatus.EXISTS, + }, + }); + + const newFileData = { + fileId: v4(), + size: BigInt(1000), + }; + + it('When the file does not exist, it should throw', async () => { + jest.spyOn(fileRepository, 'findByUuid').mockResolvedValueOnce(null); + + await expect( + service.replaceFile(userMocked, originalFile.uuid, newFileData), + ).rejects.toThrow(NotFoundException); + }); + + it('When the file was deleted or trashed, it should throw', async () => { + const trashedFile = newFile({ + attributes: { ...originalFile, status: FileStatus.DELETED }, + }); + + jest + .spyOn(fileRepository, 'findByUuid') + .mockResolvedValueOnce(trashedFile); + + await expect( + service.replaceFile(userMocked, originalFile.uuid, newFileData), + ).rejects.toThrow(NotFoundException); + }); + + it('When the file exists and is valid, it updates the file data correctly', async () => { + jest + .spyOn(fileRepository, 'findByUuid') + .mockResolvedValueOnce(originalFile); + jest.spyOn(networkService, 'deleteFile').mockResolvedValueOnce(null); + jest.spyOn(fileRepository, 'updateByUuidAndUserId'); + jest + .spyOn(usageUsecases, 'addDailyUsageChangeOnFileSizeChange') + .mockResolvedValueOnce(null); + + await service.replaceFile(userMocked, originalFile.uuid, newFileData); + + expect(fileRepository.updateByUuidAndUserId).toHaveBeenCalledWith( + originalFile.uuid, + userMocked.id, + newFileData, + ); + expect( + usageUsecases.addDailyUsageChangeOnFileSizeChange, + ).toHaveBeenCalledWith( + userMocked, + originalFile, + expect.objectContaining(newFileData), + ); + }); + }); }); diff --git a/src/modules/usage/usage.repository.spec.ts b/src/modules/usage/usage.repository.spec.ts new file mode 100644 index 00000000..dd0ca1bc --- /dev/null +++ b/src/modules/usage/usage.repository.spec.ts @@ -0,0 +1,154 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { SequelizeUsageRepository } from './usage.repository'; +import { UsageModel } from './usage.model'; +import { getModelToken } from '@nestjs/sequelize'; +import { createMock } from '@golevelup/ts-jest'; +import { Usage, UsageType } from './usage.domain'; +import { newUsage, newUser } from '../../../test/fixtures'; + +const mockUsageInstance = (usageData): Partial => ({ + ...usageData, + toJSON: jest.fn().mockReturnValue(usageData), +}); + +const mockedUser = newUser(); +const mockSequelizeQuery = jest.fn(); + +describe('SequelizeUsageRepository', () => { + let repository: SequelizeUsageRepository; + let usageModel: typeof UsageModel; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [SequelizeUsageRepository], + }) + .useMocker((token) => { + if (token === getModelToken(UsageModel)) { + return { + findAll: jest.fn(), + findOne: jest.fn(), + create: jest.fn(), + sequelize: { + query: mockSequelizeQuery, + }, + }; + } + return createMock(); + }) + .compile(); + + repository = module.get(SequelizeUsageRepository); + usageModel = module.get(getModelToken(UsageModel)); + }); + + describe('getUserUsages', () => { + it('When usages are found for a user, it should return successfully', async () => { + const mockUsages = [ + mockUsageInstance(newUsage()), + mockUsageInstance(newUsage()), + ]; + jest + .spyOn(usageModel, 'findAll') + .mockResolvedValueOnce(mockUsages as any); + + const result = await repository.getUserUsages(mockedUser.uuid); + + expect(result).toHaveLength(mockUsages.length); + expect(result[0]).toBeInstanceOf(Usage); + }); + + it('When no usages are found for a user, it should return nothing', async () => { + jest.spyOn(usageModel, 'findAll').mockResolvedValueOnce([]); + + const result = await repository.getUserUsages(mockedUser.uuid); + + expect(result).toEqual([]); + }); + }); + + describe('create', () => { + it('When usage is created, it should return successfully', async () => { + const usage = newUsage(); + const mockUsage = mockUsageInstance(usage); + jest.spyOn(usageModel, 'create').mockResolvedValueOnce(mockUsage as any); + + const result = await repository.create(usage); + + expect(result).toBeInstanceOf(Usage); + expect(result.id).toEqual(mockUsage.id); + }); + }); + + describe('getMostRecentMonthlyOrYearlyUsage', () => { + it('When the most recent monthly or yearly usage exists, it should return successfully', async () => { + const mockUsage = mockUsageInstance( + newUsage({ attributes: { type: UsageType.Monthly } }), + ); + jest.spyOn(usageModel, 'findOne').mockResolvedValueOnce(mockUsage as any); + + const result = await repository.getMostRecentMonthlyOrYearlyUsage( + mockedUser.uuid, + ); + + expect(result).toBeInstanceOf(Usage); + expect(result.type).toBe(UsageType.Monthly); + }); + + it('When no recent monthly or yearly usage exists, it should return nothing', async () => { + jest.spyOn(usageModel, 'findOne').mockResolvedValueOnce(null); + + const result = await repository.getMostRecentMonthlyOrYearlyUsage( + mockedUser.uuid, + ); + + expect(result).toBeNull(); + }); + }); + + describe('getUsage', () => { + it('When a usage is found, it should return successfully', async () => { + const mockUsage = mockUsageInstance(newUsage()); + jest.spyOn(usageModel, 'findOne').mockResolvedValueOnce(mockUsage as any); + + const result = await repository.getUsage({ type: UsageType.Daily }); + + expect(result).toBeInstanceOf(Usage); + expect(result.type).toBe(UsageType.Daily); + }); + + it('When no usage is found, it should return null', async () => { + jest.spyOn(usageModel, 'findOne').mockResolvedValueOnce(null); + + const result = await repository.getUsage({ type: UsageType.Daily }); + + expect(result).toBeNull(); + expect(usageModel.findOne).toHaveBeenCalledWith({ + where: { type: UsageType.Daily }, + order: undefined, + }); + }); + }); + + describe('getUserUsage', () => { + it('When user usage is requested, it should return the aggregated totals', async () => { + mockSequelizeQuery.mockResolvedValueOnce([ + [ + { + total_yearly_delta: 500, + total_monthly_delta: 200, + }, + ], + ]); + + const result = await repository.getUserUsage(mockedUser.uuid); + + expect(mockSequelizeQuery).toHaveBeenCalledWith(expect.any(String), { + replacements: { userUuid: mockedUser.uuid }, + }); + expect(result).toEqual({ + total_yearly_delta: 500, + total_monthly_delta: 200, + }); + }); + }); +}); diff --git a/src/modules/usage/usage.usecase.spec.ts b/src/modules/usage/usage.usecase.spec.ts index 03316414..56f1a31c 100644 --- a/src/modules/usage/usage.usecase.spec.ts +++ b/src/modules/usage/usage.usecase.spec.ts @@ -20,7 +20,7 @@ describe('UsageUseCases', () => { const module: TestingModule = await Test.createTestingModule({ providers: [UsageUseCases], }) - .useMocker(createMock) + .useMocker(() => createMock()) .compile(); usageUseCases = module.get(UsageUseCases);