200 lines
6.1 KiB
TypeScript
200 lines
6.1 KiB
TypeScript
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 }) => {
|
|
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,
|
|
}),
|
|
})
|
|
);
|
|
const response = await page.request.get("/api/note-prompts/history?workspaceId=ws1");
|
|
expect(response.status()).toBe(200);
|
|
const data = await response.json();
|
|
expect(data.items).toHaveLength(1);
|
|
});
|
|
});
|