import { describe, it, expect, vi, beforeEach } from 'vitest'; import Fastify from 'fastify'; import { fastifyAwilixPlugin } from '@fastify/awilix'; import { serializerCompiler, validatorCompiler } from 'fastify-type-provider-zod'; // Mock jose for auth plugin vi.mock('jose', () => ({ createRemoteJWKSet: vi.fn(() => 'mock-jwks'), jwtVerify: vi.fn().mockResolvedValue({ payload: { sub: 'kc-1', email: 'test@example.com', preferred_username: 'testuser', realm_access: { roles: ['member'] }, householdIds: ['hh1'], }, protectedHeader: { alg: 'RS256' }, key: {}, }), })); // Mock the users repository module with a real class const mockUpsertFromToken = vi.hoisted(() => vi.fn()); vi.mock('./users.repository.js', () => ({ UsersRepository: class MockUsersRepository { upsertFromToken = mockUpsertFromToken; }, })); import authPlugin from '../../plugins/auth.plugin.js'; import usersRoutes from './users.routes.js'; describe('users.routes', () => { async function buildTestApp() { const app = Fastify({ logger: false }); app.setValidatorCompiler(validatorCompiler); app.setSerializerCompiler(serializerCompiler); await app.register(fastifyAwilixPlugin, { disposeOnClose: true, disposeOnResponse: true, strictBooleanEnforced: true, }); await app.register(authPlugin); await app.register(usersRoutes); return app; } beforeEach(() => { vi.clearAllMocks(); }); it('GET /api/v1/users/me syncs user from token and returns profile', async () => { const mockUser = { _id: 'u1', keycloakId: 'kc-1', displayName: 'testuser', email: 'test@example.com', householdIds: ['hh1'], defaultHouseholdId: null, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; mockUpsertFromToken.mockResolvedValue(mockUser); const app = await buildTestApp(); await app.ready(); const res = await app.inject({ method: 'GET', url: '/api/v1/users/me', headers: { authorization: 'Bearer valid-token' }, }); expect(res.statusCode).toBe(200); const body = res.json(); expect(body.keycloakId).toBe('kc-1'); expect(body.email).toBe('test@example.com'); expect(mockUpsertFromToken).toHaveBeenCalledWith('kc-1', 'test@example.com', 'testuser'); await app.close(); }); });