Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does a test fail when using findBy but succeed when using waitfor?

Using react-testing-library, the following test works:

it( 'renders popular search terms, with links to search urls', () => {
      waitFor(() => {
        const popularSearch = screen.getByText( Copywriting.buyer.shop.popularSearch, {}, { timeout: 5000 })
        expect( popularSearch ).toBeInTheDocument()

        const popularSearchPills = screen.findAllByTestId( 'pill' )
        expect( popularSearchPills.length ).toBeGreaterThan( 0 )

        const hrefs = popularSearchPills.map( pill => pill.href )
        expect( hrefs.filter( urlIsValidAndNotBaseUrl )).not.toHaveLength( 0 )
      })
    })

But the following test used to work, but now fails:

it( 'renders popular search terms, with links to search urls', async () => {
      const popularSearch = await screen.findByText( Copywriting.buyer.shop.popularSearch )
      expect( popularSearch ).toBeInTheDocument()

      const popularSearchPills = await screen.findAllByTestId( 'pill' )
      expect( popularSearchPills.length ).toBeGreaterThan( 0 )

      const hrefs = popularSearchPills.map( pill => pill.href )
      expect( hrefs.filter( urlIsValidAndNotBaseUrl )).not.toHaveLength( 0 )
    })

Why would the two code snippets function differently? I thought findby was supposed to be a wrapper for waitfor.

Note: what's happening under the hood of the rendered component is that we dispatch an action which calls a saga, the saga calls fetch, which returns a piece of data, the saga then calls another action with the data as a payload, triggering a reducer that saves the data to the store. The view should then update to include the element with Copywriting.buyer.shop.popularSearch.

Is there any reason, on principle, why the two tests should have different outputs?

like image 749
Davin Shaun Avatar asked May 22 '20 07:05

Davin Shaun


People also ask

What does await waitFor do?

This allows you to waitFor things that must be checked asynchronously.


1 Answers

That could be because the default timeout is 1000ms (https://testing-library.com/docs/dom-testing-library/api-queries#findby) while in your first test you manually specify a 5000ms timeout.

You will also notice in the docs that the findBy* methods accept the waitForOptions as their third argument.

So you should

const popularSearch = await screen.findByText(Copywriting.buyer.shop.popularSearch, undefined, {
  timeout: 5000
});

Now the two tests would be identical.

like image 169
Gabriele Petrioli Avatar answered Oct 06 '22 19:10

Gabriele Petrioli