import { AuthenticationService } from '../src/modules/auth/authentication.service'; describe('AuthenticationService', () => { let service: AuthenticationService; const mockOidc: any = { verifyToken: jest.fn() }; const mockPrisma: any = {}; const mockRoleSync: any = { syncUserRolesFromAuthentik: jest.fn() }; const mockAuthz: any = { getUserPermissions: jest.fn() }; const mockEvents: any = { publish: jest.fn() }; beforeEach(() => { mockPrisma.user = { findUnique: jest.fn(), create: jest.fn() }; mockPrisma.userRole = { findMany: jest.fn() }; service = new AuthenticationService(mockOidc as any, mockPrisma as any, mockRoleSync as any, mockAuthz as any, mockEvents as any); }); test('authenticate creates context on valid token', async () => { const token = 'valid'; mockOidc.verifyToken.mockResolvedValue({ sub: 'sub1', email: 'u@example.com', groups: ['RL-Owner'] }); mockPrisma.user.findUnique.mockResolvedValue(null); mockPrisma.user.create.mockResolvedValue({ id: 'uid', authentikId: 'sub1', email: 'u@example.com' }); mockRoleSync.syncUserRolesFromAuthentik.mockResolvedValue({ skipped: false, assignedRoleIds: ['r1'] }); mockAuthz.getUserPermissions.mockResolvedValue(['users.read']); mockPrisma.userRole.findMany.mockResolvedValue([{ roleId: 'r1' }]); const ctx = await service.authenticate(token); expect(ctx.user.id).toBe('uid'); expect(ctx.permissions).toContain('users.read'); expect(mockEvents.publish).toHaveBeenCalledWith('user.authenticated', expect.any(Object)); }); test('authenticate throws for missing sub', async () => { mockOidc.verifyToken.mockResolvedValue({ email: 'u@example.com' }); await expect(service.authenticate('bad')).rejects.toThrow('Invalid token: missing sub'); }); });