Files
textbee/web/test
isra el 5d43866847 fix: show every plan in onboarding and let finished steps be reopened
The plan step hardcoded Free and Pro inline, so Scale never appeared no
matter what the pricing page offered. Tiers now come from lib/plans,
which mirrors the marketing pricing section, with a test pinning the
values so the two cannot drift silently.

Kept static rather than fetched from /billing/plans. That endpoint
returns Plan documents (limits and cents), not customer-facing copy, and
an environment with no plans rows left the step showing "plans could not
be loaded" with nothing to choose.

Reopening a completed step showed an empty row. Two things caused it:
the body was gated on the step not being done, and an effect cleared the
selection whenever the selected step was done, so clicking a finished
step deselected it on the next render. That effect exists to advance you
when the step you are sitting on completes underneath you, so it now
fires only on that transition. Both paths are covered: reopening the API
key step offers "Generate another API key", and a step completing while
selected still moves the selection on.

Skip is hidden on an already-finished step, where it would mean nothing.

Also corrects the Plan type, which declared amount, currency and
recurringInterval. The plans endpoint has never sent those; they belong
to Subscription. Anything reading plan.amount saw undefined and rendered
a paid plan as free. The fixture encoded the same wrong shape, so tests
would have passed while production broke.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 02:48:12 +03:00
..

Testing

The web app has two test layers. Both run against mocked API data. Tests must never point at a real backend.

Unit / component tests (Vitest + React Testing Library + MSW)

  • Runner: Vitest with jsdom.
  • API mocking: MSW node server (test/msw/server.ts) with handlers in test/msw/handlers.ts. Unhandled requests throw (onUnhandledRequest: 'error'), so a test can never silently reach a live backend.
  • Render helper: test/render.tsx exposes renderWithProviders / render, which wrap components in the app providers (react-query with retries off, a mock SessionProvider). Import render, screen, userEvent from @/test/render.
  • Fixtures: test/fixtures.ts is the single source of truth for mocked API data, shared with the e2e layer.

Commands:

pnpm test          # run once
pnpm test:watch    # watch mode
pnpm coverage      # with coverage report

Place tests next to the code as *.test.tsx or under __tests__/.

End-to-end tests (Playwright)

  • Runner: Playwright, specs in e2e/.
  • The real Next dev server boots on port 3100 with a fixed NEXTAUTH_SECRET and a backend URL (localhost:3999) that nothing listens on.
  • e2e/mock-api.ts intercepts every /api/v1/** request and serves the shared fixtures, so no request can reach a real backend.
  • e2e/session.ts mints a valid NextAuth session cookie so tests run authenticated without the real login flow.

Commands:

pnpm test:e2e      # headless
pnpm test:e2e:ui   # interactive UI

First-time setup downloads the browser: pnpm exec playwright install chromium.

The rule

If a new screen calls a new endpoint, add a handler in test/msw/handlers.ts and a branch in e2e/mock-api.ts, both backed by a fixture in test/fixtures.ts. Never let a test hit the network.