import type { FastifyInstance } from 'fastify'; import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest'; import { buildApp } from '../src/app.js'; import type { OidcConfig } from '../src/config.js'; import { login, makeConfig, makeTempDir, oneTarget, removeDir, SESSION_COOKIE, startStubIdp, type StubIdp, } from './helpers.js'; let idp: StubIdp; let app: FastifyInstance; let uploadDir: string; function oidcOverride(ref: StubIdp): OidcConfig { return { issuer: ref.issuer, clientId: ref.clientId, clientSecret: ref.clientSecret, scopes: ['openid', 'profile', 'email'], }; } beforeAll(async () => { idp = await startStubIdp(); }); afterAll(async () => { await idp.close(); }); beforeEach(async () => { uploadDir = await makeTempDir(); app = await buildApp(makeConfig({ targets: oneTarget(uploadDir), oidc: oidcOverride(idp) }), { logger: false, }); await app.ready(); }); afterEach(async () => { await app.close(); await removeDir(uploadDir); }); describe('GET /', () => { it('sans session : sert la page de connexion, pas la page de dépôt', async () => { const res = await app.inject({ method: 'GET', url: '/' }); expect(res.statusCode).toBe(200); expect(res.headers['content-type']).toContain('text/html'); expect(res.body).toContain('href="/auth/login"'); expect(res.body).not.toContain('id="zones"'); expect(res.body).not.toContain('Se déconnecter'); }); it('avec session valide : sert la page de dépôt avec le nom injecté', async () => { const cookie = await login(app, idp, { name: 'Alice' }); const res = await app.inject({ method: 'GET', url: '/', cookies: { [SESSION_COOKIE]: cookie }, }); expect(res.statusCode).toBe(200); expect(res.body).toContain('Connecté : Alice'); expect(res.body).toContain('Se déconnecter'); expect(res.body).toContain('id="zones"'); expect(res.body).not.toContain('{{USER_NAME}}'); expect(res.body).not.toContain('href="/auth/login"'); }); it('page de dépôt : boutons pause/réessayer, titres tronquables, pleine largeur', async () => { const cookie = await login(app, idp); const res = await app.inject({ method: 'GET', url: '/', cookies: { [SESSION_COOKIE]: cookie }, }); expect(res.body).toContain('class="pause"'); expect(res.body).toContain('class="retry"'); expect(res.body).toContain('text-overflow: ellipsis'); expect(res.body).not.toContain('max-width: 640px'); }); it('page de dépôt : une zone par cible, plus de menu déroulant ni de second sélecteur', async () => { const cookie = await login(app, idp); const res = await app.inject({ method: 'GET', url: '/', cookies: { [SESSION_COOKIE]: cookie }, }); expect(res.body).toContain('id="zones"'); expect(res.body).toContain('id="queuePause"'); expect(res.body).not.toContain('targetSelect'); expect(res.body).not.toContain('dirPicker'); }); it('échappe le nom d’utilisateur avant de l’insérer dans le HTML', async () => { const cookie = await login(app, idp, { name: '' }); const res = await app.inject({ method: 'GET', url: '/', cookies: { [SESSION_COOKIE]: cookie }, }); expect(res.body).not.toContain(''); expect(res.body).toContain('<script>alert(1)</script>'); }); it('session invalide (cookie illisible) : retombe sur la page de connexion', async () => { const res = await app.inject({ method: 'GET', url: '/', cookies: { [SESSION_COOKIE]: 'cookie-bidon' }, }); expect(res.statusCode).toBe(200); expect(res.body).toContain('href="/auth/login"'); expect(res.body).not.toContain('id="zones"'); }); });