learning_ai_notes/web/e2e/reviews-visual.spec.ts

98 lines
3.1 KiB
TypeScript

import { expect, test, type Page, type Route } from "@playwright/test";
function accessToken() {
const payload = Buffer.from(JSON.stringify({ exp: 4102444800 })).toString("base64url");
return `test.${payload}.token`;
}
async function seedAuth(page: Page) {
await page.addInitScript((token) => {
localStorage.setItem("notelett_auth_user", JSON.stringify({ id: "user-1", email: "user@example.com", name: "Review Tester" }));
localStorage.setItem("notelett_access_token", token);
localStorage.setItem("notelett_refresh_token", "refresh-token");
}, accessToken());
}
function json(route: Route, body: unknown, status = 200) {
return route.fulfill({
status,
contentType: "application/json",
body: JSON.stringify(body),
});
}
function actionDoc(id: string, afterSummary: string, state: string) {
return {
id,
productId: "notelett",
workspaceId: "ws-1",
noteId: "note-1",
actorId: "agent-1",
actorType: "agent",
actionType: "update",
state,
afterSummary,
beforeSummary: "Before text",
updatedAt: "2026-05-05T00:00:00.000Z",
updatedBy: "agent-1",
};
}
async function mockReviewApis(page: Page) {
await page.route("**/api/auth/refresh", (route) =>
json(route, { accessToken: accessToken(), refreshToken: "refresh-token" }),
);
await page.route("**/api/kill-switch**", (route) =>
json(route, { disabled: false, message: null }),
);
await page.route("**/api/**", (route) => {
const url = new URL(route.request().url());
const path = url.pathname.replace(/^\/api/, "");
if (path === "/note-agent-actions/pending") {
return json(route, {
items: [
actionDoc("act-1", "Approve release summary", "proposed"),
actionDoc("act-2", "Reject stale task", "proposed"),
],
total: 2,
});
}
if (path === "/note-agent-actions") {
return json(route, {
items: [actionDoc("act-3", "Previous review", "approved")],
total: 1,
});
}
if (path === "/broadcasts/active" || path === "/surveys/active") {
return json(route, { items: [], total: 0 });
}
return json(route, {});
});
}
test.beforeEach(async ({ page }) => {
await seedAuth(page);
await mockReviewApis(page);
});
for (const viewport of [
{ name: "desktop", width: 1440, height: 1000 },
{ name: "mobile", width: 390, height: 900 },
]) {
test(`reviews visual smoke - ${viewport.name}`, async ({ page }) => {
await page.setViewportSize({ width: viewport.width, height: viewport.height });
await page.goto("/reviews");
await expect(page.getByRole("heading", { name: "Agent review" })).toBeVisible();
await expect(page.getByRole("heading", { name: "Approval queue" })).toBeVisible();
await expect(page.getByRole("button", { name: /Approve release summary/ })).toBeVisible();
const overflow = await page.evaluate(() => document.documentElement.scrollWidth > document.documentElement.clientWidth);
expect(overflow).toBe(false);
const screenshot = await page.screenshot({ fullPage: true });
expect(screenshot.byteLength).toBeGreaterThan(10_000);
});
}