Another useful tactic is to generate a trace of what happened so you can puzzle away. Inserting console.log statements is tedious and makes your code look a little ugly. Puppeteer offers a couple of methods to trace the actions and to dynamically turn off tracing.
In uitest.js, add this code:
function frameEvent(evtname, frame) {
console.log(`${evtname} ${frame.url()} ${frame.title()}`);
}
function ignoreURL(url) {
if (url.match(/\/assets\//) === null
&& url.match(/\/socket.io\//) === null
&& url.match(/fonts.gstatic.com/) === null
&& url.match(/fonts.googleapis.com/) === null) {
return false;
} else {
return true;
}
}
...
before(async function() {
browser = await puppeteer.launch({ slomo: 500 });
page = await browser.newPage();
page.on('console', msg => {
console.log(`${msg.type()} ${msg.text()} ${msg.args().join(' ')}`);
});
page.on('error', err => {
console.error(`page ERROR ${err.stack}`);
});
page.on('pageerror', err => {
console.error(`page PAGEERROR ${err.stack}`);
});
page.on('request', req => {
if (ignoreURL(req.url())) return;
console.log(`page request ${req.method()} ${req.url()}`);
});
page.on('response', async (res) => {
if (ignoreURL(res.url())) return;
console.log(`page response ${res.status()} ${res.url()}`);
});
page.on('frameattached', async (frame) => frameEvent('frameattached', await frame));
page.on('framedetached', async (frame) => frameEvent('framedetached', await frame));
page.on('framenavigated', async (frame) => frameEvent('framenavigated', await frame));
await page.goto(process.env.NOTES_HOME_URL);
});
...
That is, the Page object offers several event listeners in which we can output details about various events, including HTTP requests and responses. We can even print out the HTML text of the response. The ignoreURL function lets us suppress a few select URLs so we're not inundated with unimportant requests and responses.
You can trace Puppeteer itself using its DEBUG environment variable. See the README for more information: https://github.com/GoogleChrome/puppeteer.