# CLAUDE.md — Cypress Local Tests

Local Cypress E2E tests running against a dockerized Songwhip stack. See `README.md` in this directory for setup, prerequisites, and how the docker stack works.

## Commands (from project root)

```bash
yarn cypress:dev                # open UI with docker stack
yarn cypress:run                # headless run
yarn cypress:run:spec <partial> # run spec by partial name
```

## Test Structure

```
integration/           # All active tests — write new tests here
├── features/          # Cross-cutting features (authGate, videos, stories)
├── pages/             # Page-level tests (catalog, artists, albums, tracks, prereleases, customPage)
└── user/              # User flows (session, pickAccount)
integration_legacy/    # DEPRECATED — never reference or use as examples
```

## Key Conventions

- **Test entities** — use page objects from `lib/`: `TestUser`, `TestAlbumPage`, `TestArtistPage`, `TestTrackPage`, `TestPrereleasePage`, `TestCustomPage`, `TestCatalogPage`, `TestLabel`
- **Selectors** — always `cy.testId('name')`, never CSS classes. Chain: `cy.testId('parent').testId('child')`
- **DB reset** — call `resetSongwhipApiDatabase()` in the outermost `before()` of every spec
- **Hydration** — custom `cy.visit()` handles it; use `cy.waitForHydration()` after `cy.reload()`
- **Apple Music mocks** — must go in `beforeEach`, not `before` (MusicKit caches between tests)
- **Text inputs** — use `changeTextInput('inputId', 'value')` from `lib/utils` (handles debounce)
- **Mock sub-requests** — use `addMockSubRequestsHeader` with helpers from `lib/mocks/subrequests`
- **No hardcoded waits** — use assertions instead of `cy.wait(ms)`
- **Independent tests** — each `it()` must work in isolation, no cross-test state dependencies
- **Fixtures** — mock data in `fixtures/` organized by service (`apple/`, `spotify/`, `youtube/`, `songwhip-api/`, `songwhip-lookup/`, `orchard/`)
