import { test, expect, type Page } from "@playwright/test"; import { resolveUrl, getSessionCookie, testUser } from "./helpers"; /** * E2E tests for authentication flows. * Covers: sign-in, sign-out, protected routes, and session persistence. */ test.describe("Auth", () => { // ─── Helpers ─────────────────────────────────────────────────────────────── async function signInViaUI(page: Page, email = testUser.email, password = testUser.password) { await page.goto(resolveUrl("/")); await page.getByRole("link", { name: /sign in/i }).click(); await page.getByPlaceholder("you@example.com").fill(email); await page.getByPlaceholder("your password").fill(password); await page.getByRole("button", { name: /sign in/i }).click(); await page.waitForURL("**/"); } // ─── Tests ──────────────────────────────────────────────────────────────── test("1. Homepage loads without auth", async ({ page }) => { const res = await page.request.get(resolveUrl("/")); expect(res.status()).toBeGreaterThanOrEqual(200); expect(res.status()).toBeLessThan(400); }); test("2. Sign in via API returns session cookie", async ({ page }) => { const res = await page.request.post(resolveUrl("/api/auth/sign-in/email"), { data: { email: testUser.email, password: testUser.password }, headers: { "Content-Type": "application/json" }, }); expect(res.status()).toBe(200); const setCookie = res.headers()["set-cookie"] ?? ""; expect(setCookie).toContain("session_token="); }); test("3. Sign in with wrong credentials returns 401", async ({ page }) => { const res = await page.request.post(resolveUrl("/api/auth/sign-in/email"), { data: { email: "bad@example.com", password: "wrongpass" }, headers: { "Content-Type": "application/json" }, }); expect(res.status()).toBe(401); }); test("4. Protected API route requires auth", async ({ page }) => { const res = await page.request.post(resolveUrl("/api/compare"), { data: { items: ["A", "B"] }, headers: { "Content-Type": "application/json" }, }); expect(res.status()).toBe(401); const body = await res.json(); expect(body.error).toMatch(/auth/i); }); test("5. Authenticated session persists across requests", async ({ page }) => { const cookie = await getSessionCookie(page); // Should be able to hit protected endpoints with the cookie const res = await page.request.get(resolveUrl("/api/user/stats"), { headers: { Cookie: cookie }, }); expect(res.status()).toBe(200); }); test("6. UI sign-in flow works", async ({ page }) => { await signInViaUI(page); // After sign-in, user should see their name or a dashboard link const bodyText = await page.content(); expect(bodyText.toLowerCase()).not.toContain("sign in"); }); });