1
19import { test, expect } from "../fixtures";
20import { createPage, createBlock, getBlocks } from "../utils/api";
21import type { PageDto, BlockDto } from "../fixtures";
22
23test.describe("Confluence P1 — page duplicate + related (T-138/T-140)", () => {
24 test("topbar More → Duplicate deep-copies the page and its blocks", async ({
25 authPage,
26 api,
27 freshWorkspace
28 }) => {
29 const ws = await freshWorkspace("Duplicate Space");
30 const src = (await createPage(api, ws.id, { title: "Dup Source" })) as PageDto;
31 const blocks = [
32 await createBlock(api, src.id, { type: "PARAGRAPH", content: { text: "dup-block-A" } }),
33 await createBlock(api, src.id, { type: "PARAGRAPH", content: { text: "dup-block-B" } })
34 ];
35
36 const srcPath = `/w/${ws.slug}/page/${src.id}`;
37 await authPage.goto(srcPath);
38 await authPage.getByRole("button", { name: "More actions" }).click();
39 await authPage.getByRole("menuitem", { name: "Duplicate" }).click();
40
41
42 await authPage.waitForURL(
43 (u) => u.pathname !== srcPath,
44 { timeout: 15_000 },
45 );
46 const copyId = new URL(authPage.url()).pathname.split("/").pop() ?? "";
47 expect(copyId, "the copy has its own page id").not.toBe(src.id);
48
49
50
51 const copyRes = await (await api.get(`/api/v1/pages/${copyId}`)).json() as {
52 page?: PageDto;
53 } & PageDto;
54 const copyPage = copyRes.page ?? copyRes;
55 expect(copyPage.title).toBe("Dup Source (copy)");
56
57
58 const copyBlocks = await getBlocks(api, copyId);
59 const texts = copyBlocks
60 .filter((b) => b.type === "PARAGRAPH")
61 .map((b) => (b.content as { text?: string })?.text ?? "");
62 expect(texts).toEqual(
63 expect.arrayContaining(["dup-block-A", "dup-block-B"]),
64 );
65 });
66
67 test("Related panel lists a referencing page (CHILD_PAGE) and shows an empty state otherwise", async ({
68 authPage,
69 api,
70 freshWorkspace
71 }) => {
72 const ws = await freshWorkspace("Related Space");
73 const referenced = (await createPage(api, ws.id, { title: "Related Target" })) as PageDto;
74 const referrer = (await createPage(api, ws.id, { title: "Related Source" })) as PageDto;
75
76
77
78 await createBlock(api, referrer.id, {
79 type: "CHILD_PAGE",
80 content: { pageId: referenced.id }
81 });
82
83 await authPage.goto(`/w/${ws.slug}/page/${referenced.id}`);
84 await authPage.getByTestId("related-button").click();
85 const panel = authPage.getByTestId("related-panel");
86 await expect(panel).toBeVisible();
87
88 const row = panel.getByTestId(`related-item-${referrer.id}`);
89 await expect(row).toHaveText("Related Source");
90 await expect(row).toHaveAttribute(
91 "href",
92 new RegExp(`/w/${ws.slug}/page/${referrer.id}$`)
93 );
94
95
96 await panel.getByRole("button", { name: "Close related pages" }).click();
97 await expect(panel).toBeHidden();
98
99
100 await authPage.goto(`/w/${ws.slug}/page/${referrer.id}`);
101 await authPage.getByTestId("related-button").click();
102 const emptyPanel = authPage.getByTestId("related-panel");
103 await expect(emptyPanel).toBeVisible();
104 await expect(emptyPanel.getByText("No related pages yet")).toBeVisible();
105 });
106});
107