# Write E2e Test

> Write a Playwright E2E test for Bruno. Use when adding or modifying tests under tests/, creating a new test suite, or reproducing a bug as an e2e spec.

- Skill: `usebruno/write-e2e-test` (Agent Skill)
- Install (CLI): `npx skillmds@latest add usebruno/write-e2e-test`
- Raw SKILL.md: https://api.skillmd.com/api/skills/usebruno/write-e2e-test/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: usebruno (https://skillmd.com/u/usebruno)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/usebruno/write-e2e-test

---


# Writing a Bruno E2E test

Read `.claude/rules/testing.md` first for the full fixture and helper reference. See
`docs/playwright-testing-guide.md` for the extended walkthrough (codegen, running,
debugging, troubleshooting) — but where it disagrees with this skill or the actual repo,
trust the repo: specs live in `tests/` (not `e2e-tests/`), the suite is `fullyParallel`,
and projects are `default`, `system-pac`, `auth`, and `ssl`
(verify in `playwright.config.ts`).

## Start with codegen or by hand

- **Codegen** (fastest for a new flow): `npm run test:codegen <name>` launches the app,
  records your clicks, and writes `tests/<name>.spec.ts`. Treat the output as a rough
  draft — move it into the right area folder, swap generated selectors for `data-testid`
  or helpers, wrap steps in `test.step`, and delete dead recorded actions.
- **By hand**: `import { test, expect } from '../../playwright'` and follow the steps below.

## Steps

1. **Place the spec** at `tests/<area>/<name>.spec.ts` — reuse an existing area dir under
   `tests/` (list it for the current set; e.g. `request/`, `collection/`, `environments/`,
   `runner/`, `scripting/`) or add one. Pick the project: `default` for most specs;
   `auth` / `ssl` / `system-pac` only when the test needs those
   servers or external dependencies.
2. **Use fixtures** from `playwright/index.ts` (read it for the full set) instead of launching
   the app yourself:
   - `page` / `electronApp` — default app with onboarding skipped.
   - `pageWithUserData` — seeds data from `tests/<area>/init-user-data/`
     (use `init-user-data-fresh/` for new-user flows).
   - `createTmpDir(tag?)` — throwaway dir for collections/files the test creates; cleaned
     up automatically, so prefer it over hardcoded paths.
   - `newPage`, `launchElectronApp`, `reuseOrLaunchElectronApp`, `restartApp` — for
     multi-window or app-restart scenarios.
   - `collectionFixturePath` / `workspaceFixturePath` — copy a committed fixture to a tmp
     dir and get its path.
3. **Use helpers** from `tests/utils/page/` instead of hand-rolling clicks — read the module
   for the current set (e.g. `createCollection`, `sendRequest`, `runCollection`).
4. **Structure each test** arrange → act → assert, and wrap the phases in `test.step` so
   the HTML report reads clearly. Prefer several focused assertions over one broad check.
5. **Wait for readiness**: `await page.locator('[data-app-state="loaded"]').waitFor()`
   before asserting on app state.
6. **Locate** by `data-testid` (Bruno's dominant convention) or documented classes
   (`.collection-item-name`); stable `getByRole` / `getByText` locators are fine too.
   Avoid brittle CSS, `#id`, or index-based selectors. If no stable selector exists, add a
   `data-testid` to the component rather than locating by text.
7. **If the test mutates a committed fixture**, restore it in `afterAll`. Existing specs
   do this with `git checkout <fixturePath>` (e.g. `tests/response-examples/*.spec.ts`) —
   follow the pattern already used by neighbouring specs in that area.
8. **Use auto-retrying assertions** (`expect(locator).toBeVisible()`); never assert
   immediately after a file-watcher-triggered change (created files take a tick to appear).
   Reserve `page.waitForTimeout()` for when no locator assertion can wait instead.
9. **Run it**: `npx playwright test tests/<area>/<name>.spec.ts --project=default`
   (the web + test servers start automatically). Debug with `--ui`, `--headed`, `--debug`,
   or `--trace on` (then `npx playwright show-trace test-results/**/trace.zip`).

## Checklist before done

- [ ] Test is isolated — unique tmp paths (`createTmpDir`), no state shared with other tests
- [ ] Passes on a clean second run (retry-safe; worker fixtures persist across retries)
- [ ] Folders expanded before asserting on their children (collapsed = not in DOM)
- [ ] Any mutated committed fixture is restored in `afterAll`
- [ ] Any codegen-generated draft refactored to fixtures/helpers + stable selectors
- [ ] Steps wrapped in `test.step`; no `test.only`, no `page.pause()`

