import { expect, test, type Page } from "@playwright/test"; const ADMIN_EMAIL = process.env.PAPERCLIP_RELEASE_SMOKE_EMAIL ?? process.env.SMOKE_ADMIN_EMAIL ?? "smoke-admin@paperclip.local"; const ADMIN_PASSWORD = process.env.PAPERCLIP_RELEASE_SMOKE_PASSWORD ?? process.env.SMOKE_ADMIN_PASSWORD ?? "paperclip-smoke-password"; const COMPANY_NAME = `Release-Smoke-${Date.now()}`; const AGENT_NAME = "Release Smoke Lead"; // The arc asks for a name, not a role, so every onboarding hire is filed under // the neutral role (DEFAULT_AGENT_ROLE in ui/src/lib/onboarding-agent-role.ts). const AGENT_ROLE = "general"; // Seeded by the wizard's launch step (DEFAULT_TASK_TITLE in // ui/src/components/OnboardingWizard.tsx). const FIRST_TASK_TITLE = "Paperclip onboarding"; async function signIn(page: Page) { await page.goto("/"); await expect(page).toHaveURL(/\/auth/); await page.locator('input[type="email"]').fill(ADMIN_EMAIL); await page.locator('input[type="password"]').fill(ADMIN_PASSWORD); await page.getByRole("button", { name: "Sign In" }).click(); await expect(page).not.toHaveURL(/\/auth/, { timeout: 20_000 }); } async function getJson(page: Page, url: string): Promise { const response = await page.request.get(url); expect(response.ok()).toBe(true); return (await response.json()) as T; } // ONBOARDING_STORAGE_KEY in ui/src/components/OnboardingWizard.tsx. const ONBOARDING_DRAFT_STORAGE_KEY = "paperclip-onboarding-state"; /** * Open the wizard on its first step and hand back the organization-name field. * * `/onboarding` resolves to `{ initialStep: 1 }` on a self-hosted instance * (`resolveRouteOnboardingOptions`) and the route keeps the wizard open, so * this lands on "name your organization" whether or not the instance already * holds a company. Navigating explicitly is what keeps the spec re-runnable: * the release-smoke config retries once in CI, and by the second attempt the * instance is no longer company-less, so sign-in lands on a dashboard instead. * * The saved draft is dropped first. Sign-in on an instance that already holds * an agentless company redirects into *that* company's onboarding, which * persists its id into the draft; the restored draft then makes step 1 skip * creating a company and hire into the old one instead. That is an artifact of * re-running against a re-used instance, not behaviour this spec is asserting, * and a fresh release-smoke container never has it. * * The field is located by role. Step 1 has no id and its `