Testing app containing AppLoading component

Viewed 473

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'));
        });
    });
0 Answers
Related