-
-
Notifications
You must be signed in to change notification settings - Fork 44
find* methods does not work as expected? #82
Comments
Hi, thanks for the issue! Without some more code to work off of it'll be a little hard to debug unfortunately, but we'll give it a shot. My guess is Then when it comes to the example from the site, it probably needs updated 😬I should look into that. |
After poking around the code it seems that For the code example I just used the code on the README.md and it fails on the async method. |
I tried a couple of permutations here: import React, { useState } from 'react';
import { Button, Text, View } from 'react-native';
import {
fireEvent, render, wait, waitForElement
} from '@testing-library/react-native';
function Example() {
const [show, setShow] = useState(false);
return (
<View>
<Button
testID="button"
onPress={() => setTimeout(setShow(!show), 500)}
>
Press this to change state
</Button>
{ show && <Text testID="test">asdf</Text> }
</View>
);
}
test('test by queryByTestId', async () => {
const { queryByTestId, getByTestId } = render(
<Example />,
);
fireEvent.press(getByTestId('button'));
await wait(() => expect(queryByTestId('test')).toBeTruthy()); // works
});
test('test by waitForElement', async () => {
const { queryByTestId } = render(
<Example />,
);
const element = await waitForElement(() => queryByTestId('test'));
expect(element).toBeTruthy(); // does not work
});
test('test by findByTestId', async () => {
const { findByTestId } = render(
<Example />,
);
const element = await findByTestId('test');
expect(element).toBeTruthy(); // does not work
}); Maybe this could help? |
The problem is that the async helpers expect that on their first try they’re going to throw because the element isn’t there. If the element is already in the DOM, just use getBy or queryBy. Only use findBy if you expect the element to not be there and appear asynchronously |
I see, but on the example I have provided, the item with the testID of |
There are multiple issues with your examples. Your first test passes because you aren’t making any assertions, so there’s nothing to fail. Also a queryBy never throws an error, it just returns null, so nothing would be broken in any case, it just does nothing. Your second and third fail because you never press the button that makes the element with the test id you’re looking for show. You should use getBy, not queryBy, when making async assertions like waitForElement because as I said, the async helpers rely on errors being thrown and queryBy won’t throw errors, it just returns null or an empty array. Lastly, the whole second and third tests are probably acting a little buggy because the onPress function is probably not right. It should be I’m going to go ahead and close this because I’m confident there’s no bug in the library itself, these helpers work for a lot of folks every day and we have a lot of tests that double check this behavior. I’m sorry for the confusion on the example, I’d encourage you to open an issue or even a PR over there if you’d like to fix the examples. If you’re looking for more help getting started, I’d check out the testing library spectrum chat or stack overflow, the difference in query types and the way queries work are generic testing library questions, they’re not specific to react native. The way they work for us are the same way they work in all of the other implementations. Good luck! |
Hi, I would like to point out that for the first test, if I were to replace the wait with the following: I have also updated the You are right about the incorrect tests for the 2nd and 3rd, and I have updated them to the following: test('test by waitForElement', async () => {
const { queryByTestId, getByTestId } = render(
<Example />,
);
fireEvent.press(getByTestId('button'));
const element = await waitForElement(() => queryByTestId('test'));
expect(element).toBeTruthy(); // does not work
});
test('test by findByTestId', async () => {
const { findByTestId, getByTestId } = render(
<Example />,
);
fireEvent.press(getByTestId('button'));
const element = await findByTestId('test');
expect(element).toBeTruthy(); // does not work
}); and both still does not work. Could you have another look at this? |
Hi, I managed to solve this issue by disabling I will do a PR to update the README so that other people will not fall into the same problem. BTW you are incorrect on import React, {useState} from 'react';
import {Button} from 'react-native';
import {render, fireEvent} from '@testing-library/react-native';
const TestComponent = () => {
const [show, setShow] = useState(false);
return (
<div>
<Button
testID="button"
onPress={() => setTimeout(() => setShow(!show), 500)}
>
Press Me
</Button>
{show && <p testID="test">asdf</p>}
</div>
);
};
test('test by queryByTestId', async () => {
const {findByTestId, getByTestId} = render(<TestComponent />);
fireEvent.press(await findByTestId('button'));
const element = await findByTestId('test');
expect(element).toBeTruthy();
}); Thanks for your help! |
react-native
native-testing-library
version: 5.0.1jest-preset
: @testing-library/react-nativereact-native
version: 16.12.0node
version: 11Relevant code or config:
What you did:
Hi, I am trying to use the
find*
methods to attempt to wait for an element to appear. The second block works but the first one doesn't. Shouldn't both be equivalent?What happened:
I got the error here:
: Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.Error:
Reproduction:
In fact, I wasn't able to run the async method in the README - I get this error:

Problem description:
Both methods should work similarly because the Promise in the
find
implementation should resolve once theget*
returns trueCan you help us fix this issue by submitting a pull request?
I can try if I have a direction how to fix this!
The text was updated successfully, but these errors were encountered: