fix permissions and teacher attendance workflows
This commit is contained in:
128
apps/server/src/attendance/attendance-import.service.spec.ts
Normal file
128
apps/server/src/attendance/attendance-import.service.spec.ts
Normal file
@@ -0,0 +1,128 @@
|
||||
import { BadRequestException } from '@nestjs/common';
|
||||
import { AttendanceImportService } from './attendance-import.service';
|
||||
import { DingTalkService } from '../integration/dingtalk.service';
|
||||
import { AttendanceService } from './attendance.service';
|
||||
|
||||
describe('AttendanceImportService', () => {
|
||||
const dingRawRepo = {
|
||||
find: jest.fn(),
|
||||
findOne: jest.fn(),
|
||||
save: jest.fn(),
|
||||
};
|
||||
const studentRepo = { findOne: jest.fn() };
|
||||
const studentDingMappingRepo = { findOne: jest.fn() };
|
||||
const dingTalkService = {
|
||||
fetchAttendanceResults: jest.fn(),
|
||||
};
|
||||
const attendanceService = {
|
||||
autoMatchDingRecords: jest.fn(),
|
||||
};
|
||||
|
||||
let service: AttendanceImportService;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
service = new AttendanceImportService(
|
||||
dingRawRepo as never,
|
||||
studentRepo as never,
|
||||
studentDingMappingRepo as never,
|
||||
dingTalkService as unknown as DingTalkService,
|
||||
attendanceService as unknown as AttendanceService,
|
||||
);
|
||||
});
|
||||
|
||||
it('splits DingTalk requests by at most 50 users and 7 calendar days without offset pagination', async () => {
|
||||
const userIds = Array.from({ length: 51 }, (_, index) => `user-${index + 1}`);
|
||||
dingTalkService.fetchAttendanceResults.mockResolvedValue([]);
|
||||
|
||||
await (service as any).fetchAllPages({
|
||||
startDate: '2026-07-01',
|
||||
endDate: '2026-07-10',
|
||||
userIds,
|
||||
});
|
||||
|
||||
expect(dingTalkService.fetchAttendanceResults).toHaveBeenCalledTimes(4);
|
||||
expect(dingTalkService.fetchAttendanceResults.mock.calls.map(([params]) => params)).toEqual([
|
||||
{
|
||||
startDate: '2026-07-01',
|
||||
endDate: '2026-07-07',
|
||||
userIds: userIds.slice(0, 50),
|
||||
},
|
||||
{
|
||||
startDate: '2026-07-01',
|
||||
endDate: '2026-07-07',
|
||||
userIds: userIds.slice(50),
|
||||
},
|
||||
{
|
||||
startDate: '2026-07-08',
|
||||
endDate: '2026-07-10',
|
||||
userIds: userIds.slice(0, 50),
|
||||
},
|
||||
{
|
||||
startDate: '2026-07-08',
|
||||
endDate: '2026-07-10',
|
||||
userIds: userIds.slice(50),
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('rejects an attendance import without DingTalk user IDs', async () => {
|
||||
await expect(
|
||||
(service as any).fetchAllPages({
|
||||
startDate: '2026-07-01',
|
||||
endDate: '2026-07-01',
|
||||
userIds: [],
|
||||
}),
|
||||
).rejects.toBeInstanceOf(BadRequestException);
|
||||
|
||||
expect(dingTalkService.fetchAttendanceResults).not.toHaveBeenCalled();
|
||||
});
|
||||
it('stores the DingTalk user name returned with the attendance record', async () => {
|
||||
const entity = await (service as any).mapToEntity({
|
||||
userId: 'ding-1',
|
||||
userName: '张三',
|
||||
workDate: '2026-07-01',
|
||||
timeResult: 'Normal',
|
||||
locationResult: '',
|
||||
planCheckTime: '',
|
||||
actualCheckTime: '2026-07-01T08:00:00.000Z',
|
||||
checkId: 'check-1',
|
||||
checkType: 'OnDuty',
|
||||
});
|
||||
|
||||
expect(entity.userName).toBe('张三');
|
||||
});
|
||||
|
||||
it('fills the student name from the DingTalk mapping when saving an imported record', async () => {
|
||||
dingTalkService.fetchAttendanceResults.mockResolvedValue([
|
||||
{
|
||||
userId: 'ding-1',
|
||||
userName: '',
|
||||
workDate: '2026-07-01',
|
||||
timeResult: 'Normal',
|
||||
locationResult: '',
|
||||
planCheckTime: '',
|
||||
actualCheckTime: '2026-07-01T08:00:00.000Z',
|
||||
checkId: 'check-1',
|
||||
checkType: 'OnDuty',
|
||||
},
|
||||
]);
|
||||
dingRawRepo.find.mockResolvedValue([]);
|
||||
studentDingMappingRepo.findOne.mockResolvedValue({ studentId: 3 });
|
||||
studentRepo.findOne.mockResolvedValue({ id: 3, name: '张三' });
|
||||
dingRawRepo.save.mockImplementation(async (entities) => entities);
|
||||
|
||||
await service.importFromDingTalk({
|
||||
startDate: '2026-07-01',
|
||||
endDate: '2026-07-01',
|
||||
userIds: ['ding-1'],
|
||||
autoMatch: false,
|
||||
});
|
||||
|
||||
expect(dingRawRepo.save).toHaveBeenCalledWith(
|
||||
[expect.objectContaining({ userName: '张三' })],
|
||||
{ chunk: 50 },
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user