Puppeteer: Wait until elementHandle is no longer attached to the DOM

Viewed 829

So, I run into this problem where there are some spinners rendered here and there and I want to wait until the spinners are no longer attached in the DOM.

Don't know too much JS to do so, but in Selenium you can use a predicate like:

Wait.Until(driver => driver.findElements(By.Xpath("XPATH")).Count < 0).

So far what I have accomplished is the following:

    async fillSearch(value: string) {
            await this.searchInput.then(x => x.click({ clickCount: 3 }));
            await this.page.keyboard.press("Backspace");
            await this.searchInput.then(x => x.type(value));
            ...//HERE I HAVE TO WAIT FOR THE SPINNER TO GO...
        }

this.searchInput is a Promise<ElementHandle> retrieved by page.$x("xpathOfInput").

I have a prop called this.spinners retrieving a Promise<ElementHandle[]> so when the Promise it's resolved I can get the lenght of the array and know if any element was founded on the DOM.

So the question would be:

Is there a way to use something like page.waitFor() to wait for the promise to get resolved and afterwards compares if spinners.length < 0 and wait until that happens?

I supose there must be a way to achieve the same with a predicate on the waitFor but so far I can't manage to pull it out...

1 Answers

Using page.waitForXPath

The easiest way would be to use page.waitForXPath with the option hidden set to true:

await page.waitForXPath('XPATH', { hidden: true });

This will wait until the element is not present in the DOM anymore or hidden (via CSS).

Alternative: page.waitForFunction

Alternatively, you can use page.waitForFunction to wait until a function that you provide returns true. By using document.evaluate to evaluate an XPath expression you can then wait until your condition resoles to true.

Using an existing variable

As you already have the element in a variable, you can use page.waitForFunction and pass the element as args:

await page.waitForFunction(element => element.parentNode === null, {}, spinnerElement);

You might need to change the checking function depending on how the node is removed.

Related