DEV Community

Cover image for Testing library awaiting queries
Chris Bongers
Chris Bongers

Posted on • Originally published at daily-dev-tips.com

Testing library awaiting queries

So far, we have mainly used direct queries to find elements.
Sometimes you could have a query that we need to be waited for.

Some examples might be:

  • Element fades in
  • Element only shows after user interaction
  • Element might disappear after a user action

Using the findBy queries

The easiest way to deal with this is using the findBy queries.
They are a combination of getBy and waitFor.

Let's say we have some user interaction on a button.
Once we click, we need to wait for the element to re-render with the new text.

const button = screen.getByRole('button');
button.click();
await screen.findByText('Clicked once');
button.click();
await screen.findByText('Clicked twice');
Enter fullscreen mode Exit fullscreen mode

As you can see, the two latter ones have a check based on the awaiting promise.

Remember that the testing library is only the selector helper, so we still need to use some testing library, Jest, to check if this is true.

const button = screen.getByRole('button');
button.click();
expect(await screen.findByText('Clicked once')).toBeInTheDocument();
button.click();
expect(await screen.findByText('Clicked twice')).toBeInTheDocument();
Enter fullscreen mode Exit fullscreen mode

Using waitFor

Sometimes we cannot leverage findBy queries, maybe because we need to await some function to execute.

Or perhaps we have to await some time to pass before we can do the next thing.

This is precisely where the waitFor function comes in handy. We can wrap some code with this.
For example, wrapping a promise with waitFor will wait until the promise throws a rejection.

await waitFor(() => {
  expect(mockCall).toHaveBeenCalledTimes(1);
});
Enter fullscreen mode Exit fullscreen mode

In the above example, we wait for an API to be called, and only once it's called once will we pass this step.

We can also pass some options to this waitFor:

  • container: The HTML element, by default, the global document
  • timeout: Default 1000ms
  • interval: Default 50ms
  • onTimeout: Prints the container and error in the console, but you can override this
  • mutationObserverOptions: The actual behavior that checks for changes

Using the waitForElementToBeRemoved

As we now have seen the waitFor in action, we can also leverage waitForElementToBeRemoved.

As the name suggests, it can wait for elements to be removed.
It has the same call signature and options as waitFor.

It can take one, or multiple elements will wait to be removed.

waitForElementToBeRemoved(document.queryByRole('button')).then(() =>
  console.log('Button no longer in DOM')
);
Enter fullscreen mode Exit fullscreen mode

Or in the case of multiple:

waitForElementToBeRemoved(document.queryAllByRole('img')).then(() =>
  console.log('All images are gone')
);
Enter fullscreen mode Exit fullscreen mode

And that's how we can wait for elements to show up, be modified, or be removed from the DOM.

Thank you for reading, and let's connect!

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter

Top comments (0)