Files
PaperClipAI/tests/e2e/onboarding.spec.ts
T
DottaandPaperclip c79d347abe Update company creation copy (#8653)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The onboarding and company switcher UI are the first places users
create or select an organization
> - Some of that surface still used older team/workspace wording even
though the product model is company-centric
> - Mixed wording makes the setup path feel inconsistent and can make
users wonder whether they are creating a team, workspace, or company
> - This pull request updates the affected UI copy to consistently say
company
> - The benefit is a clearer first-run and navigation experience without
changing behavior

## Linked Issues or Issue Description

No public issue exists for this small UI polish change.

### Problem or motivation

The company creation and switcher surfaces used mixed
team/workspace/company wording for the same concept, which makes the
setup path feel inconsistent.

### Proposed solution

Update the visible copy, accessibility label, inline comment, e2e
expectations, and matching test expectations to use company-centric
language consistently.

### Alternatives considered

Leave the existing wording alone, but that preserves inconsistent
terminology in a high-traffic setup path.

### Roadmap alignment

This is focused UI polish and does not overlap with a roadmap-level core
feature.

### Additional context

The create action keeps its trailing ellipsis because it opens the
onboarding wizard rather than completing immediately.

## What Changed

- Updated front door and onboarding wizard labels from team-oriented
copy to company-oriented copy.
- Updated the sidebar company menu from workspace/team wording to
company wording, including the trigger accessibility label and empty
fallback text.
- Kept the sidebar create action ellipsis for the dialog/wizard
affordance.
- Updated component and Playwright test expectations for the new copy.

## Verification

- `pnpm exec vitest run ui/src/components/SidebarCompanyMenu.test.tsx`
- Attempted `npx playwright test --config tests/e2e/playwright.config.ts
tests/e2e/onboarding.spec.ts tests/e2e/nux-phase4-screenshots.spec.ts
tests/e2e/planning-mode-visual-verification.spec.ts
tests/e2e/conference-room-typing-intro.spec.ts`; local browser launch is
blocked by missing host Chromium dependencies (`libatk1.0-0t64`,
`libatspi2.0-0t64`, `libxcomposite1`, `libxdamage1`, `libxfixes3`,
`libxrandr2`, `libgbm1`, `libasound2t64`).
- Screenshots intentionally omitted because this is a copy-only change
and no design screenshots are needed for review.

## Risks

Low risk. This is copy-only UI polish plus matching test updates; no
data model, API, migration, workflow, lockfile, or behavior changes are
included.

## Model Used

OpenAI GPT-5 Codex (`gpt-5`) via the Paperclip Codex agent, with
tool-assisted repository inspection, GitHub CLI usage, and local command
execution.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-06-26 12:01:02 -05:00

102 lines
4.1 KiB
TypeScript

import { test, expect } from "@playwright/test";
/**
* E2E: Onboarding wizard flow (NUX Phase 2 expanded wizard).
*
* The wizard now opens on a front door (path picker) and the "Create a new
* company" path runs:
* Step 0 — Front door (Create a new company / Level up existing)
* Step 1a — Name your company
* Step 1b — Define your mission (direct or guided)
* Step 2 — Hire your team lead (adapter picker)
* Step 3+ — Launch celebration → CEO chat → hiring plan → orientation
*
* This test covers the deterministic, LLM-free core: it drives the front door
* through company naming + mission definition (which creates the company and a
* company-level goal) and verifies the wizard advances to the team-lead step.
*
* The tail (CEO chat at step 4, hiring-plan generation at step 5, final
* landing) depends on a live LLM and is verified separately during manual /
* LLM-backed QA — see PAP-50. Surface-level rendering of every step is
* snapshotted by nux-phase4-screenshots.spec.ts.
*/
const COMPANY_NAME = `E2E-Test-${Date.now()}`;
const MISSION = "Build affordable home robots that handle household chores.";
test.describe("Onboarding wizard", () => {
test("create-company path: name + mission creates company and goal", async ({
page,
}) => {
const pageErrors: string[] = [];
page.on("pageerror", (err) => pageErrors.push(err.message));
// New-NUX surfaces are flag-gated default-OFF (PAP-136/137/138): turn the
// experimental flag on for this throwaway instance before driving them.
const flagRes = await page.request.patch("/api/instance/settings/experimental", {
data: { enableConferenceRoomChat: true },
});
expect(flagRes.ok()).toBe(true);
await page.goto("/onboarding");
// The wizard may open on a launcher card or directly on the capsule
// wizard; the front door (step 0) requires a click into the create path.
const startBtn = page.getByRole("button", {
name: /Start Onboarding|New Company|Add Agent/,
});
if (await startBtn.count()) {
await startBtn.first().click();
}
const createCard = page.getByRole("button", { name: /Build a new company/ });
if (await createCard.count()) {
await createCard.first().click();
}
// Step 1 — Name your company.
await expect(
page.getByRole("heading", { name: "Name your company" }),
).toBeVisible({ timeout: 15_000 });
await page.getByPlaceholder("Acme Corp").fill(COMPANY_NAME);
await page.getByRole("button", { name: /^Next/ }).click();
// Step 2 — Define your mission (direct entry is the default path).
await expect(
page.getByRole("heading", { name: "Define your mission" }),
).toBeVisible({ timeout: 10_000 });
await page
.getByPlaceholder("What is your team trying to achieve?")
.fill(MISSION);
// "Confirm mission" creates the company + a company-level goal, then
// advances to the team-lead naming step of the capsule wizard.
await page.getByRole("button", { name: /Confirm mission/ }).click();
await page.waitForSelector('input[placeholder="Chief of staff"]', {
timeout: 30_000,
});
// Verify the company + company-level goal were persisted.
const baseUrl = page.url().split("/").slice(0, 3).join("/");
const companiesRes = await page.request.get(`${baseUrl}/api/companies`);
expect(companiesRes.ok()).toBe(true);
const companies = await companiesRes.json();
const company = companies.find(
(c: { name: string }) => c.name === COMPANY_NAME,
);
expect(company, `company ${COMPANY_NAME} should exist`).toBeTruthy();
const goalsRes = await page.request.get(
`${baseUrl}/api/companies/${company.id}/goals`,
);
expect(goalsRes.ok()).toBe(true);
const goals = await goalsRes.json();
const companyGoal = (Array.isArray(goals) ? goals : []).find(
(g: { level?: string }) => g.level === "company",
);
expect(companyGoal, "a company-level goal should be created").toBeTruthy();
// The expanded wizard must not crash the app (Rules-of-Hooks regression).
expect(pageErrors, pageErrors.join("\n")).toHaveLength(0);
});
});