import { expect, type Page, type TestInfo } from "@playwright/test"; export function isRealSandboxProvider(provider = process.env.SANDBOX_PROVIDER) { return provider === "e2b" || provider === "daytona" || provider === "box"; } export function realSandboxTimeout(real: number, emulated: number) { if (process.env.SANDBOX_PROVIDER === "box") return Math.max(real, 300_000); return isRealSandboxProvider() ? real : emulated; } export function activeBotId(page: Page) { const id = new URL(page.url()).pathname.split("/").filter(Boolean).at(-1); if (!id || id === "app") throw new Error(`missing bot id in ${page.url()}`); return id; } export async function rpc(page: Page, procedure: string, body: unknown): Promise { const response = await page.request.post(`/rpc/${procedure}`, { data: { json: body } }); const parsed = (await response.json()) as { json?: T; error?: { message?: string } }; if (!response.ok() || parsed.error) { throw new Error(`${procedure} ${response.status()}: ${parsed.error?.message ?? "failed"}`); } return parsed.json as T; } export async function completeOnboarding(page: Page, testInfo?: TestInfo) { await page.waitForURL(/\/(onboarding|app)/, { timeout: 20_000 }); const heading = page.getByRole("heading", { name: /Connect a model|Create your first bot/ }); const chief = page.getByText("Chief").first(); await heading.or(chief).waitFor({ timeout: 20_000 }); if ((await chief.isVisible().catch(() => false)) && page.url().includes("/app")) return; if ( await page .getByRole("heading", { name: "Connect a model" }) .isVisible() .catch(() => false) ) { if (testInfo) await captureScreenshot(page, testInfo, "02-connect-model"); await page.getByRole("button", { name: "Skip for now" }).click(); await page .getByRole("heading", { name: "Create your first bot" }) .or(chief) .waitFor({ timeout: 20_000 }); } if ( await page .getByRole("heading", { name: "Create your first bot" }) .isVisible() .catch(() => false) ) { if (testInfo) await captureScreenshot(page, testInfo, "03-create-first-bot"); await page.locator("label:has-text('Name') input").fill("Chief"); const created = page.waitForResponse( (response) => response.url().includes("/rpc/bots/create") && response.ok(), ); await page.getByRole("button", { name: "Continue" }).click(); await created; await page.waitForURL(/\/app\//, { timeout: 20_000 }); } await page.waitForURL(/\/app/); await expect(page.getByText("Chief").first()).toBeVisible(); if (testInfo) await captureScreenshot(page, testInfo, "06-onboarding-complete"); } export async function signup( page: Page, email: string, password: string, name: string, testInfo?: TestInfo, ) { await page.goto("/sign-up"); await expect(page.getByRole("heading", { name: "Create your BangSo Bot" })).toBeVisible(); if (testInfo) await captureScreenshot(page, testInfo, "01-sign-up"); await page.getByPlaceholder("Your name").fill(name); await page.getByPlaceholder("Your email address").fill(email); await page.getByPlaceholder("Password").fill(password); await page.getByRole("button", { name: "Create account" }).click(); } export async function captureScreenshot(page: Page, testInfo: TestInfo, name: string) { const screenshotPath = testInfo.outputPath(`${name}.png`); await page.screenshot({ animations: "disabled", caret: "hide", fullPage: true, path: screenshotPath, }); await testInfo.attach(name, { contentType: "image/png", path: screenshotPath }); } export async function openNewBot(page: Page) { await page.getByTitle("Create").click(); await page.getByRole("button", { name: "New bot" }).click(); }