web/e2e/specs/onboarding.spec.ts
Rama master · réplica de lectura del repositorio original.
import { expect } from "playwright/test";
import { afterAll, describe, it } from "vitest";
import { BASE_URL, E2E_WORKSPACE_PATH } from "../helpers";
import { authedPage, closeBrowser } from "./browser";
import { clearDefaultWorkspaceOwnership, restoreDefaultWorkspaceOwnership, updateUser } from "../setup/db";
// The wizards restore their flags on completion; afterAll is a safety net so a mid-test failure can't leave the seeded user stranded in a wizard, or leave the default workspace without an Owner role for every other spec file that assumes one exists.
afterAll(() => {
updateUser({ first_login_done: 1 });
restoreDefaultWorkspaceOwnership();
return closeBrowser();
});
describe("onboarding wizards", () => {
it("welcome wizard: opens at first sign-in, and finishing later continues into the app", async () => {
updateUser({ first_login_done: 0 });
const page = await authedPage(`${E2E_WORKSPACE_PATH}/docs`);
await page.waitForURL("**/wizard/welcome?step=profile");
await expect(page.getByRole("heading", { name: "Introduce yourself" })).toBeVisible();
await page.getByRole("button", { name: "Continue", exact: true }).click();
await page.waitForURL((url) => url.searchParams.get("step") !== "profile");
await page.getByRole("button", { name: "Finish later", exact: true }).click();
await page.waitForURL(`${BASE_URL}${E2E_WORKSPACE_PATH}`);
await expect(page.getByRole("heading", { name: /docs, tickets, chat, and deploys/i })).toBeVisible();
});
it("owner wizard: first user sets up their workspace, connects tools, and finishes with no computer", async () => {
updateUser({ first_login_done: 1 });
// global.ts's seed pre-creates the default workspace's Owner role/membership for every other spec's benefit, but tenancy.BindDefaultWorkspaceOwner always INSERTs a fresh one (idx_roles_owner_singleton), so this genuinely-fresh-owner flow 409s unless that pre-seeded row is cleared first.
clearDefaultWorkspaceOwnership();
const page = await authedPage("/");
await page.waitForURL("**/onboarding/owner");
await page.getByRole("button", { name: "Continue", exact: true }).click();
// The workspace step names the workspace only; projects come from the project wizard.
await expect(page.getByLabel("Workspace name", { exact: true })).toBeVisible();
await expect(page.getByLabel(/project/i)).toHaveCount(0);
await page.getByRole("button", { name: "Continue", exact: true }).click();
// Connect your tools is the last step; no computer is needed to finish. Wait for it, or the click lands on the workspace step's busy Continue.
await expect(page.getByRole("heading", { name: "Connect your tools" })).toBeVisible();
await page.getByRole("button", { name: "Continue", exact: true }).click();
await expect(page.getByRole("heading", { name: "Workspace ready" })).toBeVisible();
// The Welcome wizard takes over at its finish view, listing what is still the owner's to set up, past the profile the owner wizard already set.
await page.waitForURL((url) => url.pathname === "/wizard/welcome" && url.searchParams.get("step") === "finish");
await expect(page.getByRole("heading", { name: "2 things left for later" })).toBeVisible();
await expect(page.getByRole("button", { name: "Open Connect GitHub" })).toBeVisible();
await expect(page.getByRole("button", { name: "Open Your computer" })).toBeVisible();
await page.getByRole("button", { name: "Finish later", exact: true }).click();
await page.waitForURL((url) => !url.pathname.startsWith("/wizard/welcome"));
});
it("dns onboarding renders and can be skipped", async () => {
const page = await authedPage("/wizard/onboarding/dns");
await page.waitForLoadState("networkidle");
await expect(
page.getByRole("heading", { name: /set up dns/i }),
).toBeVisible();
await page.getByRole("button", { name: /skip for now/i }).click();
await page.waitForURL("**/");
});
});