import 'reflect-metadata'; import { plainToInstance } from 'class-transformer'; import { validate } from 'class-validator'; import { QueryOperationLogsDto } from './dto/operation-log.dto'; import { OperationLogsService } from './operation-logs.service'; const createQb = () => ({ orderBy: jest.fn().mockReturnThis(), andWhere: jest.fn().mockReturnThis(), skip: jest.fn().mockReturnThis(), take: jest.fn().mockReturnThis(), getManyAndCount: jest.fn().mockResolvedValue([[], 0]), }); describe('operation log query boundaries', () => { it.each(['0', '-1', '1.5', 'abc'])('rejects invalid page %s', async (page) => { const dto = plainToInstance(QueryOperationLogsDto, { page }); expect((await validate(dto)).some((error) => error.property === 'page')).toBe(true); }); it.each(['0', '201', '1.5', 'abc'])('rejects invalid page size %s', async (pageSize) => { const dto = plainToInstance(QueryOperationLogsDto, { pageSize }); expect((await validate(dto)).some((error) => error.property === 'pageSize')).toBe(true); }); it.each(['2026-02-31', '2026-07-13T00:00:00Z'])( 'rejects invalid or non-date-only value %s', async (startDate) => { const dto = plainToInstance(QueryOperationLogsDto, { startDate }); expect((await validate(dto)).some((error) => error.property === 'startDate')).toBe(true); }, ); it('transforms valid pagination and applies its database window', async () => { const dto = plainToInstance(QueryOperationLogsDto, { page: '2', pageSize: '20' }); expect(await validate(dto)).toEqual([]); const qb = createQb(); const service = new OperationLogsService({ createQueryBuilder: jest.fn().mockReturnValue(qb) } as never); await service.findAll(dto); expect(qb.skip).toHaveBeenCalledWith(20); expect(qb.take).toHaveBeenCalledWith(20); }); it('rejects a reversed period before opening a query', async () => { const repo = { createQueryBuilder: jest.fn() }; const service = new OperationLogsService(repo as never); await expect(service.findAll({ startDate: '2026-08-01', endDate: '2026-07-31' })) .rejects.toThrow('结束日期不能早于开始日期'); expect(repo.createQueryBuilder).not.toHaveBeenCalled(); }); });