From 57d6dedbcd0006b8adcdb666af6a2fd3768b1e4e Mon Sep 17 00:00:00 2001 From: Justin Wang Date: Sun, 26 Apr 2026 14:29:54 -0400 Subject: [PATCH] test --- .../src/allocations/allocations.controller.ts | 7 - .../src/allocations/allocations.module.ts | 2 - .../allocations/allocations.service.spec.ts | 170 ++++++++++++++++++ 3 files changed, 170 insertions(+), 9 deletions(-) delete mode 100644 apps/backend/src/allocations/allocations.controller.ts create mode 100644 apps/backend/src/allocations/allocations.service.spec.ts diff --git a/apps/backend/src/allocations/allocations.controller.ts b/apps/backend/src/allocations/allocations.controller.ts deleted file mode 100644 index 06cdd4fc9..000000000 --- a/apps/backend/src/allocations/allocations.controller.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Controller } from '@nestjs/common'; -import { AllocationsService } from './allocations.service'; - -@Controller('allocations') -export class AllocationsController { - constructor(private allocationsService: AllocationsService) {} -} diff --git a/apps/backend/src/allocations/allocations.module.ts b/apps/backend/src/allocations/allocations.module.ts index 7d62e964d..4fccf7065 100644 --- a/apps/backend/src/allocations/allocations.module.ts +++ b/apps/backend/src/allocations/allocations.module.ts @@ -1,7 +1,6 @@ import { forwardRef, Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { Allocation } from './allocations.entity'; -import { AllocationsController } from './allocations.controller'; import { AllocationsService } from './allocations.service'; import { AuthModule } from '../auth/auth.module'; import { DonationItemsModule } from '../donationItems/donationItems.module'; @@ -13,7 +12,6 @@ import { DonationItem } from '../donationItems/donationItems.entity'; forwardRef(() => AuthModule), DonationItemsModule, ], - controllers: [AllocationsController], providers: [AllocationsService], exports: [AllocationsService], }) diff --git a/apps/backend/src/allocations/allocations.service.spec.ts b/apps/backend/src/allocations/allocations.service.spec.ts new file mode 100644 index 000000000..0c55e71b9 --- /dev/null +++ b/apps/backend/src/allocations/allocations.service.spec.ts @@ -0,0 +1,170 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { getRepositoryToken } from '@nestjs/typeorm'; +import { BadRequestException } from '@nestjs/common'; +import { testDataSource } from '../config/typeormTestDataSource'; +import { AllocationsService } from './allocations.service'; +import { Allocation } from './allocations.entity'; +import { DonationItem } from '../donationItems/donationItems.entity'; + +jest.setTimeout(60000); + +describe('AllocationsService', () => { + let service: AllocationsService; + + beforeAll(async () => { + if (!testDataSource.isInitialized) { + await testDataSource.initialize(); + } + await testDataSource.query(`DROP SCHEMA IF EXISTS public CASCADE`); + await testDataSource.query(`CREATE SCHEMA public`); + + const module: TestingModule = await Test.createTestingModule({ + providers: [ + AllocationsService, + { + provide: getRepositoryToken(Allocation), + useValue: testDataSource.getRepository(Allocation), + }, + { + provide: getRepositoryToken(DonationItem), + useValue: testDataSource.getRepository(DonationItem), + }, + ], + }).compile(); + + service = module.get(AllocationsService); + }); + + beforeEach(async () => { + await testDataSource.query(`DROP SCHEMA IF EXISTS public CASCADE`); + await testDataSource.query(`CREATE SCHEMA public`); + await testDataSource.runMigrations(); + }); + + afterEach(async () => { + await testDataSource.query(`DROP SCHEMA public CASCADE`); + await testDataSource.query(`CREATE SCHEMA public`); + }); + + afterAll(async () => { + if (testDataSource.isInitialized) { + await testDataSource.destroy(); + } + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); + + describe('getAllAllocationsByOrder', () => { + it('should return empty array for order with no allocations', async () => { + await testDataSource.query(`DELETE FROM allocations WHERE order_id = 1`); + + const result = await service.getAllAllocationsByOrder(1); + + expect(result).toEqual([]); + }); + + it('should return all allocations for a given order', async () => { + const result = await service.getAllAllocationsByOrder(2); + + expect(result).toHaveLength(3); + const quantities = result + .map((a) => a.allocatedQuantity) + .sort((a, b) => a! - b!); + expect(quantities).toEqual([15, 20, 30]); + result.forEach((a) => { + expect(a.allocationId).toBeDefined(); + expect(a.item).toBeDefined(); + }); + }); + }); + + describe('createMultiple', () => { + it('should create a single allocation and increment reservedQuantity', async () => { + const orderId = 1; + const itemId = 4; + + const result = await service.createMultiple( + orderId, + new Map([[itemId, 3]]), + ); + + expect(result).toHaveLength(1); + expect(result[0].allocatedQuantity).toBe(3); + expect(result[0].orderId).toBe(orderId); + expect(result[0].itemId).toBe(itemId); + const [{ reserved_quantity }] = await testDataSource.query( + `SELECT reserved_quantity FROM donation_items WHERE item_id = $1`, + [itemId], + ); + expect(Number(reserved_quantity)).toBe(33); + }); + + it('should create multiple allocations and increment each reservedQuantity', async () => { + const orderId = 1; + const itemId1 = 4; + const itemId2 = 5; + + const result = await service.createMultiple( + orderId, + new Map([ + [itemId1, 5], + [itemId2, 2], + ]), + ); + + expect(result).toHaveLength(2); + const [item1] = await testDataSource.query( + `SELECT reserved_quantity FROM donation_items WHERE item_id = $1`, + [itemId1], + ); + const [item2] = await testDataSource.query( + `SELECT reserved_quantity FROM donation_items WHERE item_id = $1`, + [itemId2], + ); + expect(Number(item1.reserved_quantity)).toBe(35); + expect(Number(item2.reserved_quantity)).toBe(22); + }); + + it('should throw BadRequestException for orderId of 0', async () => { + await expect( + service.createMultiple(0, new Map([[1, 1]])), + ).rejects.toThrow(new BadRequestException('Invalid Order ID')); + }); + + it('should throw BadRequestException for negative orderId', async () => { + await expect( + service.createMultiple(-5, new Map([[1, 1]])), + ).rejects.toThrow(new BadRequestException('Invalid Order ID')); + }); + + it('should throw BadRequestException for itemId of 0', async () => { + await expect( + service.createMultiple(1, new Map([[0, 1]])), + ).rejects.toThrow(new BadRequestException('Invalid Donation Item ID')); + }); + + it('should work with a given transaction manager', async () => { + const orderId = 1; + const itemId = 4; + + let result: Allocation[] = []; + await testDataSource.transaction(async (manager) => { + result = await service.createMultiple( + orderId, + new Map([[itemId, 4]]), + manager, + ); + }); + + expect(result).toHaveLength(1); + expect(result[0].allocatedQuantity).toBe(4); + const [{ reserved_quantity }] = await testDataSource.query( + `SELECT reserved_quantity FROM donation_items WHERE item_id = $1`, + [itemId], + ); + expect(Number(reserved_quantity)).toBe(34); + }); + }); +});