I am new to the world of unit testing and I have just began to write tests for my React Native (Expo) app. After doing research I have finally landed in using Jest and React Native Testing Library.
Consider the following that uses the AppLoading component.
const App: React.FC = () => {
const [resourcesHasLoaded, setResourcesHasLoaded] = useState<boolean>(false);
const cacheResources = useCallback(async (): Promise<any> => {
const images = [require('./assets/icon.png')];
const cacheImages = images.map((image) => {
return Asset.fromModule(image).downloadAsync();
});
return Promise.all([cacheImages]);
}, []);
if (resourcesHasLoaded) {
return <Text>Hello world</Text>;
}
return (
<AppLoading
startAsync={cacheResources}
onError={console.warn}
onFinish={() => setResourcesHasLoaded(true)}
/>
);
};
When running my test, that looks like this:
describe('App.tsx', () => {
it('should be able to render', async () => {
render(<App />);
});
});
I end up with the following error (although, test passes):
Warning: An update to App 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 */
So, I wrapped my `render` in with `act` the following way:
act(() => {
render(<App />);
});
... which resulted in the same error.
If I however wrap the onFinish-callback in my component the following way the test passes without warnings.
onFinish={() => act(() => setResourcesHasLoaded(true))}
But do I really want to pollute my React Component with test-specific functions? I saw no example of this, so I can only assume that this is bad practice.
Any suggestions here?
Update
I got the suggestion to use waitFor after my render by @Estus Flask in my comments. That did the trick... the test now passes.
https://callstack.github.io/react-native-testing-library/docs/api/#waitfor
describe('App.tsx', () => {
it('should be able to render', async () => {
const { findByText } = render(<MyApp />);
await waitFor(() => findByText('Hello world'));
});
});