query / test starts after two rerenders of the view
See original GitHub issueDescribe the bug
Hi, I’m not sure if it’s a bug or a question, but it feels for me that it is working the wrong way. I want to test a simple thing in one of my views, which is a loader appearance.
View looks like this:
export const TheView: React.FC<Props> = (props) => {
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
setIsLoading(true);
performWhateverPromiseOrRequest()
.finally(() => {
setIsLoading(false);
});
}
}
}, []);
return (
<View style={styles.container}>
{isLoading && <View testID="activityIndicator" style={styles.activityIndicator} />}
{...theRestOfTheView}
</View>
);
};
And the test looks like this:
it('should show the loader at the beginning if coordinates arent defined', async () => {
// mocks
const { findByTestId, queryByTestId } = render({
initialState
});
console.log('here');
const loader = queryByTestId('activityIndicator');
await waitFor(() => expect(loader).not.toBeNull());
});
Please take a look at the console logs both in the view and the test. The result I get from them is:
console.log false
console.log true
console.log here
console.log true
console.log true
console.log false
It looks like the view is being rerendered twice before the query / test even begins. This is the snippet from the render.js file from the lib:
function render(component, {
wrapper: Wrapper,
createNodeMock
} = {}) {
const wrap = innerElement => Wrapper ? /*#__PURE__*/React.createElement(Wrapper, null, innerElement) : innerElement;
const renderer = renderWithAct(wrap(component), createNodeMock ? {
createNodeMock
} : undefined);
const update = updateWithAct(renderer, wrap);
const instance = renderer.root;
(0, _cleanup.addToCleanupQueue)(renderer.unmount);
return { ...(0, _getByAPI.getByAPI)(instance),
...(0, _queryByAPI.queryByAPI)(instance),
...(0, _findByAPI.findByAPI)(instance),
...(0, _a11yAPI.a11yAPI)(instance),
update,
container: instance,
rerender: update,
// alias for `update`
unmount: renderer.unmount,
toJSON: renderer.toJSON,
debug: debug(instance, renderer)
};
}
and it seems like I’m right - I can see render
and update
methods called.
Expected behavior
I’d like the “hear” console.log to appear before any other console.log so that I can actually wait for things that happen from the beginning of the tested component’s lifecycle.
Steps to Reproduce
Just implement a similar code, put the console logs in the same places and see what happens.
Versions
@testing-library/react-native: ^7.2.0 => 7.2.0 react: 17.0.2 => 17.0.2 react-native: 0.67.2 => 0.67.2 react-test-renderer: 17.0.2 => 17.0.2
Issue Analytics
- State:
- Created 2 years ago
- Comments:6
Top GitHub Comments
@pierrezimmermannbam So I think I didn’t catch that properly. Understood. Thank you for your time (again) and explanations. 😉
@wmatyjanomtek yes I think it doesn’t matter, it is shown instantaneously to the user. All synchronous code run in useEffects will be completed before your first query so there’s no need to wait for them to be finished, you should only use waitFor when promises are involved. Also if there are timeouts then you should use jest fake timers api
In addition to what I said earlier, here is the description of the act util from react-test-renderer
The act util ensures that all useEffects will be run when udpating a component/hook state in a test to match better the user’s experience so it’s definitely the intended behavior