There are multiple ways of getting an element's text content: getByText
vs findByText
vs queryByText
.
Sometimes I get confused about which one to use.
I have the following example in react-native:
it('should render children', () => {
const mockedChildComponentTxt = 'Children are rendered';
const { getByText, findByText, queryByText } = render(
<MyProvider>
<div>{mockedChildComponentTxt}</div>
</MyProvider>,
);
expect(queryByText(mockedChildComponentTxt)).toBeTruthy()
});
queryByText
and getByText
are failing, but findByText
works.
debug()
resulting in:
<RNCSafeAreaView
onInsetsChange={[Function anonymous]}
style={
Object {
"flex": 1,
}
}
>
<div>
Children are rendered
</div>
</RNCSafeAreaView>
Why findByText
works in the above example, but getByText
and queryByText
fail?
findBy
queries return a promise which resolves when a matching element is found. The promise is rejected if no elements match or if more than one match is found after a default timeout of 1000 ms. If you need to find more than one element, then usefindAllBy
.
getBy
queries return the first matching node for a query, and throw an error if no elements match or if more than one match is found. If you need to find more than one element, then usegetAllBy
.
queryBy
queries return the first matching node for a query, and return null if no elements match. This is useful for asserting an element that is not present. This throws if more than one match is found (usequeryAllBy
instead).
Here in your example the rendered component contains the text "Children are rendered," but it seems that it might not be available in the DOM immediately.
it's possible that the element is added to the DOM asynchronously after rendering, which is why getByText
and queryByText
are not able to find it immediately. however, findByText
works because it waits for the element to appear in the DOM due to its asynchronous nature
findBy
queries return a promise which resolves when a matching element is found.
and when it finds the element, the test passes.