How should I query?
React Native Testing Library provides various query types for finding views in tests. The number of queries can be confusing. This guide helps you pick the right queries for your test scenarios.
Query parts
Each query is composed of two parts: variant and predicate, which are separated by the by word in the middle of the query.
Consider the following query:
For this query, getBy* is the query variant, and *ByRole is the predicate.
Query variant
The query variants describe the expected number (and timing) of matching elements, so they differ in their return type.
Queries work as implicit assertions on the number of matching elements and will throw an error when the assertion fails.
Idiomatic query variants
Idiomatic query variants clarify test intent and the expected number of matching elements. They will also throw helpful errors if assertions fail to help diagnose the issues.
Here are general guidelines for picking idiomatic query variants:
- Use
getBy*in the most common case when you expect a single matching element. Use other queries only in more specific cases. - Use
findBy*when an element is not yet in the element tree, but you expect it to be there as a result of some asynchronous action. - Use
getAllBy*(andfindAllBy*for async) if you expect more than one matching element, e.g. in a list. - Use
queryBy*only when element should not exist to use it together with e.g.not.toBeOnTheScreen()matcher.
Avoid using queryAllBy* in regular tests, as it provides no assertions on the number of matching elements. You may still find it useful when building reusable custom testing tools.
Query predicate
The query predicate describes how you decide whether to match the given element.
Idiomatic query predicates
Choosing the right query predicate helps express test intent and makes tests resemble how users interact with your code (components, screens, etc.), following our Guiding Principles. Most predicates also promote proper accessibility props, which add a semantic layer on top of an element tree composed primarily of View elements.
Use query predicates in the following order of priority:
1. By Role query
The *ByRole predicate starts with the semantic role of the element and can be narrowed down with additional options. React Native has two role systems: the web/ARIA-compatible one based on role prop and the traditional one based on accessibilityRole prop. You can use either.
In most cases, you need to set accessibility roles explicitly (or your component library can set some of them for you). These roles allow assistive technologies (like screen readers) and testing code to understand your view hierarchy better.
Some frequently used roles include:
alert- important text to be presented to the user, e.g., error messagebuttoncheckbox&switch- on/off controlsheading(header) - header for content section, e.g., the title of navigation barimg(image)linkmenu&menuitemprogressbarradiogroup&radiosearchbox(search)slider(adjustable)summarytablist&tabtext- static text that cannot changetoolbar- container for action buttons
Name option
Frequently, you will want to add the name option, which will match both the element's role and its accessible name (= element's accessibility label or text content).
Here are a couple of examples:
- start button:
getByRole("button", { name: "Start" }) - silent mode switch:
getByRole("switch", { name: "Silent Mode" }) - screen header:
getByRole("header", { name: "Settings" }) - undo menu item:
getByRole("menuitem", { name: "Undo" }) - error messages:
getByRole("alert", { name: /Not logged in/ })
2. Text input queries
Querying TextInput elements presents a unique challenge as there is no separate role for TextInput elements. There is a searchbox/search role, which can be assigned to TextInput, but it should be only used in the context of search inputs, leaving other text inputs without a role to query with.
Therefore, you can use the following queries to find relevant text inputs:
*ByLabelText- will match the accessibility label of the element. This query will match any host elements, includingTextInputelements.*ByPlaceholderText- will match the placeholder ofTextInputelement. This query will match onlyTextInputelements.*ByDisplayValue- will the current (or default) value ofTextInputelement. This query will match onlyTextInputelements.
3. Other accessible queries
These queries reflect the apps' user experience, both visual and through assistive technologies (e.g. screen reader).
These queries include:
*ByText- will match the text content of the element. This query will match onlyTextelements.*ByLabelText- will match the accessibility label of the element.*ByHintText- will match the accessibility hint of the element.
4. Test ID query
As a final predicate, you can use the testID prop to find relevant views. Using the *ByTestId predicate offers the most flexibility, but at the same time, it does not represent the user experience, as users are not aware of test IDs.
Note that using test IDs is common in end-to-end testing due to various issues with querying views through other means in that specific context. For integration and component tests, use the recommended RNTL queries to make tests more reliable and resilient.
