1
18import { test, expect } from "../fixtures";
19import { createPage, createBlock, getBlocks } from "../utils/api";
20import type { PageDto, BlockDto } from "../fixtures";
21
22test.describe("Templates variables — T-142 (RHF apply-with-values)", () => {
23 test("Use → variable form → required blocks submit; valid values substitute the tokens", async ({
24 authPage,
25 api,
26 freshWorkspace
27 }) => {
28 const ws = await freshWorkspace("Var Template Space");
29 const src = (await createPage(api, ws.id, { title: "Plan Draft" })) as PageDto;
30 await createBlock(api, src.id, {
31 type: "PARAGRAPH",
32 content: { text: "Project {{project}} is owned by {{owner}}." }
33 });
34
35
36 const tRes = await api.post(`/api/v1/pages/${src.id}/templates`, {
37 data: {
38 name: "Plan Template",
39 variables: [
40 { name: "project", label: "Project name", type: "text", required: true },
41 { name: "owner", label: "Owner", type: "text" }
42 ]
43 }
44 });
45 expect(tRes.status(), await tRes.text()).toBe(201);
46 const tpl = (await tRes.json()) as { id: string; variables: unknown };
47 expect(Array.isArray(tpl.variables)).toBe(true);
48
49 await authPage.goto(`/w/${ws.slug}/templates`);
50 const item = authPage.getByTestId(`template-item-${tpl.id}`);
51 await expect(item).toBeVisible({ timeout: 15_000 });
52
53
54 await item.getByTestId(`template-apply-${tpl.id}`).click();
55 const projectInput = authPage.getByLabel("Project name");
56 await expect(projectInput).toBeVisible();
57 await expect(authPage.getByLabel("Owner")).toBeVisible();
58 await expect(authPage.getByRole("button", { name: "Create page" })).toBeVisible();
59
60
61 await authPage.getByRole("button", { name: "Create page" }).click();
62 await expect(authPage.getByTestId("tpl-var-error-project")).toHaveText("Required");
63
64 await expect(authPage).toHaveURL(/\/templates$/);
65
66
67 await projectInput.fill("Apollo");
68 await authPage.getByLabel("Owner").fill("Ada");
69 await authPage.getByRole("button", { name: "Create page" }).click();
70 await authPage.waitForURL(/\/w\/[^/]+\/page\/[^/]+$/, { timeout: 20_000 });
71 const newId = new URL(authPage.url()).pathname.split("/").pop() ?? "";
72 expect(newId).toBeTruthy();
73 expect(newId).not.toBe(src.id);
74
75
76
77
78 const blocks = await getBlocks(api, newId);
79 const texts = blocks
80 .filter((b) => b.type === "PARAGRAPH")
81 .map((b) => (b.content as { text?: string })?.text ?? "");
82 expect(texts).toContain("Project Apollo is owned by Ada.");
83 expect(texts.join(" ")).not.toContain("{{");
84 });
85});
86