# AGENTS.md: Cypress tests

## Commands
- Headless: `npx cypress run` · one spec: `npx cypress run --spec cypress/e2e/checkout.cy.ts` · component tests: `npx cypress run --component`
- Interactive (for humans): `npx cypress open`

## Writing tests
- Specs in `cypress/e2e/<feature>.cy.ts`; component specs next to components (`Button.cy.tsx`).
- Select by `data-cy` attributes (`cy.get('[data-cy=submit]')`) or accessible text via `cy.contains('button', 'Pay')`. Never select by CSS classes or DOM structure.
- Cypress commands are async and chain; don't assign their results to variables. Use `.then()` or aliases (`.as('order')`).
- Assertions retry: `cy.get(...).should('have.text', 'Paid')`. Never `cy.wait(5000)`; wait on aliased network calls instead: `cy.intercept('POST', '/api/orders').as('createOrder'); ... cy.wait('@createOrder')`.
- Stub third-party and slow services with `cy.intercept` + fixtures; keep at least one happy-path test against the real backend.
- Log in with `cy.session()` + an API request in a custom command (`cy.login()`), not through the UI each time.
- Seed and reset data with `cy.task('db:seed')` or API calls in `beforeEach`; tests must not depend on each other.
- Custom commands live in `cypress/support/commands.ts` with TypeScript declarations.

## Don't
- Don't use `{ force: true }` to click hidden elements, or `cy.wait(<ms>)`.
- Don't disable `testIsolation`.

## Done
The changed specs pass headless 3 times in a row.
