Files
kandev/apps/web/e2e/tests/session/multi-session.spec.ts
T

144 lines
4.8 KiB
TypeScript

import { test, expect } from "../../fixtures/test-base";
import { KanbanPage } from "../../pages/kanban-page";
import { SessionPage } from "../../pages/session-page";
const DONE_STATES = ["COMPLETED", "WAITING_FOR_INPUT"];
/**
* Tests for launching multiple sessions on the same task.
* Verifies session handover context injection and environment reuse.
*/
test.describe("Multi-session", () => {
test("second session on same task receives handover context", async ({
testPage,
apiClient,
seedData,
}) => {
test.setTimeout(90_000);
// 1. Create task and start first agent session
const task = await apiClient.createTaskWithAgent(
seedData.workspaceId,
"Multi Session Task",
seedData.agentProfileId,
{
description: "/e2e:simple-message",
workflow_id: seedData.workflowId,
workflow_step_id: seedData.startStepId,
repository_ids: [seedData.repositoryId],
},
);
// 2. Wait for first session to finish
await expect
.poll(
async () => {
const { sessions } = await apiClient.listTaskSessions(task.id);
return DONE_STATES.includes(sessions[0]?.state ?? "");
},
{ timeout: 30_000, message: "Waiting for first session to finish" },
)
.toBe(true);
// 3. Verify first session created environment
const env = await apiClient.getTaskEnvironment(task.id);
expect(env).not.toBeNull();
// 4. Navigate to task and verify first session is visible
const kanban = new KanbanPage(testPage);
await kanban.goto();
const card = kanban.taskCardByTitle("Multi Session Task");
await expect(card).toBeVisible({ timeout: 10_000 });
await card.click();
await expect(testPage).toHaveURL(/\/t\//, { timeout: 15_000 });
const session = new SessionPage(testPage);
await session.waitForLoad();
// Verify first session's response is visible
await expect(session.chat.getByText("simple mock response", { exact: false })).toBeVisible({
timeout: 15_000,
});
// 5. Verify task has exactly one session
const { sessions: sessionsAfterFirst } = await apiClient.listTaskSessions(task.id);
expect(sessionsAfterFirst).toHaveLength(1);
expect(sessionsAfterFirst[0].task_environment_id).toBe(env!.id);
});
test("task environment persists after session completes", async ({ apiClient, seedData }) => {
test.setTimeout(90_000);
// Create task and start agent
const task = await apiClient.createTaskWithAgent(
seedData.workspaceId,
"Env Persistence Task",
seedData.agentProfileId,
{
description: "/e2e:simple-message",
workflow_id: seedData.workflowId,
workflow_step_id: seedData.startStepId,
repository_ids: [seedData.repositoryId],
},
);
// Wait for session to finish
await expect
.poll(
async () => {
const { sessions } = await apiClient.listTaskSessions(task.id);
return DONE_STATES.includes(sessions[0]?.state ?? "");
},
{ timeout: 30_000, message: "Waiting for session to finish" },
)
.toBe(true);
// Verify environment still exists and is in "ready" state after completion
const env = await apiClient.getTaskEnvironment(task.id);
expect(env).not.toBeNull();
expect(env!.status).toBe("ready");
expect(env!.task_id).toBe(task.id);
});
test("second session reuses same worktree as first session", async ({ apiClient, seedData }) => {
test.setTimeout(90_000);
// 1. Create task with first session
const task = await apiClient.createTaskWithAgent(
seedData.workspaceId,
"Worktree Reuse Task",
seedData.agentProfileId,
{
description: "/e2e:simple-message",
workflow_id: seedData.workflowId,
workflow_step_id: seedData.startStepId,
repository_ids: [seedData.repositoryId],
},
);
// 2. Wait for first session to finish
await expect
.poll(
async () => {
const { sessions } = await apiClient.listTaskSessions(task.id);
return DONE_STATES.includes(sessions[0]?.state ?? "");
},
{ timeout: 30_000, message: "Waiting for first session to finish" },
)
.toBe(true);
// 3. Capture first session's environment info
const { sessions: firstSessions } = await apiClient.listTaskSessions(task.id);
const firstSession = firstSessions[0];
const env = await apiClient.getTaskEnvironment(task.id);
expect(env).not.toBeNull();
// 4. Verify the session points to the task environment
// The worktree reuse is verified through the task_environment_id linkage:
// when a second session launches on the same task, persistTaskEnvironment()
// finds the existing environment and reuses its WorktreeID.
expect(firstSession.task_environment_id).toBe(env!.id);
});
});