Skip to content

Instantly share code, notes, and snippets.

@dgozman
Created October 2, 2020 04:35
Show Gist options
  • Save dgozman/d1c46f966eb9854ee1fe24960b603b28 to your computer and use it in GitHub Desktop.
Save dgozman/d1c46f966eb9854ee1fe24960b603b28 to your computer and use it in GitHub Desktop.
Playwright network settled helper

Network Settled

This helper waits for requests initiated by the action to finish. It is similar to waitUntil: 'networkidle' option, but is designed to work with any action, like click.

Example usage:

const waitForNetworkSettled = require('./networkSettled');

// Wait for network settled after navigation,
// account for two long-polling requests that never finish.
await waitForNetworkSettled(page, async () => {
  await page.goto('http://my-site.com', { waituntil: 'domcontentloaded' });
}, 2);

// Wait for images to load after clicking the button
// that loads some more images.
await waitForNetworkSettled(page, async () => {
  await page.click('text=Load more images');
});
// Set to true to print debug information.
const DEBUG = false;
module.exports = async function waitForNetworkSettled(page, action, longPolls = 0) {
let networkSettledCallback;
const networkSettledPromise = new Promise(f => networkSettledCallback = f);
let requestCounter = 0;
let actionDone = false;
const pending = new Set();
const maybeSettle = () => {
if (actionDone && requestCounter <= longPolls)
networkSettledCallback();
};
const onRequest = request => {
++requestCounter;
DEBUG && pending.add(request);
DEBUG && console.log(`+[${requestCounter}]: ${request.url()}`);
};
const onRequestDone = request => {
// Let the page handle responses asynchronously (via setTimeout(0)).
//
// Note: this might be changed to use delay, e.g. setTimeout(f, 100),
// when the page uses delay itself.
const evaluate = page.evaluate(() => new Promise(f => setTimeout(f, 0)));
evaluate.catch(e => null).then(() => {
--requestCounter;
maybeSettle();
DEBUG && pending.delete(request);
DEBUG && console.log(`-[${requestCounter}]: ${request.url()}`);
});
};
page.on('request', onRequest);
page.on('requestfinished', onRequestDone);
page.on('requestfailed', onRequestDone);
let timeoutId;
DEBUG && (timeoutId = setInterval(() => {
console.log(`${requestCounter} requests pending:`);
for (const request of pending)
console.log(` ${request.url()}`);
}, 5000));
const result = await action();
actionDone = true;
maybeSettle();
DEBUG && console.log(`action done, ${requestCounter} requests pending`);
await networkSettledPromise;
DEBUG && console.log(`action done, network settled`);
page.removeListener('request', onRequest);
page.removeListener('requestfinished', onRequestDone);
page.removeListener('requestfailed', onRequestDone);
DEBUG && clearTimeout(timeoutId);
return result;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment