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

108 lines
3.5 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"];
const HANDOFF_SUMMARY = "Handoff summary: completed the prior session work.";
async function mockSummarizeUtility(testPage: import("@playwright/test").Page) {
await testPage.route("**/api/v1/utility/execute", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
success: true,
response: HANDOFF_SUMMARY,
}),
});
});
}
async function createProfiles(
apiClient: InstanceType<typeof import("../../helpers/api-client").ApiClient>,
) {
const { agents } = await apiClient.listAgents();
if (agents.length === 0) throw new Error("no agents available in test fixtures");
const agentId = agents[0].id;
const profileA = await apiClient.createAgentProfile(agentId, "Handoff Profile A", {
model: "mock-fast",
});
const profileB = await apiClient.createAgentProfile(agentId, "Handoff Profile B", {
model: "mock-slow",
});
return { profileA, profileB };
}
test.describe("Session handoff", () => {
test("opens handoff dialog with target profile from session tab context menu", async ({
testPage,
apiClient,
seedData,
}) => {
test.setTimeout(120_000);
const { profileA, profileB } = await createProfiles(apiClient);
await mockSummarizeUtility(testPage);
const task = await apiClient.createTaskWithAgent(
seedData.workspaceId,
"Session Handoff Task",
profileA.id,
{
description: "/e2e:simple-message",
workflow_id: seedData.workflowId,
workflow_step_id: seedData.startStepId,
repository_ids: [seedData.repositoryId],
},
);
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);
const { sessions } = await apiClient.listTaskSessions(task.id);
const session1Id = sessions[0].id;
const kanban = new KanbanPage(testPage);
await kanban.goto();
await kanban.taskCardByTitle("Session Handoff Task").click();
await expect(testPage).toHaveURL(/\/t\//, { timeout: 15_000 });
const session = new SessionPage(testPage);
await session.waitForLoad();
await expect(session.chat.getByText("simple mock response", { exact: false })).toBeVisible({
timeout: 15_000,
});
await session.openHandoffDialog(session1Id, profileB.id);
await expect(session.handoffDialog()).toBeVisible({ timeout: 5_000 });
await expect(session.handoffDialog()).toContainText("Hand off to");
await expect(session.handoffDialog()).toContainText("Handoff Profile B");
const prompt = session.newSessionPromptInput();
await expect(prompt).toHaveValue(HANDOFF_SUMMARY, { timeout: 15_000 });
await prompt.fill(`${HANDOFF_SUMMARY}\n/e2e:simple-message`);
await session.newSessionStartButton().click();
await expect(session.handoffDialog()).not.toBeVisible({ timeout: 15_000 });
await expect
.poll(
async () => {
const { sessions: updated } = await apiClient.listTaskSessions(task.id);
return updated.length;
},
{ timeout: 30_000, message: "Waiting for handoff session to be created" },
)
.toBe(2);
});
});