Files
kandev/apps/web/e2e/tests/task/threads-task-actions.spec.ts
T
2026-09-12 16:54:56 +02:00

117 lines
4.3 KiB
TypeScript

import { test, expect } from "../../fixtures/test-base";
import {
allTaskActionOutcomes,
seedActionThreads,
seedLinkedIssue,
ThreadActionsPage,
withTaskActionSettings,
} from "./threads-task-actions-helpers";
import {
failedActionOutcomes,
filteredArchiveOutcome,
lateArchiveOutcome,
} from "./threads-task-actions-edge-helpers";
import { pendingArchiveRecovery, pendingLastArchive } from "./threads-pending-archive-helpers";
for (const [name, outcome] of [
["pending archive recovers without taking focus", pendingArchiveRecovery],
["pending last archive stays empty through settlement", pendingLastArchive],
] as const) {
test(name, async ({ testPage, apiClient, seedData }, testInfo) => {
test.setTimeout(120_000);
await withTaskActionSettings(apiClient, () =>
outcome(testPage, apiClient, seedData, false, testInfo),
);
});
}
for (const [name, outcome] of [
["failures and retry", failedActionOutcomes],
["late archive retains a newer menu", lateArchiveOutcome],
["filtered opener retains archive identity", filteredArchiveOutcome],
] as const) {
test(name, async ({ testPage, apiClient, seedData }) => {
test.setTimeout(120_000);
await withTaskActionSettings(apiClient, () => outcome(testPage, apiClient, seedData, false));
});
}
test("contains long desktop workflow submenus and keeps final steps reachable", async ({
testPage,
apiClient,
seedData,
}) => {
test.setTimeout(120_000);
const { a, destination } = await seedActionThreads(apiClient, seedData);
for (let index = 0; index < 30; index++)
await apiClient.createWorkflowStep(
destination.id,
`${index} ${"LongStep".repeat(20)}`,
index + 1,
);
await testPage.setViewportSize({ width: 900, height: 500 });
await testPage.goto(`/threads?workspace=${seedData.workspaceId}`);
const ui = new ThreadActionsPage(testPage);
await ui.open(a.id);
await ui.nested("Send to workflow");
await ui.nested(destination.name);
const submenu = testPage
.getByRole("menu")
.filter({ has: ui.choice(`29 ${"LongStep".repeat(20)}`) })
.last();
await ui.contained(submenu);
await ui.choice(`29 ${"LongStep".repeat(20)}`).scrollIntoViewIfNeeded();
await expect(ui.choice(`29 ${"LongStep".repeat(20)}`)).toBeInViewport();
await testPage.keyboard.press("Escape");
await expect(ui.trigger(a.id)).toBeFocused();
});
test("completes all six task actions from desktop Threads and cancels destructive choices", async ({
testPage,
apiClient,
seedData,
}) => {
test.setTimeout(240_000);
await seedLinkedIssue(apiClient);
try {
await allTaskActionOutcomes(testPage, apiClient, seedData, false);
} finally {
await apiClient.saveUserSettings({ confirm_task_archive: true });
}
});
// @covers AC-TASKS-THREADS-ACTIONS-003.6, AC-TASKS-THREADS-ACTIONS-004.1, AC-TASKS-THREADS-ACTIONS-004.6
test("keeps native chat context, supports header right-click and keyboard dismissal", async ({
testPage,
apiClient,
seedData,
}) => {
test.setTimeout(180_000);
const { a } = await seedActionThreads(apiClient, seedData);
const ui = new ThreadActionsPage(testPage);
await testPage.goto(`/threads?workspace=${seedData.workspaceId}&taskId=${a.id}`);
await ui.expectHeaderActionAlignment(a.id);
await ui.column(a.id).locator("header p").click({ button: "right" });
await expect(testPage.getByTestId("task-management-menu")).toBeVisible();
await testPage.keyboard.press("Escape");
await expect(ui.trigger(a.id)).toBeFocused();
await ui.trigger(a.id).press("Enter");
await testPage.getByTestId("task-context-priority").focus();
await testPage.keyboard.press("ArrowRight");
await expect(testPage.getByTestId("task-context-priority-low")).toBeVisible();
await testPage.keyboard.press("ArrowLeft");
await testPage.keyboard.press("Escape");
await expect(ui.trigger(a.id)).toBeFocused();
const editor = ui.column(a.id).locator(".tiptap.ProseMirror");
await editor.click({ button: "right" });
await expect(testPage.getByTestId("task-management-menu")).toHaveCount(0);
await editor.fill("Draft kept after task actions");
await ui.open(a.id);
await testPage.keyboard.press("Escape");
await expect(editor).toHaveText("Draft kept after task actions");
await ui.open(a.id);
await testPage.mouse.click(4, 4);
await expect(testPage.getByTestId("task-management-menu")).toHaveCount(0);
await expect(ui.trigger(a.id)).toBeFocused();
});