import { ForbiddenException } from '@nestjs/common'; import { ClassesService } from './classes.service'; describe('ClassesService — teacher data scope', () => { const classRepo = { find: jest.fn() }; const classStudentRepo = { createQueryBuilder: jest.fn() }; const classTeacherRepo = { find: jest.fn(), findOne: jest.fn() }; const service = new ClassesService( classRepo as never, classStudentRepo as never, classTeacherRepo as never, {} as never, {} as never, {} as never, {} as never, ); beforeEach(() => jest.clearAllMocks()); it('returns only class ids assigned to a teacher', async () => { classTeacherRepo.find.mockResolvedValue([{ classId: 3 }, { classId: 5 }, { classId: 3 }]); await expect(service.getAccessibleClassIds(21, false)).resolves.toEqual([3, 5]); }); it('rejects access to a class outside the teacher assignments', async () => { classTeacherRepo.findOne.mockResolvedValue(null); await expect(service.assertClassAccess(21, 9, false)).rejects.toBeInstanceOf( ForbiddenException, ); }); it('allows class managers to access any class', async () => { await expect(service.assertClassAccess(21, 9, true)).resolves.toBeUndefined(); expect(classTeacherRepo.findOne).not.toHaveBeenCalled(); }); }); it('clears denormalized teacher ids when the last teacher for that role is removed', async () => { const classRepo = { update: jest.fn() }; const classTeacherRepo = { find: jest .fn() .mockResolvedValueOnce([{ id: 1, classId: 8, userId: 21 }]) .mockResolvedValueOnce([]), delete: jest.fn().mockResolvedValue({ affected: 1 }), }; const service = new ClassesService( classRepo as never, {} as never, classTeacherRepo as never, {} as never, {} as never, {} as never, {} as never, ); await service.removeTeacher(8, 21); expect(classRepo.update).toHaveBeenCalledWith(8, { headTeacherId: null, lifeTeacherId: null, academicTeacherId: null, }); });