← ClaudeAtlas

component-test-writerlisted

Write React component, hook, and end-to-end tests using Vitest, React Testing Library, MSW, and Playwright — chosen for behaviour coverage rather than line coverage, with accessible queries and no implementation-detail assertions. Use this skill whenever the user asks for tests, mentions Vitest, Jest, React Testing Library, MSW, Playwright, Cypress, test coverage, flaky tests, mocking API calls, or testing hooks, forms, async UI, or user flows — including "add tests for this component" and "why is this test flaky".
jayeshsojitra103/claude-frontend-skills · ★ 0 · Testing & QA · score 61
Install: claude install-skill jayeshsojitra103/claude-frontend-skills
# Component Test Writer A test suite is worth what it catches minus what it costs to maintain. Tests coupled to implementation break on every refactor while catching nothing, which is how teams end up with 90% coverage and no confidence. This skill writes tests against behaviour the user can observe. ## Choose the level first | Level | Tool | Use for | Keep it | |---|---|---|---| | Unit | Vitest | pure functions, reducers, formatters, validation | many, fast | | Component | Vitest + RTL | rendering, interaction, conditional UI, a11y contract | most of the suite | | Integration | RTL + MSW | data fetching, forms with real submit, routing | a solid layer | | E2E | Playwright | critical revenue paths across real pages | few, high value | The common failure is inversion: a hundred shallow component tests and no test that a user can actually check out. Ask what breaking would be most expensive, and start there. ## Component tests **Query priority.** Use `getByRole` first, then `getByLabelText` for form fields, then `getByText`. `getByTestId` is the last resort. This is not stylistic — role-based queries fail when the component becomes inaccessible, so the suite doubles as an accessibility regression net. **Interact as a user.** `userEvent` over `fireEvent`: it dispatches the full event sequence (pointerdown, focus, keydown, input) that real interaction produces, so it catches bugs `fireEvent.change` walks straight past. ```tsx const user = userEvent.setup(); await user.typ