Testing Library Queries Priority
Query UI like a user — getByRole first, test ids last, and which variant (get/query/find) to use for presence and async.
- testing
- testing-library
Testing Library’s default recommendation is a priority list of queries. Follow it and your tests stay close to assistive tech and human users. Ignore it and you test CSS class soup.
Docs: About Queries, Cheatsheet.
The priority list
- Accessible queries
getByRolegetByLabelTextgetByPlaceholderTextgetByTextgetByDisplayValue
- Semantic extras
getByAltTextgetByTitle
- Test IDs
getByTestId
// Prefer
screen.getByRole('button', { name: /sign in/i });
screen.getByLabelText(/email/i);
screen.getByRole('heading', { level: 1, name: /settings/i });
// Avoid as default
screen.getByTestId('email-input');
container.querySelector('.btn-primary');
get vs query vs find
| Prefix | Throws if missing? | Async? | Use |
|---|---|---|---|
getBy |
Yes | No | Element should already be there |
queryBy |
No (null) |
No | Assert absence |
findBy |
Yes (after timeout) | Yes | Element appears after wait |
// present
expect(screen.getByRole('alert')).toHaveTextContent(/error/i);
// absent
expect(screen.queryByRole('alert')).not.toBeInTheDocument();
// eventually present
expect(await screen.findByRole('alert')).toBeInTheDocument();
getAllBy / queryAllBy / findAllBy for lists.
Roles you should know
| UI | Role |
|---|---|
| Button | button |
| Link | link |
| Text field | textbox, spinbutton, … |
| Checkbox | checkbox |
| Dialog | dialog |
| Nav | navigation |
| Main | main |
If getByRole can’t find it, the control may lack an accessible name — fix the UI.
// Broken for AT and tests
<div onClick={save}>Save</div>
// Fixed
<button type="button" onClick={save}>Save</button>
Name option
screen.getByRole('button', { name: /continue/i });
screen.getByRole('textbox', { name: /full name/i });
Name comes from label, text content, aria-label, etc. — accessible names.
Within scopes
const dialog = screen.getByRole('dialog');
within(dialog).getByRole('button', { name: /confirm/i });
Avoid ambiguous matches in large pages.
Footguns
getByTextfor buttons — prefer role + name.- Regex too loose (
/a/) matching noise. - Using
queryByfor elements that must exist — fails soft. findBywithout await.
Interview out-loud answer
“I use Testing Library’s query priority: roles and labels first, test ids last. get for present, query for absent, find for async. If role queries fail, I treat it as a possible a11y bug.”
Hidden elements
By default, Testing Library queries ignore styles that hide elements. If you must assert a hidden accessible name (visually hidden labels), check docs for hidden: true options. Prefer visible labels when possible so users and tests share the same path.
Extra practice
Write a minimal demo in a scratch file or the playground: one happy path, one failure path, and one boundary input. If you cannot exhibit a bug that the pattern prevents, you do not own the concept yet — re-read the primary docs linked below and tighten the example until the failure is obvious.
Notes from real codebases
Teams that succeed here keep the rules mechanical: lint where possible, CI for the rest, and a short human checklist for what automation cannot see. Document exceptions with an owner name and a removal date so “temporary” escapes do not become permanent architecture.
Related on this site
- Testing Library
- Test ids as last resort
- user-event vs fireEvent
- Accessible names computation
- Accessibility testing in CI
Further reading
Related guides
- Accessibility Testing in CIWire axe and lint rules into CI without false confidence — what automation catches, what it misses, and a practical pipeline.
- Component Testing StorybookUse Storybook as a component workshop and optional test runner — stories as living specs, interaction tests, and a11y checks.
- Contract Testing APIsKeep frontend and backend agreements honest — schema contracts, Pact-style consumer tests, and OpenAPI-driven checks without brittle E2E.
- Coverage Metrics PitfallsWhy 100% line coverage can still ship bugs — gaming metrics, useless tests, and what coverage is actually good for.
- End-to-End Testing TradeoffsWhen E2E tests earn their keep, why they flake, and how to keep a small critical-path suite instead of a slow second frontend.