forked from wangziqi/gongxue-base
82 lines
3.4 KiB
TypeScript
82 lines
3.4 KiB
TypeScript
import { BadRequestException, NotFoundException } from '@nestjs/common';
|
|
import { BillsService } from './bills.service';
|
|
import { Bill } from '../entities/bill.entity';
|
|
|
|
function queryBuilder() {
|
|
return {
|
|
update: jest.fn().mockReturnThis(),
|
|
set: jest.fn().mockReturnThis(),
|
|
where: jest.fn().mockReturnThis(),
|
|
execute: jest.fn().mockResolvedValue({ affected: 1 }),
|
|
};
|
|
}
|
|
|
|
function createService(bills: Partial<Bill>[] = []) {
|
|
const billRepo = {
|
|
find: jest.fn().mockResolvedValue(bills),
|
|
findOne: jest.fn().mockResolvedValue(bills[0] ?? null),
|
|
save: jest.fn(async (value) => value),
|
|
update: jest.fn(),
|
|
createQueryBuilder: jest.fn(() => queryBuilder()),
|
|
};
|
|
const manager = {
|
|
delete: jest.fn(),
|
|
update: jest.fn(),
|
|
};
|
|
const dataSource = { transaction: jest.fn(async (callback) => callback(manager)) };
|
|
const service = new BillsService(
|
|
billRepo as any,
|
|
{ delete: jest.fn() } as any,
|
|
{} as any,
|
|
{ update: jest.fn() } as any,
|
|
{} as any,
|
|
{} as any,
|
|
dataSource as any,
|
|
{} as any,
|
|
);
|
|
return { service, billRepo, dataSource, manager };
|
|
}
|
|
|
|
describe('BillsService state and batch boundaries', () => {
|
|
it('rejects an empty batch status update', async () => {
|
|
const { service, billRepo } = createService();
|
|
await expect(service.batchUpdateStatus([], 'paid')).rejects.toBeInstanceOf(BadRequestException);
|
|
expect(billRepo.find).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('rejects a batch status update when some ids do not exist', async () => {
|
|
const { service, billRepo } = createService([{ id: 1, paidAmount: 0, outstandingAmount: 10 }]);
|
|
await expect(service.batchUpdateStatus([1, 2], 'unpaid')).rejects.toBeInstanceOf(NotFoundException);
|
|
expect(billRepo.createQueryBuilder).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('rejects marking a partially paid bill unpaid', async () => {
|
|
const { service, billRepo } = createService([{ id: 1, paidAmount: 10, outstandingAmount: 90, status: 'partially_paid' }]);
|
|
await expect(service.updateStatus(1, { status: 'unpaid' })).rejects.toBeInstanceOf(BadRequestException);
|
|
expect(billRepo.save).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('rejects an empty batch archive', async () => {
|
|
const { service, dataSource } = createService();
|
|
await expect(service.batchRemove([])).rejects.toBeInstanceOf(BadRequestException);
|
|
expect(dataSource.transaction).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('rejects a batch archive when some ids do not exist', async () => {
|
|
const { service, dataSource } = createService([{ id: 1, paidAmount: 0, status: 'unpaid' }]);
|
|
await expect(service.batchRemove([1, 2])).rejects.toBeInstanceOf(NotFoundException);
|
|
expect(dataSource.transaction).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('archives an unpaid bill without deleting rows', async () => {
|
|
const { service, billRepo, dataSource, manager } = createService([{ id: 1, paidAmount: 0, status: 'unpaid' }]);
|
|
await expect(service.remove(1)).resolves.toEqual({ message: '账单已归档' });
|
|
expect(billRepo.save).not.toHaveBeenCalled();
|
|
expect(billRepo.createQueryBuilder).not.toHaveBeenCalled();
|
|
expect(billRepo.findOne).toHaveBeenCalledWith({ where: { id: 1 } });
|
|
expect((billRepo as any).update).toHaveBeenCalledWith(1, expect.objectContaining({ status: 'cancelled' }));
|
|
expect(dataSource.transaction).not.toHaveBeenCalled();
|
|
expect(manager.delete).not.toHaveBeenCalled();
|
|
});
|
|
});
|