I'm using react-native-testing-library
and after upgrading react-navigation
from 4 to 5, I followed these instructions: https://callstack.github.io/react-native-testing-library/docs/react-navigation to upgrade most of my test suite.
So far so good. The crux here is basically to wrap your tests in a NavigationContainer
so my components have access to those hooks that previously came from react-navigation-hooks
.
This works fine when my tests are synchronous, but as soon as I add the async
keyword to the test function, I get the following warning:
console.error
Warning: An update to ForwardRef(NavigationContainer) inside a test was not wrapped in act(...).
When testing, code that causes React state updates should be wrapped into act(...):
act(() => {
/* fire events that update state */
});
/* assert on the output */
This ensures that you're testing the behavior the user would see in the browser. Learn more at https://reactjs.org/docs/test-utils.html#act
in ForwardRef(NavigationContainer)
There are plenty of tests that I run synchronously and which succeed. But in some components, I do run some async logic to get the desired result.
From what I understand, I should wrap any async code in an act
call. However, even in this case, I can't get rid of this error.
I went ahead to try and narrow down the issue. Now, all I do is render the wrapped component like this:
test('a simple test', async () => {
const component = (
<NavigationContainer>
<AppNavigator />
</NavigationContainer>
);
const {queryByText} = render(component);
expect(queryByText('test')).toBeNull();
});
And I'm still running into the same issue. Be aware that the actual test succeeds, only that I'm still getting this console error.
Next, I tried to wrap the render
call in act
and waitForElement
, because that's what I'm supposed to do when running async logic. But it seems that the async code here is executed after the rendering happens.
So I went on to investigate which part of NavigationContainer
is responsible for firing the async logic responsible for the error, and it seems that this bit of code (line 49-51) does something interesting:
const [isReady, initialState = rest.initialState] = useThenable(
getInitialState
);
getInitialState
is the result of destructuring the return value of the useLinking
call some lines before (43-47). Without going into further detail, getInitialState
is wrapped inside a promise in there, so it becomes "thenable".
Now, if I uncomment the useThenable
, the console error goes away. But obviously that's not something I can easily achieve from outside this file. So I'm a bit stuck here because I don't know how to write my test code in an async way without running into this error all the time, and I don't feel like ignoring or suppressing it is a good idea either.
Any help would be appreciated.
await act(async () => {})
right after the render call helped me get rid of the error. – Willie