import { CurrentUserGuard } from '../../src/modules/identity/presentation/guards/current-user.guard'; import { SyncIdentityHandler } from '../../src/modules/identity/application/handlers/user/sync-identity.handler'; import { IUser } from '../../src/modules/identity/domain/repositories/user.interface'; import { IdentityData } from '../../src/core/auth/interfaces/identity-data'; import { UnauthorizedException } from '@nestjs/common'; describe('CurrentUserGuard', () => { let guard: CurrentUserGuard; let mockSync: Partial; let mockUserRepo: Partial; beforeEach(() => { mockSync = { execute: jest.fn() }; mockUserRepo = { getById: jest.fn() }; guard = new CurrentUserGuard(mockSync as any, mockUserRepo as any); }); function makeContext(req: any): any { return { switchToHttp: () => ({ getRequest: () => req }) } as any; } test('raylabContext fast path sets currentUser and returns true', async () => { const user = { id: 'u1' } as any; const req: any = { raylabContext: { user } }; const res = await guard.canActivate(makeContext(req)); expect(res).toBe(true); expect(req.currentUser).toBe(user); }); test('missing identity throws UnauthorizedException', async () => { const req: any = {}; await expect(guard.canActivate(makeContext(req))).rejects.toThrow(UnauthorizedException); }); test('internal identity resolves by getById and does not call sync', async () => { const identity = new IdentityData('uid', 'u', 'e'); const req: any = { identity, identitySource: 'internal' }; (mockUserRepo.getById as jest.Mock).mockResolvedValue({ id: 'uid', roles: [], permissions: [] }); const res = await guard.canActivate(makeContext(req)); expect(res).toBe(true); expect(req.currentUser).toBeDefined(); expect((mockSync.execute as jest.Mock)).not.toHaveBeenCalled(); }); test('internal identity with missing user throws UnauthorizedException', async () => { const identity = new IdentityData('missing', 'u', 'e'); const req: any = { identity, identitySource: 'internal' }; (mockUserRepo.getById as jest.Mock).mockRejectedValue(new Error('User tidak ditemukan.')); await expect(guard.canActivate(makeContext(req))).rejects.toThrow(UnauthorizedException); expect((mockSync.execute as jest.Mock)).not.toHaveBeenCalled(); }); test('external identity calls syncIdentityHandler', async () => { const identity = new IdentityData('extsub', 'u', 'e'); const req: any = { identity, identitySource: 'external' }; (mockSync.execute as jest.Mock).mockResolvedValue({ id: 'user-ext' }); const res = await guard.canActivate(makeContext(req)); expect(res).toBe(true); expect(req.currentUser).toBeDefined(); expect((mockUserRepo.getById as jest.Mock)).not.toHaveBeenCalled(); }); });