Promptheus/commands36 commands · free · CC0Promptheus hub ↗
← All commands
/e2e <user flow>

Test

E2E test a flow

Playwright flow — role selectors, auto-wait, no sleeps.

e2eplaywrighttesting
CategoryTest
Arguments<user flow>
Allowed toolsReadGrepGlobEditWriteBash
What it does

Write a Playwright end-to-end test for a critical user journey with resilient role-based selectors and no flakiness.

.claude/commands/e2e.md.claude/commands/ (project) · ~/.claude/commands/ (global)
Install into your repo
npx promptheus-commands add e2e

The prompt

Write one Playwright end-to-end test covering this user flow: $ARGUMENTS

If $ARGUMENTS is empty, ask the user which flow to test and stop; do not guess.

1. Detect the existing setup before writing anything

  • Read playwright.config.* for testDir, baseURL, projects, webServer, and any global setup/auth storageState. If there is no Playwright config, say so and propose installing it (npm init playwright@latest) instead of inventing one.
  • Open 2-3 existing specs in testDir and mirror their conventions: file naming, fixture imports (project test fixture vs bare @playwright/test), page-object usage, auth pattern, and how they get a base URL. Never hardcode http://localhost:PORT; rely on baseURL and relative paths.
  • Grep the app source for the routes/components in the flow to learn the real roles, labels, and existing data-testids. Do not invent selectors from assumption.

2. Write the test

  • Place it in testDir with the project's naming pattern (e.g. <flow>.spec.ts). One test() per flow, wrapped in a test.describe if peers do.
  • Structure the body as explicit Arrange / Act / Assert steps, optionally grouped with test.step() for readable traces.
  • Selectors, in this priority: getByRole(name:), getByLabel, getByPlaceholder, getByText, then getByTestId. Never CSS/XPath tied to structure, nth-child, or generated class names. If no accessible handle exists, add a data-testid to the component and use it.
  • Assertions: only web-first, auto-retrying expect(locator) (toBeVisible, toHaveText, toHaveURL, toBeEnabled). Assert observable user-facing outcomes, not implementation. Never assert on a bare boolean snapshot (expect(await locator.isVisible()).toBe(true)).
  • Actions auto-wait, so chain them directly. Await every locator action and every assertion.
  • Stub non-deterministic and third-party dependencies inside the flow (payment gateways, analytics, maps, email/SMS, feature flags, Date.now/random-driven UI) with page.route(url, route => route.fulfill(...)) so the test asserts your app's behavior, not a live external service. Register routes before the navigation that triggers them. Do not mock the first-party API you are seeding through — exercise it for real.

3. Independence and state

  • The test must pass alone and in any order, repeatedly. No dependence on a prior test or leftover data.
  • Seed and tear down state via API request context, DB fixture, or the project's existing seeding helper — never by clicking through unrelated UI to set up.
  • Make identifiers unique per run (timestamp/uuid) so reruns don't collide. Clean up created records in afterEach/afterAll or use an isolated/transactional test account.
  • Reuse the project's auth storageState if present; otherwise authenticate in a fixture or beforeEach, not inline in the flow under test.

4. Never

  • Never waitForTimeout, sleep, or arbitrary delays — wait on a condition (locator state, waitForURL, waitForResponse) instead.
  • Never page.waitForSelector when a web-first expect covers it.
  • Never leave test.only, console.log, commented code, or networkidle waits.

5. Verify before finishing

  • Ensure the app is reachable first. If playwright.config.* defines a webServer, Playwright starts it automatically. If it does not, the run targets an already-running server at baseURL — start the dev server (or point baseURL at a live environment) before running, or the spec fails instantly on a dead URL and no selector/wait/seed fix will help.
  • Find the project's real e2e command in package.json scripts (e.g. npm run test:e2e, yarn e2e, pnpm test:e2e) and use it, appending the file path so only this spec runs. Fall back to npx playwright test <file> only if no such script exists.
  • The spec must pass. If it flakes or fails, fix the selector/wait/seed/mock — do not paper over it with a timeout or a retry count. Report the exact command run, pass/fail result, and the final test file path.

Add it to your toolkit

Save it as .claude/commands/e2e.md or .cursor/commands/e2e.md, then invoke it with /e2e and your arguments.

Back to top ↑