import { describe, test, expect, beforeAll, afterAll, mock } from "bun:test"; import { db } from "@/db"; import { annotators, quizSessions } from "@/db/schema"; import { eq } from "drizzle-orm"; const cookieJar = new Map(); const mockCookieStore = { get(name: string) { const value = cookieJar.get(name); return value ? { value } : undefined; }, set(name: string, value: string, _opts?: unknown) { cookieJar.set(name, value); }, delete(name: string) { cookieJar.delete(name); }, }; mock.module("next/headers", () => ({ cookies: async () => mockCookieStore, })); const { createSession } = await import("@/lib/auth"); const { GET, POST } = await import("../route"); const TEST_ANNOTATOR = { id: "test-warmup-user", displayName: "Test Warmup User", password: "testpass", }; const QUIZ_SESSION_ID = "test-warmup-quiz-session"; beforeAll(async () => { // Clean up any leftover data await db .delete(quizSessions) .where(eq(quizSessions.annotatorId, TEST_ANNOTATOR.id)); await db.delete(annotators).where(eq(annotators.id, TEST_ANNOTATOR.id)); // Create test annotator await db.insert(annotators).values(TEST_ANNOTATOR); // Create a passed quiz session await db.insert(quizSessions).values({ id: QUIZ_SESSION_ID, annotatorId: TEST_ANNOTATOR.id, totalQuestions: 8, score: 8, passed: true, completedAt: new Date(), answers: "[]", }); // Set up session cookie cookieJar.clear(); await createSession(TEST_ANNOTATOR.id); }); afterAll(async () => { await db .delete(quizSessions) .where(eq(quizSessions.annotatorId, TEST_ANNOTATOR.id)); await db.delete(annotators).where(eq(annotators.id, TEST_ANNOTATOR.id)); }); describe("GET /api/warmup", () => { test("returns first warmup paragraph", async () => { const res = await GET(); const data = await res.json(); expect(res.status).toBe(200); expect(data.done).toBe(false); expect(data.warmupCompleted).toBe(0); expect(data.paragraph).toBeDefined(); expect(data.paragraph.id).toBe("warmup-1"); expect(data.paragraph.text).toBeTruthy(); expect(data.paragraph.index).toBe(0); expect(data.paragraph.total).toBe(5); }); }); describe("POST /api/warmup", () => { test("returns gold answer and explanation for correct answer", async () => { const req = new Request("http://localhost:3000/api/warmup", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ category: "Board Governance", specificity: 3, warmupIndex: 0, }), }); const res = await POST(req); const data = await res.json(); expect(res.status).toBe(200); expect(data.categoryCorrect).toBe(true); expect(data.specificityCorrect).toBe(true); expect(data.goldCategory).toBe("Board Governance"); expect(data.goldSpecificity).toBe(3); expect(data.explanation).toBeTruthy(); expect(data.warmupCompleted).toBe(1); expect(data.done).toBe(false); }); test("returns feedback for incorrect answer", async () => { const req = new Request("http://localhost:3000/api/warmup", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ category: "Management Role", specificity: 1, warmupIndex: 1, }), }); const res = await POST(req); const data = await res.json(); expect(res.status).toBe(200); expect(data.categoryCorrect).toBe(false); expect(data.specificityCorrect).toBe(false); expect(data.goldCategory).toBe("Incident Disclosure"); expect(data.goldSpecificity).toBe(4); expect(data.warmupCompleted).toBe(2); }); test("rejects mismatched warmup index", async () => { const req = new Request("http://localhost:3000/api/warmup", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ category: "Risk Management Process", specificity: 1, warmupIndex: 0, // should be 2 at this point }), }); const res = await POST(req); expect(res.status).toBe(400); const data = await res.json(); expect(data.error).toBe("Warmup index mismatch"); }); test("completes remaining warmups and returns done", async () => { // Complete warmups 2, 3, 4 for (let i = 2; i < 5; i++) { const req = new Request("http://localhost:3000/api/warmup", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ category: "None/Other", specificity: 1, warmupIndex: i, }), }); const res = await POST(req); expect(res.status).toBe(200); } // GET should now return done const res = await GET(); const data = await res.json(); expect(data.done).toBe(true); expect(data.warmupCompleted).toBe(5); }); }); describe("GET /api/warmup - unauthorized", () => { test("returns 401 without session", async () => { cookieJar.clear(); const res = await GET(); expect(res.status).toBe(401); }); });