/** * T-141 — template PREVIEW web E2E (read-only snapshot dialog). * * Verifies the WEB surface: every template row (including builtins) has a * "Preview" button; clicking it opens the read-only dialog fed by the NEW * `GET /templates/:id/preview` endpoint; the dialog renders the frozen * snapshot (page title + block text); Escape closes it. The endpoint's * authz (member 200 / non-member 404, no leak) is integration-covered in * `templates.integration.test.ts`. */ import { test, expect } from "../fixtures"; import { createPage, createBlock } from "../utils/api"; import type { PageDto } from "../fixtures"; test.describe("Templates preview — T-141 (read-only snapshot dialog)", () => { test("Preview shows the frozen snapshot (title + blocks); Escape closes", async ({ authPage, api, freshWorkspace }) => { const ws = await freshWorkspace("Preview Space"); const src = (await createPage(api, ws.id, { title: "Preview Source" })) as PageDto; await createBlock(api, src.id, { type: "PARAGRAPH", content: { text: "preview body text" } }); const tRes = await api.post(`/api/v1/pages/${src.id}/templates`, { data: { name: "Preview Tpl" } }); expect(tRes.status(), await tRes.text()).toBe(201); const tpl = (await tRes.json()) as { id: string }; await authPage.goto(`/w/${ws.slug}/templates`); const item = authPage.getByTestId(`template-item-${tpl.id}`); await expect(item).toBeVisible({ timeout: 15_000 }); // Every row (builtins included) offers Preview. await expect(authPage.getByTestId(`template-preview-${tpl.id}`)).toBeVisible(); // Open the preview. await item.getByTestId(`template-preview-${tpl.id}`).click(); const body = authPage.getByTestId("template-preview-body"); await expect(body).toBeVisible({ timeout: 15_000 }); // The frozen snapshot: page title + the block's text, read-only. await expect(authPage.getByTestId("template-preview-title")).toHaveText("Preview Source"); await expect(body.getByText("preview body text")).toBeVisible(); // No editable controls in the snapshot. await expect(body.locator("[contenteditable], input, textarea")).toHaveCount(0); // Escape closes the dialog. await authPage.keyboard.press("Escape"); await expect(body).toBeHidden({ timeout: 5_000 }); }); });