import { RbacService } from './rbac.service'; describe('RbacService.purgeUser', () => { const createService = (overrides?: { user?: Record; counts?: Record; }) => { const user = { id: 2, username: 'teacher1', isArchived: true, ...overrides?.user, }; const userRepo = { findOne: jest.fn().mockResolvedValue(user), delete: jest.fn().mockResolvedValue({ affected: 1 }), }; const counts = overrides?.counts ?? {}; const countFor = (key: string) => jest.fn().mockResolvedValue(counts[key] ?? 0); const service = new RbacService( {} as never, {} as never, userRepo as never, { count: countFor('headTeacher') } as never, {} as never, { count: countFor('classTeacher') } as never, { count: countFor('schedule') } as never, { count: countFor('student') } as never, { count: countFor('session') } as never, ); return { service, userRepo }; }; it('rejects the current user, the admin user, and non-archived users', async () => { const current = createService(); await expect(current.service.purgeUser(2, 2)).rejects.toThrow( '不能永久删除当前登录用户', ); const admin = createService({ user: { username: 'admin' } }); await expect(admin.service.purgeUser(2, 1)).rejects.toThrow('不能永久删除默认管理员'); const active = createService({ user: { isArchived: false } }); await expect(active.service.purgeUser(2, 1)).rejects.toThrow( '仅已归档用户可以永久删除,请先归档', ); }); it('rejects users with student, class, schedule, or attendance references', async () => { const { service, userRepo } = createService({ counts: { student: 1 } }); await expect(service.purgeUser(2, 1)).rejects.toThrow( '该用户存在关联数据(关联学生),无法永久删除', ); expect(userRepo.delete).not.toHaveBeenCalled(); }); it('deletes an archived user with no references', async () => { const { service, userRepo } = createService(); await expect(service.purgeUser(2, 1)).resolves.toEqual({ message: '用户已永久删除(不可恢复)', }); expect(userRepo.delete).toHaveBeenCalledWith(2); }); });