15

My componentDidMount() fires off a call to an async function but depending on the result of that function, it might not result in any DOM change. Is there any way I can wait for the function to complete in my tests?

Here's an example - the click button is initially disabled. If the async function returns true, the click button should be enabled:

    myAsyncFunction.mockImplementation(() => true);
    const {queryByText} = render(<Component />);
    const button = queryByText("Click");
    expect(button).toBeDisabled();
    await waitFor( () => expect(button).not.toBeDisabled() );
    expect(button).not.toBeDisabled();

But if it returns false the button stays disabled:

    myAsyncFunction.mockImplementation(() => false);   // async returning different value
    const {queryByText} = render(<Component />);
    const button = queryByText("Click");
    expect(button).toBeDisabled();
    await waitFor( () => {} );                       //        <== **** CODE SMELL ****
    expect(button).toBeDisabled();

The second test does actually work but the empty waitFor() is considsered bad practice. is there any way to avoid this?

Andy
  • 10,412
  • 13
  • 70
  • 95
  • You probably want to fire: `await wait();` after rendering component: ```const {queryByText} = render(); await wait(); ``` – Branislav Lazic Apr 02 '20 at 14:01
  • yes, wait() is now deprecated and I beleive that `waitFor(()=>{});` is the new equivalent. However I read somewhere (I think it was in the previous version of the react-testing-library docs) that an empty wait() was considered bad practice and you should wait for something concrete instead – Andy Apr 04 '20 at 10:23

1 Answers1

30

In the docs for waitFor, it is recommended to just wait for your async function .toHaveBeenCalled like so

await waitFor(() => expect(mockAPI).toHaveBeenCalledTimes(1))
Koleok
  • 511
  • 4
  • 4
  • 1
    Aha! thanks, that text has been updated since I asked the question :-). As I understand it, this would wait for the function to be called, but not wait for the promise to be resolved. However, since it's explicit in the docs now, I guess it's OK – Andy Apr 21 '20 at 07:03
  • What is 'mockAPI' here? Ie, if one is using https://mswjs.io/ as recommended by ReactTestingLibrary, would you pass in the return value of setupServer? (I tried but got confusing results which don't indicate whether it's working or not.) – Byofuel Oct 22 '21 at 20:47
  • 1
    This is a direct quote from the [testing-library docs](https://testing-library.com/docs/dom-testing-library/api-async#waitfor), in that context `mockAPI` is the name they are using to refer to _any asynchronous function you might need to wait for_ before your expectation can be asserted. – Koleok Oct 25 '21 at 18:51