1
30import { test, expect } from "../fixtures";
31import { createPage, createBlock } from "../utils/api";
32import type { PageDto } from "../fixtures";
33
34interface TaskDto {
35 id: string;
36 pageId: string;
37 title: string;
38 status: string;
39 pageTitle?: string;
40}
41
42test.describe("Tasks inbox — P3 (T-164)", () => {
43 test("assigned task appears in the inbox and advances status inline", async ({
44 authPage,
45 api,
46 freshWorkspace
47 }) => {
48 const ws = await freshWorkspace("Tasks Inbox Space");
49 const me = (await (await api.get("/api/v1/users/me")).json()) as { user: { id: string } };
50
51
52
53 const unassigned = (await (
54 await api.post(`/api/v1/workspaces/${ws.id}/tasks`, { data: { title: "Unassigned probe" } })
55 ).json()) as TaskDto;
56
57 const TASK_TITLE = "E2E inbox task";
58 const task = (await (
59 await api.post(`/api/v1/workspaces/${ws.id}/tasks`, {
60 data: { title: TASK_TITLE, assigneeIds: [me.user.id] }
61 })
62 ).json()) as TaskDto;
63 expect(task.status).toBe("todo");
64
65 await authPage.goto(`/w/${ws.slug}/inbox`);
66 await expect(authPage.getByRole("heading", { name: "Inbox" })).toBeVisible();
67
68
69 const main = authPage.locator("#workspace-main");
70
71
72
73 const row = main.getByRole("link", { name: TASK_TITLE });
74 await expect(row).toBeVisible({ timeout: 15_000 });
75 await expect(main.getByRole("link", { name: "Unassigned probe" })).toHaveCount(0);
76
77
78 await authPage.getByRole("button", { name: `Mark ${TASK_TITLE} as in_progress` }).click();
79 await expect(authPage.getByRole("button", { name: `Mark ${TASK_TITLE} as done` })).toBeVisible({
80 timeout: 10_000
81 });
82
83
84
85 await authPage.getByRole("button", { name: `Mark ${TASK_TITLE} as done` }).click();
86 await expect(authPage.getByRole("button", { name: `Mark ${TASK_TITLE} as` })).toHaveCount(0, {
87 timeout: 10_000
88 });
89 await authPage.getByRole("button", { name: "Done" }).click();
90 await expect(main.getByRole("link", { name: TASK_TITLE })).toBeVisible({ timeout: 15_000 });
91 });
92});
93
94test.describe("Page review workflow — P3 (T-162/T-163)", () => {
95 test("request review → in review → approve (single reviewer)", async ({
96 authPage,
97 api,
98 freshWorkspace
99 }) => {
100 const ws = await freshWorkspace("Reviews Space");
101 const me = (await (await api.get("/api/v1/users/me")).json()) as { user: { id: string; name: string } };
102 const page = (await createPage(api, ws.id, { title: "Review me" })) as PageDto;
103 await createBlock(api, page.id, { type: "PARAGRAPH", content: { text: "Body for review" } });
104
105 await authPage.goto(`/w/${ws.slug}/page/${page.id}`);
106
107
108 const banner = authPage.getByTestId("review-banner");
109 await expect(banner).toBeVisible({ timeout: 20_000 });
110 await banner.getByRole("button", { name: /request review/i }).click();
111
112
113
114 const reviewerCheckbox = banner.getByLabel(me.user.name);
115 await expect(reviewerCheckbox).toBeVisible();
116 await reviewerCheckbox.check();
117 await banner.getByRole("button", { name: /submit/i }).click();
118
119
120 await expect(authPage.getByText("In review")).toBeVisible({ timeout: 10_000 });
121 await authPage.getByRole("button", { name: /approve/i }).click();
122
123
124 await expect(authPage.getByText("Last review: approved")).toBeVisible({ timeout: 10_000 });
125
126
127 const state = (await (
128 await api.get(`/api/v1/pages/${page.id}/review`)
129 ).json()) as { state: string; lastReview: { decision: string | null } | null };
130 expect(state.state).toBe("published");
131 expect(state.lastReview?.decision).toBe("approved");
132 });
133});
134