test-selectorslisted
Install: claude install-skill soumit-kaz/lazysitter
# Test selectors and assertions
## Query priority, and the reason for it
1. **`getByRole(role, { name })`** — how assistive technology finds the element.
2. **`getByLabelText`** — form controls.
3. **`getByPlaceholderText`** — only when there is genuinely no label (which is itself a defect).
4. **`getByText`** — non-interactive content.
5. **`getByDisplayValue`** — the current value of an input.
6. **`getByTestId`** — **last resort**.
This is not a style preference. **A role query that passes proves the element is exposed to assistive technology with an accessible name** — so it tests behaviour and accessibility in a single assertion. A `data-testid` proves only that someone added an attribute.
```jsx
getByRole('button', { name: 'Delete item' }) // asserts: it is a button, and it is named
getByTestId('delete-btn') // asserts: an attribute exists
```
The first fails if the button becomes a `<div>` with no role, or loses its label. The second passes happily while the UI becomes unusable by keyboard and screen reader.
## When `data-testid` is legitimate
- A container with no accessible representation (a layout wrapper you need to scope a query to).
- Elements distinguished only by position among identical siblings.
- A canvas or custom-rendered surface with no DOM semantics.
Each one deserves a comment saying why. Every testid is a place where the test can pass while the UI is broken for real users.
## Assert the outcome, not the mechanism
```jsx