import type { FastifyInstance } from 'fastify'; import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest'; import { buildApp } from '../src/app.js'; import { login, makeConfig, makeTempDir, oneTarget, removeDir, SESSION_COOKIE, startStubIdp, type StubIdp, } from './helpers.js'; let idp: StubIdp; let app: FastifyInstance; let uploadDir: string; beforeAll(async () => { idp = await startStubIdp(); }); afterAll(async () => { await idp.close(); }); beforeEach(async () => { uploadDir = await makeTempDir(); app = await buildApp( makeConfig({ targets: oneTarget(uploadDir), oidc: { issuer: idp.issuer, clientId: idp.clientId, clientSecret: idp.clientSecret, scopes: ['openid', 'profile', 'email'], }, }), { logger: false }, ); await app.ready(); }); afterEach(async () => { await app.close(); await removeDir(uploadDir); }); describe('flux d’authentification', () => { it('GET /auth/login redirige vers l’issuer avec un défi PKCE et pose un cookie', async () => { const res = await app.inject({ method: 'GET', url: '/auth/login' }); expect(res.statusCode).toBe(302); const target = new URL(res.headers.location as string); expect(target.origin).toBe(idp.issuer); expect(target.searchParams.get('code_challenge')).toBeTruthy(); expect(target.searchParams.get('state')).toBeTruthy(); expect(res.cookies.some((c) => c.name === SESSION_COOKIE)).toBe(true); }); it('GET /auth/me est anonyme par défaut, authentifié après login', async () => { const anon = await app.inject({ method: 'GET', url: '/auth/me' }); expect(anon.json()).toEqual({ authenticated: false }); const cookie = await login(app, idp, { name: 'Alice' }); const me = await app.inject({ method: 'GET', url: '/auth/me', cookies: { [SESSION_COOKIE]: cookie }, }); expect(me.json()).toEqual({ authenticated: true, name: 'Alice' }); }); it('POST /auth/logout vide la session (soumission de