Files
kandev/apps/web/e2e/tests/task/mobile-task-dependency-navigation.spec.ts
T
2026-09-21 18:22:29 +01:00

123 lines
4.7 KiB
TypeScript

// Filename starts with "mobile-" so this runs on the mobile-chrome project.
import { expect, test } from "../../fixtures/test-base";
import {
assertLocatorWithinViewportX,
assertNoDocumentHorizontalOverflow,
} from "../../helpers/layout-assertions";
test("mobile dependency links preserve the task workbench and touch layout", async ({
testPage,
apiClient,
seedData,
}) => {
const predecessor = await apiClient.createTask(
seedData.workspaceId,
"Mobile navigation predecessor",
{
workflow_id: seedData.workflowId,
workflow_step_id: seedData.startStepId,
repository_ids: [seedData.repositoryId],
},
);
const target = await apiClient.createTask(seedData.workspaceId, "Mobile navigation target", {
workflow_id: seedData.workflowId,
workflow_step_id: seedData.startStepId,
repository_ids: [seedData.repositoryId],
blocked_by: [predecessor.id],
});
const dependent = await apiClient.createTask(
seedData.workspaceId,
"Mobile navigation dependent",
{
workflow_id: seedData.workflowId,
workflow_step_id: seedData.startStepId,
repository_ids: [seedData.repositoryId],
blocked_by: [target.id],
},
);
await testPage.goto(`/t/${target.id}`);
const taskTitle = testPage.getByTestId("mobile-task-picker-trigger");
await expect(taskTitle).toContainText(target.title);
const documentRequests: string[] = [];
const onRequest = (request: import("@playwright/test").Request) => {
if (
request.isNavigationRequest() &&
request.frame() === testPage.mainFrame() &&
request.resourceType() === "document"
) {
documentRequests.push(request.url());
}
};
testPage.on("request", onRequest);
try {
await testPage.evaluate(() => {
(window as Window & { __taskLinkDocumentSentinel?: string }).__taskLinkDocumentSentinel =
"mobile-dependency-links-stay-in-spa";
});
const chip = testPage.getByTestId("task-dependency-chip");
await chip.tap();
const drawer = testPage.getByTestId("task-dependency-chip-drawer");
await expect(drawer).toBeVisible();
await expect(drawer.locator("[class*='overflow-y-auto']")).toHaveCount(1);
await assertLocatorWithinViewportX(drawer, "dependency drawer");
await assertNoDocumentHorizontalOverflow(testPage, "dependency drawer");
const entries = drawer.getByTestId("task-dependency-entry");
await expect(entries).toHaveCount(2);
for (const entry of await entries.all()) {
const box = await entry.boundingBox();
expect(box, "dependency entry must have geometry").not.toBeNull();
expect(box?.height ?? 0, "dependency entry touch target").toBeGreaterThanOrEqual(44);
await assertLocatorWithinViewportX(entry, "dependency entry");
}
const blockedBy = entries.filter({ hasText: predecessor.title });
await expect(blockedBy).toHaveAttribute("href", `/t/${predecessor.id}`);
await blockedBy.tap();
await expect(testPage).toHaveURL(new RegExp(`/t/${predecessor.id}$`));
await expect(testPage.getByTestId("mobile-task-picker-trigger")).toContainText(
predecessor.title,
);
await expect(testPage.getByTestId("task-dependency-chip-drawer")).toHaveCount(0);
expect(documentRequests).toHaveLength(0);
expect(
await testPage.evaluate(
() =>
(window as Window & { __taskLinkDocumentSentinel?: string }).__taskLinkDocumentSentinel,
),
).toBe("mobile-dependency-links-stay-in-spa");
await testPage.goBack();
await expect(testPage).toHaveURL(new RegExp(`/t/${target.id}$`));
await expect(testPage.getByTestId("mobile-task-picker-trigger")).toContainText(target.title);
expect(documentRequests).toHaveLength(0);
await chip.tap();
const reopenedDrawer = testPage.getByTestId("task-dependency-chip-drawer");
await expect(reopenedDrawer).toBeVisible();
const blocks = reopenedDrawer
.getByTestId("task-dependency-entry")
.filter({ hasText: dependent.title });
await expect(blocks).toHaveAttribute("href", `/t/${dependent.id}`);
await blocks.tap();
await expect(testPage).toHaveURL(new RegExp(`/t/${dependent.id}$`));
await expect(testPage.getByTestId("mobile-task-picker-trigger")).toContainText(dependent.title);
await expect(testPage.getByTestId("task-dependency-chip-drawer")).toHaveCount(0);
expect(documentRequests).toHaveLength(0);
expect(
await testPage.evaluate(
() =>
(window as Window & { __taskLinkDocumentSentinel?: string }).__taskLinkDocumentSentinel,
),
).toBe("mobile-dependency-links-stay-in-spa");
await assertNoDocumentHorizontalOverflow(testPage, "mobile dependency navigation");
} finally {
testPage.off("request", onRequest);
}
});