How to check if a Puppeteer Page is currently in navigation state?

Viewed 859

I'm writing some wrapper on top of Puppeteer. I have a general "click" function, and a "getHtml" one:

class Page {
    
        ....

    async click(selector: string) {

        await this.context.evaluate((querySelector, text) => {

            const elem = document.querySelector(querySelector) as HTMLInputElement;

            if (elem) {

                elem.click();
            }

        }, selector);
    }

    async getHtml() {//

        const html = await this.context.evaluate(() => {
            return document.querySelector('html')?.innerHTML;
        })

        return html;
    }
}

As you can see, click() function just receives a querySelector , and then clicks whatever element is found.

Problem is, that if this element click causes navigation, the subsequent operations might encounter this error:

Execution context was destroyed, most likely because of a navigation

For example, if the client code does something like this:

const page = new Page(...)
...

await page.click('someSelector')//If this selector matches a link, navigation is triggered.

await page.getHtml()//Then there is an Error

Is there any way, to check if there is a pending navigation, so that i could conditionally wait for it, within various functions?

I cannot just waitForNavigation by default, within the click function, because this will cause the code to hang, in case there was no navigation caused by the click.

1 Answers

Maybe a workaround like this can help?

const [_, navigation] = await Promise.allSettled([
  elem.click(),
  page.waitForNavigation(),
]);

if (navigation.status === 'fulfilled') /* There was navigation. */;
else /* There was timeout, no navigation. */;
Related