Queries & Selectors
Choose getBy, queryBy, and findBy queries following Testing Library priority.
Query Priority
Prefer queries in order: getByRole (with accessible name), getByLabelText, getByPlaceholderText, getByText, getByDisplayValue, getByAltText, getByTitle, last resort getByTestId.
Accessible queries keep tests aligned with screen readers and keyboard users—improving both test quality and app a11y.
screen.getByRole("button", { name: /submit/i });
screen.getByLabelText("Email address");
screen.getByTestId("custom-widget"); // when no accessible handlegetBy Queries
getBy* throws if element not found or multiple matches—fail fast in happy path tests. Use regex or exact string for name and text options.
Within getByRole, name matches accessible name computation from aria-label, labelledby, or element text.
- Multiple elements error—use getAllBy* or narrow with within()
- Hidden elements excluded by default; { hidden: true } overrides
- Selector option on getByRole filters role subset
screen.getByRole("heading", { level: 1, name: "Dashboard" });
screen.getByText((content, element) => content.startsWith("Welcome"));queryBy Queries
queryBy* returns null if absent—use for asserting element does not exist. Combine with expect(...).not.toBeInTheDocument().
Do not use queryBy when element should exist—getBy gives better error message on failure.
expect(screen.queryByText("Error")).not.toBeInTheDocument();findBy Queries
findBy* returns Promise resolving when element appears—default 1000ms timeout. Use for async data fetch rendering content after mount.
await screen.findByRole("alert") waits for success message. All findAllBy variants exist for lists.
render(<UserProfile userId="1" />);
expect(await screen.findByText("Ada Lovelace")).toBeInTheDocument();within and Custom Queries
within(container) scopes queries to subtree—tables, modals, list items. buildQueries creates reusable custom query bundles for repeated patterns.
Avoid container.querySelector—it bypasses Testing Library visibility and accessibility checks.
const row = screen.getByRole("row", { name: /Ada/ });
within(row).getByRole("button", { name: "Edit" });