import { expect, test } from "@playwright/test"; import { captureScreenshot, completeOnboarding, projectRow, rpc, signup, waitForChatComposer, } from "./helpers"; test("a new project opens straight into the conversation with its own main agent", async ({ page, }, testInfo) => { const stamp = Date.now(); await signup(page, `project-main-${stamp}@rakazo.test`, "password12", "Project Main"); await completeOnboarding(page); const homeSpaceId = await page.evaluate(() => window.localStorage.getItem("rakazo:space-id")); const homeMain = await rpc<{ id: string }>(page, "bots/ensureMain", {}); const projekte = page.locator(".sidebar-projekte"); await projekte.getByTestId("create-project-trigger").click(); const dialog = page.getByRole("dialog", { name: "New project" }); await dialog.getByLabel("Name").fill("Launch"); await dialog.getByRole("button", { name: "Create project", exact: true }).click(); await page.waitForURL(/\/app\/g\/[^/]+$/, { timeout: 30_000 }); await expect .poll(() => page.evaluate(() => window.localStorage.getItem("rakazo:space-id"))) .not.toBe(homeSpaceId); await waitForChatComposer(page); // The project is one conversation, led by a main agent of its own. const projectEntry = projectRow(projekte, "Launch"); await expect(projectEntry).toBeVisible({ timeout: 30_000 }); await expect(projekte.getByRole("button", { name: "Start", exact: true })).toHaveCount(0); const groupId = new URL(page.url()).pathname.split("/").at(-1)!; const snapshot = await rpc<{ leadBotId?: string }>(page, "threads/get", { groupId }); expect(snapshot.leadBotId).toBeTruthy(); expect(snapshot.leadBotId).not.toBe(homeMain.id); const composer = page.getByRole("combobox", { name: "Message" }); await composer.fill("What should we do first?"); await composer.press("Enter"); const transcript = page.getByTestId("transcript"); await expect(transcript).toContainText(/on it|handled/i, { timeout: 60_000 }); await captureScreenshot(page, testInfo, "project-main-conversation"); }); test("a project's main agent hands work to the project's specialist", async ({ page, }, testInfo) => { const stamp = Date.now(); await signup(page, `project-delegate-${stamp}@rakazo.test`, "password12", "Project Delegate"); await completeOnboarding(page); const projekte = page.locator(".sidebar-projekte"); await projekte.getByTestId("create-project-trigger").click(); const dialog = page.getByRole("dialog", { name: "New project" }); await dialog.getByLabel("Name").fill("Website"); await dialog.getByRole("button", { name: "Create project", exact: true }).click(); await page.waitForURL(/\/app\/g\/[^/]+$/, { timeout: 30_000 }); await waitForChatComposer(page); const groupId = new URL(page.url()).pathname.split("/").at(-1)!; const designer = await rpc<{ id: string }>(page, "bots/create", { name: "Designer", title: "", description: "", instructions: "", notifyOnFinish: true, }); const composer = page.getByRole("combobox", { name: "Message" }); await composer.fill("delegate to the bot named Designer: sketch a landing page"); await composer.press("Enter"); const transcript = page.getByTestId("transcript"); const card = transcript.getByTestId("delegated-task-card"); await expect(card).toBeVisible({ timeout: 60_000 }); await expect(card).toContainText("Designer"); await expect(card).toHaveAttribute("data-status", "done", { timeout: 60_000 }); await expect( transcript.getByText("closing the task: sketch a landing page.").first(), ).toBeVisible({ timeout: 60_000 }); const snapshot = await rpc<{ members?: Array<{ botId: string }> }>(page, "threads/get", { groupId, }); expect(snapshot.members?.map((member) => member.botId)).toContain(designer.id); await captureScreenshot(page, testInfo, "project-main-agent-delegates"); });