I'm trying to automatically login to a website using puppeteer, with the following script:
const puppeteer = require('puppeteer');
async function logIn(userName, password) {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://foo.com'); //anonymized host
await page.type('[name="Email"]', userName);
await page.type('[name="Pass"]', password);
page.click('[type=submit]');
await page.waitForNavigation({waitUntil: 'load'});
}
logIn('[email protected]')
The await
for waitForNavigation
eventually times out at 30 seconds. Launching puppeteer with {headless: false}
on the same script, I can check in chromium's devtools that document.readyState
evals to "complete" way before the timeout thresold interval. Am I doing something wrong?
According to Puppeteer documentation proper pattern for clicking on submit and waiting for navigation is like this:
await Promise.all([
page.waitForNavigation({ waitUntil: 'load' }),
page.click('[type=submit]'),
]);
Adding to the answer of Everettss, I would like to present a more modern code. Basically instead of doing any operation and calling waitFornavigation
, the motive is to do the other way around. Something like this:
//Get the promise which isn't resolved yet
const navigationPromise = page.waitForNavigation();
//Perform the activity (Click, Goto etc). Note that the link is any valid url
await page.goto(link);
//wait until the navigationPromise resolves
await navigationPromise;
This helps to avoid race condition as per this discussion
This code makes use of async/await which is much more readable than promise-based code
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