So I used a while loop so my test will run in a constant loop until my back-end will crash. I've implemented a try and catch(error) so any front-end crash the automation will refresh and keep running
while(true){
try{
await page.waitFor(selector)
await page.click(selector)
}
catch(error){
console.log("FE crashed with\n\n" + error + "\n\nRefreshing page and continuing profile switching")
await page.reload(page);
continue;
}}
So indeed any timeout error the automation refreshes the page and continuing the loop. but Im recieving a different crash error
(node:6535) UnhandledPromiseRejectionWarning: Error: Page crashed!
at Page._onTargetCrashed (/home/raymond/node_modules/puppeteer/lib/Page.js:170:24)
at CDPSession.Page.client.on.event (/home/raymond/node_modules/puppeteer/lib/Page.js:125:56)
at CDPSession.emit (events.js:182:13)
at CDPSession._onMessage (/home/raymond/node_modules/puppeteer/lib/Connection.js:200:12)
at Connection._onMessage (/home/raymond/node_modules/puppeteer/lib/Connection.js:112:17)
at _tickCallback (internal/process/next_tick.js:43:7)
at listOnTimeout (timers.js:294:7)
at processTimers (timers.js:268:5)
(node:6535) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
How can I handle this error?, if I refresh the page manually everything works fine. Thanks
Puppeteer Supported Browsers Puppeteer Supports Chromium-Based Browsers and Firefox.
Puppeteer is a Node. js library developed by Google that lets you control headless Chrome through the DevTools Protocol. It is a tool for automating testing in your application using headless Chrome or Chromebit devices, without requiring any browser extensions like Selenium Webdriver or PhantomJS.
Puppeteer is a Node library which provides a high-level API to control headless Chrome or Chromium over the DevTools Protocol. It can also be configured to use full (non-headless) Chrome or Chromium.
You are assuming, that the error happened because the page navigation failed. This might be the case, but it could also be a different error like a Protocol error. In a case like that, you cannot just reuse the page
object, but you first have to restart the browser.
Some time ago, I crawled roughly 400k pages for testing purposes. In total, I experienced 34 of these puppeteer crashes, where some unexpected error crashes the whole browser. To harden your code against these kind of crashes, you need a robust way to restart the browser.
Code Sample
let browser = await puppeteer.launch(/* .. */);
let page = await browser.newPage();
while(true) {
try {
// your code that might crash
} catch (err) {
try {
await page.reload(); // soft fix
} catch (recoveringErr) {
// unable to reload the page, hard fix
try {
await browser.close();
} catch (err) { // browser close was not necessary
// you might want to log this error
}
browser = await puppeteer.launch(/* .. */);
page = await browser.newPage();
}
}
}
Although this code might look horrendous with three nested try..catch
blocks, it does a good job of keeping your code running.
First, your original code is executed. If the initial problem happens, a page.reload
call is tried to fix the problem. In case this works, the loop will continue running. If that does not work, the browser will be restarted.
For restarting the browser, I recommend to first try to close the old browser. Although, this might likely fail, it clears all memory and correctly disposes the browser object. Depending on your use case, you might want to log the error or simply ignore it. After disposing the old browser object, you can restart the browser and the loop may continue.
Alternative
As an alternative, you could use my library puppeteer-cluster which has error handling build in. The library automatically restarts the browser in cases in which the page is not usable anymore. In addition, the library can run multiple pages in parallel (as you are trying to stress-test the server I'm assuming).
As per the official documentation, an 'error' event is emitted when the page crashes which can be used to do certain stuff basis the application.
page.on('error', err => { /*custom logic to handle the crash*/ });
For the above specific use case, you could go about doing something like this:
let browser = await puppeteer.launch();
let page = await getNewPage(browser);
while(true){
try{
if (page.isClosed()) {
page = await getNewPage(browser);
}
await page.waitFor(selector)
await page.click(selector)
}
catch(error){
console.log("FE error with\n\n" + error + "\n\nRefreshing page and continuing profile switching")
await page.reload();
continue;
}}
async function getNewPage(browser) {
let page = await browser.newPage();
page.on('error', err => {
if (!page.isClosed()) {
//Close page if not closed already
page.close();
}
}
return page;
}
Reference: page.on('error')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With