Files
kandev/apps/web/e2e/tests/workflow/queue-limit-navigation.spec.ts
2026-09-18 10:33:17 +01:00

119 lines
4.4 KiB
TypeScript

import { expect, test } from "../../fixtures/test-base";
import { KanbanPage } from "../../pages/kanban-page";
import { SessionPage } from "../../pages/session-page";
import { createWipQueueScenario } from "../../helpers/queue-limit-navigation";
import {
createQueuedSessionOwnershipScenario,
waitForLaunchQueue,
} from "./queued-session-ownership-helpers";
test.describe("Queue limit navigation", () => {
test("labels the global capacity queue and returns without changing the task", async ({
testPage,
apiClient,
backend,
seedData,
}) => {
test.setTimeout(240_000);
const releaseCeiling = await backend.useEnv({ KANDEV_MAX_CONCURRENT_SESSIONS: "1" });
let fillerSessionId: string | undefined;
try {
const scenario = await createQueuedSessionOwnershipScenario(
apiClient,
seedData,
"Global queue navigation",
);
fillerSessionId = scenario.fillerSessionId;
await testPage.goto(`/t/${scenario.taskId}`);
await new SessionPage(testPage).waitForLoad();
const queueStatus = testPage.locator('[data-testid="task-launch-queue-status"]:visible');
await expect(queueStatus).toContainText("Global session limit");
await expect(queueStatus).toContainText("All workspaces");
const settingsLink = queueStatus.getByTestId("launch-queue-session-capacity-link");
await expect(settingsLink).toHaveAttribute(
"href",
"/settings/preferences/task-behavior#setting-session-capacity",
);
await settingsLink.click();
await expect(testPage).toHaveURL(
/\/settings\/preferences\/task-behavior#setting-session-capacity$/,
);
await expect(
testPage.locator('[data-settings-target="setting-session-capacity"]'),
).toHaveAttribute("data-settings-target-highlight", "true");
await testPage.goBack();
await new SessionPage(testPage).waitForLoad();
await expect(
testPage.locator('[data-testid="task-launch-queue-status"]:visible'),
).toBeVisible();
await expect(
waitForLaunchQueue(apiClient, seedData.workspaceId, scenario.taskId, 5_000),
).resolves.toMatchObject({ reason: "session_capacity" });
} finally {
if (fillerSessionId) {
await apiClient
.stopSession({
session_id: fillerSessionId,
reason: "queue-limit-navigation e2e cleanup",
force: true,
})
.catch(() => undefined);
}
await releaseCeiling();
}
});
test("links a WIP queue to its workflow and promotes after a saved limit change", async ({
testPage,
apiClient,
seedData,
}) => {
const scenario = await createWipQueueScenario(apiClient, seedData, "WIP queue navigation");
const kanban = new KanbanPage(testPage);
await kanban.goto();
await expect(kanban.taskCard(scenario.queuedTaskId)).toBeVisible();
await kanban.taskCard(scenario.queuedTaskId).click();
const sessionPage = new SessionPage(testPage);
await sessionPage.waitForLoad();
const wipStatus = testPage.getByTestId("task-wip-queue-status");
await expect(wipStatus).toBeVisible();
await expect(wipStatus).toContainText("Workflow WIP limit");
await expect(wipStatus).toContainText("WIP queue navigation workflow / Review");
await expect(wipStatus).toContainText("1 of 1 task admitted");
const settingsLink = wipStatus.getByTestId("wip-queue-settings-link");
await expect(settingsLink).toHaveAttribute(
"href",
`/settings/workspaces/${seedData.workspaceId}/workflows#workflow-card-${scenario.workflowId}`,
);
await settingsLink.click();
await expect(testPage).toHaveURL(
new RegExp(
`/settings/workspaces/${seedData.workspaceId}/workflows#workflow-card-${scenario.workflowId}$`,
),
);
await expect(testPage.getByTestId(`workflow-card-${scenario.workflowId}`)).toHaveAttribute(
"data-settings-target-highlight",
"true",
);
await testPage.goBack();
await sessionPage.waitForLoad();
await expect(wipStatus).toBeVisible();
await apiClient.updateWorkflowStep(scenario.reviewStepId, { wip_limit: 2 });
await expect
.poll(async () => (await apiClient.getTask(scenario.queuedTaskId)).wip_admitted)
.toBe(true);
await expect(wipStatus).toHaveCount(0);
await expect(apiClient.getTask(scenario.admittedTaskId)).resolves.toMatchObject({
wip_admitted: true,
});
});
});