test: add unit tests for Schedules, Bills, and Attendance services

This commit is contained in:
2026-07-05 20:51:24 +08:00
parent 09580e4a4e
commit a7a1969d79
3 changed files with 396 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
import { Test, TestingModule } from '@nestjs/testing';
import { getRepositoryToken } from '@nestjs/typeorm';
import { BadRequestException, ValidationPipe } from '@nestjs/common';
import { Repository } from 'typeorm';
import { AttendanceService } from './attendance.service';
import { AttendanceRecord } from '../entities/attendance-record.entity';
import { DingAttendanceRaw } from '../entities/ding-attendance-raw.entity';
import { BatchCreateAttendanceDto } from './dto/attendance.dto';
describe('AttendanceService — batchCreate', () => {
let service: AttendanceService;
let attendanceRepo: jest.Mocked<Pick<Repository<AttendanceRecord>, 'create' | 'save'>>;
const savedRecords: AttendanceRecord[] = [];
beforeEach(async () => {
savedRecords.length = 0;
const mockRepo = {
create: jest
.fn()
.mockImplementation((data: Partial<AttendanceRecord>) => ({ id: 1, ...data } as AttendanceRecord)),
save: jest
.fn()
.mockImplementation((entities: AttendanceRecord[]) => {
const result = entities.map((e, i) => ({ ...e, id: i + 1 } as AttendanceRecord));
savedRecords.push(...result);
return Promise.resolve(result);
}),
};
const mockDingRepo = {};
const module: TestingModule = await Test.createTestingModule({
providers: [
AttendanceService,
{ provide: getRepositoryToken(AttendanceRecord), useValue: mockRepo },
{ provide: getRepositoryToken(DingAttendanceRaw), useValue: mockDingRepo },
],
}).compile();
service = module.get<AttendanceService>(AttendanceService);
attendanceRepo = module.get(getRepositoryToken(AttendanceRecord));
});
it('valid batch with morning_reading, evening_study, and night_check sessions → succeeds', async () => {
const dto: BatchCreateAttendanceDto = {
records: [
{ studentId: 1, classId: 10, attendanceDate: '2026-07-05', session: 'morning_reading', status: 'present' },
{ studentId: 2, classId: 10, attendanceDate: '2026-07-05', session: 'evening_study', status: 'present' },
{ studentId: 3, classId: 10, attendanceDate: '2026-07-05', session: 'night_check', status: 'present' },
],
};
const result = await service.batchCreate(dto);
expect(result.count).toBe(3);
expect(result.records).toHaveLength(3);
expect(result.records[0].session).toBe('morning_reading');
expect(result.records[1].session).toBe('evening_study');
expect(result.records[2].session).toBe('night_check');
});
it('invalid session → validation error (DTO-level)', async () => {
const pipe = new ValidationPipe({ whitelist: true });
const invalidPayload = {
records: [
{ studentId: 1, attendanceDate: '2026-07-05', session: 'invalid_session', status: 'present' },
],
};
await expect(
pipe.transform(invalidPayload, {
type: 'body',
metatype: BatchCreateAttendanceDto,
}),
).rejects.toThrow();
});
it('empty batch → BadRequestException', async () => {
const dto: BatchCreateAttendanceDto = { records: [] };
await expect(service.batchCreate(dto)).rejects.toThrow(BadRequestException);
});
});