Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Puppeteer page.waitForNavigation() timeout error handling

Using puppeteer, i open up a page when i enter a value - it outputs the result.

await page.click('button[class="button form-button rs-gcbalance-btn"]')

await page.waitForSelector('div[class="small-4 large-4 rs-gcbalance-result-num-col').catch(err => console.log(err))

await page.evaluate((card) => {
    console.log(card + " - " + document.querySelectorAll('div[class="small-4 large-4 rs-gcbalance-result-num-col"]')[1].querySelector('span').innerHTML)
}, card)

But that works correctly only if the value on enter is valid. If it's not, it would throw an error, but without any network activity or load event.
That means, that if the value is incorrect, the element i'm waiting for won't appear and will throw an error, closing the program.

Navigation Timeout Exceeded: 30000ms exceeded

The question is: how to handle the error, so if it throw a timeout error, i can catch it and call another function?

like image 299
almarc Avatar asked Oct 09 '18 08:10

almarc


People also ask

How do you handle timeout error in puppeteer?

A simple workaround is to override the default timeout value, setting the new value to _0_ and passing a “waitUntil”: “load” parameter in the options object in the Puppeteer goto() method.

What does Page waitForNavigation do?

It fills the login form, submits the login form, waits for the form to be submited and then redirects to dashboard. On the server it works fine if I remove await page. waitForNavigation(); from the code and I get redirected to dashboard.

How do you increase navigation timeout in puppeteer?

To set navigation timeout with Node. js Puppeteer, we can call goto with the timeout option. await page. goto(url, { waitUntil: 'load', timeout: 0 });

How do I change the default timeout in puppeteer?

By default, the timeout is 30 sec in puppeteer. But we can change it according to the requirement. page. setDefaultTimeout(ms) is used to change the default timeout.


3 Answers

The try catch block is a solution.

However, on the accepted answer all errors are silenced!!

You should only catch the Puppeteer TimeOut errors.

try {
  await page.waitForSelector('.foo');
} catch (e) {
  if (e instanceof puppeteer.errors.TimeoutError) {
    // Do something if this is a timeout.
  }
}

References: https://devdocs.io/puppeteer/

like image 197
Victor Avatar answered Oct 17 '22 17:10

Victor


Just wrap it in try catch block:

try {
  await page.waitForSelector('#element', { timeout: 1000 });
  // do what you have to do here
} catch (e) {
    console.log('element probably not exists');
}

Here is a fully working example:

const puppeteer = require('puppeteer');

const html = `
<html>
    <body>
        <div id="element">element inner html</div>
    </body>
</html>`;

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto(`data:text/html,${html}`);

  try {
    await page.waitForSelector('#element-not-exists', { timeout: 1000 });
    const element = await page.$('#element-not-exists');
    console.log(await (await element.getProperty('innerHTML')).jsonValue());
  } catch (e) {
    console.log('element probably not exists');
  }
  await browser.close();
})();
like image 7
Everettss Avatar answered Oct 17 '22 17:10

Everettss


you can use waitForNavigation method after button click and attach a catch block like below to handle navigation timeout error in case value entered is incorrect and navigation does not happens

page.waitForNavigation({waitUntil:"domcontentloaded"}).catch(error => {
    // handler code here
});
like image 1
Dhiraj Kumar Avatar answered Oct 17 '22 18:10

Dhiraj Kumar