import fs from 'node:fs/promises'; import os from 'node:os'; import path from 'node:path'; import { afterAll, beforeAll, describe, expect, it } from 'vitest'; import { getGameDb } from '@/lib/db/client'; import { createSession } from '@/lib/auth'; import { POST } from './route'; // v0.71.0 — logout route tests: deletes the session named by X-Flight-Session, idempotently. let dir: string; beforeAll(async () => { dir = await fs.mkdtemp(path.join(os.tmpdir(), 'flight-logout-api-')); process.env.FLIGHT_DB_PATH = path.join(dir, 'logout.db'); }); afterAll(async () => { delete process.env.FLIGHT_DB_PATH; await fs.rm(dir, { recursive: true, force: true }); }); const post = (sessionId?: string) => POST( new Request('http://localhost/api/logout', { method: 'POST', headers: sessionId ? { 'X-Flight-Session': sessionId } : undefined, }), ); async function mintSession(): Promise { const inst = await getGameDb(); return createSession(inst, 'admin-kamilkrzywda'); // any user id works — logout only deletes the session row } describe('POST /api/logout', () => { it('returns 401 without a session header', async () => { const res = await post(); expect(res.status).toBe(401); }); it('deletes the named session and is idempotent on repeat calls', async () => { const sessionId = await mintSession(); const count = (await getGameDb()).raw.exec('SELECT COUNT(*) FROM sessions WHERE id = ?', [sessionId])[0].values[0][0]; expect(Number(count)).toBe(1); const first = await post(sessionId); expect(first.status).toBe(200); expect(await first.json()).toEqual({ ok: true }); // The row is gone… const after = (await getGameDb()).raw.exec('SELECT COUNT(*) FROM sessions WHERE id = ?', [sessionId])[0].values[0][0]; expect(Number(after)).toBe(0); // …and a second logout of the same (now unknown) session is still 200. const second = await post(sessionId); expect(second.status).toBe(200); expect(await second.json()).toEqual({ ok: true }); }); });