v1.1.0: session guard on all game routes + register + sign-in screen (ISS-107)
CI / build + unit + e2e (pull_request) Failing after 26m20s

This commit is contained in:
2026-09-26 14:40:56 +00:00
parent 21dd37f88c
commit b0f1bd8b67
54 changed files with 1002 additions and 91 deletions
+16 -1
View File
@@ -2,9 +2,12 @@ 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 { createSession } from '@/lib/auth';
import { getGameDb } from '@/lib/db/client';
import { GET } from './route';
let dir: string;
let sessionId: string;
beforeAll(async () => {
// Same pattern as app/api/state/route.test.ts: point the DB singleton at a throwaway file so
@@ -12,6 +15,8 @@ beforeAll(async () => {
// vitest gives each test file its own module registry (fresh singleton).
dir = await fs.mkdtemp(path.join(os.tmpdir(), 'flight-events-'));
process.env.FLIGHT_DB_PATH = path.join(dir, 'events.db');
// v1.1.0 (ISS-107): /api/events is session-guarded — mint a session for the seeded admin user.
sessionId = await createSession(await getGameDb(), 'admin-kamilkrzywda');
});
afterAll(async () => {
@@ -20,8 +25,18 @@ afterAll(async () => {
});
describe('GET /api/events', () => {
// v1.1.0 (ISS-107): EventSource cannot set headers, so the client passes the session as a query
// param — this test exercises exactly that path (requireAuthSse).
const req = () => new Request(`http://localhost/api/events?session=${sessionId}`);
it('rejects an unauthenticated request with 401', async () => {
const res = await GET(new Request('http://localhost/api/events'));
expect(res.status).toBe(401);
expect(((await res.json()) as { error: string }).error).toMatch(/authentication required/i);
});
it('streams SSE with the current snapshot as the first event', async () => {
const res = await GET();
const res = await GET(req());
expect(res.status).toBe(200);
expect(res.headers.get('content-type')).toContain('text/event-stream');
expect(res.headers.get('cache-control')).toBe('no-cache');