BangSo/apps/web/e2e/helpers.ts

97 lines
3.7 KiB
TypeScript

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<T>(page: Page, procedure: string, body: unknown): Promise<T> {
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();
}