import { test, expect } from "@playwright/test"; test.describe("Smart Actions", () => { test.beforeEach(async ({ page }) => { // Mock all backend API calls await page.route("**/api/note-prompts**", (route) => { if (route.request().method() === "GET") { return route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ items: [ { id: "builtin-summarize", slug: "summarize", name: "Summarize", category: "transform", isBuiltin: true, inputType: "text", outputType: "new_note", }, { id: "custom-1", slug: "my-custom", name: "My Custom Template", category: "generate", isBuiltin: false, inputType: "text", outputType: "replace", }, ], total: 2, }), }); } if (route.request().method() === "POST") { return route.fulfill({ status: 201, contentType: "application/json", body: JSON.stringify({ id: "new-template-1", slug: "new-template", name: "New Template", category: "transform", isBuiltin: false, }), }); } if (route.request().method() === "DELETE") { return route.fulfill({ status: 204 }); } return route.fulfill({ status: 200, contentType: "application/json", body: "{}" }); }); await page.route("**/api/notes**", (route) => route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ items: [], total: 0 }), }) ); await page.route("**/api/workspaces**", (route) => route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ items: [], total: 0 }), }) ); await page.route("**/api/prompt-schedules**", (route) => route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ items: [], total: 0 }), }) ); await page.route("**/api/prompt-webhooks**", (route) => route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ items: [], total: 0 }), }) ); await page.route("**/api/**", (route) => route.fulfill({ status: 200, contentType: "application/json", body: "{}" }) ); }); test("dashboard page loads with smart actions API mocked", async ({ page }) => { await page.goto("/dashboard"); await page.waitForLoadState("domcontentloaded"); await expect(page.locator("body")).toBeVisible(); }); test("note detail page loads without JS errors", async ({ page }) => { const errors: string[] = []; page.on("pageerror", (err) => errors.push(err.message)); await page.goto("/notes/test-note-1"); await page.waitForLoadState("domcontentloaded"); await expect(page.locator("body")).toBeVisible(); const realErrors = errors.filter( (e) => !e.includes("fetch") && !e.includes("Failed") && !e.includes("Unexpected") && !e.includes("hydration") ); expect(realErrors).toHaveLength(0); }); test("settings page loads without JS errors", async ({ page }) => { const errors: string[] = []; page.on("pageerror", (err) => errors.push(err.message)); await page.goto("/settings"); await page.waitForLoadState("domcontentloaded"); await expect(page.locator("body")).toBeVisible(); const realErrors = errors.filter( (e) => !e.includes("fetch") && !e.includes("Failed") && !e.includes("Unexpected") && !e.includes("hydration") ); expect(realErrors).toHaveLength(0); }); test("prompts page loads with template list", async ({ page }) => { await page.goto("/prompts"); await page.waitForLoadState("domcontentloaded"); await expect(page.locator("body")).toBeVisible(); }); test("knowledge gaps page loads", async ({ page }) => { await page.route("**/api/workspaces/ws-1/knowledge-gaps", (route) => route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ gaps: [], topicMap: {} }), }) ); await page.goto("/workspaces/ws-1/gaps"); await page.waitForLoadState("domcontentloaded"); await expect(page.locator("body")).toBeVisible(); }); test("search page loads without JS errors", async ({ page }) => { const errors: string[] = []; page.on("pageerror", (err) => errors.push(err.message)); await page.goto("/search"); await page.waitForLoadState("domcontentloaded"); await expect(page.locator("body")).toBeVisible(); const realErrors = errors.filter( (e) => !e.includes("fetch") && !e.includes("Failed") && !e.includes("Unexpected") && !e.includes("hydration") ); expect(realErrors).toHaveLength(0); }); test("workspaces page loads", async ({ page }) => { await page.goto("/workspaces"); await page.waitForLoadState("domcontentloaded"); await expect(page.locator("body")).toBeVisible(); }); test("reviews page loads", async ({ page }) => { await page.goto("/reviews"); await page.waitForLoadState("domcontentloaded"); await expect(page.locator("body")).toBeVisible(); }); test("history API mock returns items", async ({ page }) => { // page.route() intercepts BROWSER network requests, while // page.request.get() uses Playwright's separate request context // which bypasses page.route() entirely. Drive the request from // within the page (fetch) so the mock applies. await page.route("**/api/note-prompts/history**", (route) => route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ items: [{ id: "h1", noteId: "n1", workspaceId: "ws1", toolName: "summarize", state: "applied", createdAt: "2026-01-01T00:00:00Z" }], total: 1, }), }) ); await page.goto("/dashboard"); const data = await page.evaluate(async () => { const res = await fetch("/api/note-prompts/history?workspaceId=ws1"); return { status: res.status, body: await res.json() } as { status: number; body: { items: unknown[]; total: number } }; }); expect(data.status).toBe(200); expect(data.body.items).toHaveLength(1); }); });