Testing library awaiting queries

I'm a full-stack developer from South Africa 🇿🇦. I love writing about JavaScript, HTML and CSS.
Search for a command to run...

I'm a full-stack developer from South Africa 🇿🇦. I love writing about JavaScript, HTML and CSS.
No comments yet. Be the first to comment.
Most of you know me for my consistency, a golden arrow in my blog series. I've written 1000 articles in 1008 days! Almost an article a day, and my honeymoon was the only holiday I ever took. I'm super proud of this achievement; it has been a fantasti...

It's not the first time I'll be talking about community. I think it's an essential aspect of any successful tool. This shows in my previous explorations of Astro, Medusa, and now Vendure as well. All these products thrive in a super open, welcoming, ...

The cool part about Vendure is how easy it is to set up and how abstract each layer is. Basically, we get the following elements: External database Server Worker Admin UI Frontend While this is amazing, it also brings a bit of complexity when it co...

The previous article looked at customizing Vendure on a data and process level. In this article, we'll look at customizing emails, as they are often a big part of a webshop system. We'll be looking at two different layers of customization for customi...

Even though Vendure is a pretty significant project out of the box, in some cases, we might want to go in and modify some elements to work to our specific use case. In this article, I'll take a high-level look at some elements we can customize within...

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:
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');
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();
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);
});
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 documenttimeout: Default 1000msinterval: Default 50msonTimeout: Prints the container and error in the console, but you can override thismutationObserverOptions: The actual behavior that checks for changesAs 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')
);
Or in the case of multiple:
waitForElementToBeRemoved(document.queryAllByRole('img')).then(() =>
console.log('All images are gone')
);
And that's how we can wait for elements to show up, be modified, or be removed from the DOM.
Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter