Monika Mateeva
Monika Mateeva

Reputation: 181

How to properly test if a Toast has been shown in react native using native base?

I am trying to write a test that checks if the screen is showing a Toast with an error message. The test passes, but there is a warning:

 console.error
    Warning: You called act(async () => ...) without await. 
This could lead to unexpected testing behaviour, interleaving multiple act calls 
and mixing their scopes. You should - await act(async () => ...);

The screen is working fine, I am just learning how to write tests. This is my test:

it('shows error correctly', async () => {
    mockAxios.get.mockRejectedValueOnce(new Error('Async error'))
    const { queryByText } = renderWithRedux(<DiscoverScreen />)
    await waitFor(() => {
        expect(queryByText(ErrorMessages.GeneralErrorToast)).not.toBeNull()
    })
    
    await waitForElementToBeRemoved(() => queryByText(ErrorMessages.GeneralErrorToast), { timeout: 5000 })
})

What am I not doing right? Definitely there is an issue with react native testing, because there are problems for certain async querying, especially when you have several of them. I found that here: https://github.com/callstack/react-native-testing-library/issues/379#issuecomment-720734366

I am using native base for showing the Toast, which is using Animated I think. Should I use jest.useFakeTimers() and how?

Upvotes: 1

Views: 3001

Answers (1)

Monika Mateeva
Monika Mateeva

Reputation: 181

After researching how the Toast in native base works (this could be done when you open the source code in github - https://github.com/GeekyAnts/NativeBase/blob/master/src/basic/ToastContainer.js), I found that it uses Animated.timing.

So I had to find out how to deal with react native animations in tests. That article had a solution that worked for me: https://medium.com/@joncardasis/react-native-how-to-test-components-implementing-animated-with-jest-8cabb5fc2730

After I added the code in my jest setup file, this is how my test looks:

global.withAnimatedTimeTravelEnabled(async () => {
    const { queryByText } = renderedComponent

    await waitFor(() => {
        expect(queryByText(ErrorMessages.GeneralErrorToast)).not.toBeNull()
    })

    global.timeTravel(Constants.ErrorToastDelay)
    expect(queryByText(ErrorMessages.GeneralErrorToast)).toBeNull()
})

It works and now the test passes with no warnings!

One little adjustment in my jest configuration was also missing. I had to add this:

"testEnvironment": "jsdom"

I hope this could help someone else, too!

Upvotes: 1

Related Questions