Martin Thompson
Martin Thompson

Reputation: 3755

Playwright Wait for Page to completely load and XHR / Ajax Calls complete

I have previously used Puppeteer in Node.js and I am now using Microsoft.Playwright in .Net

I have a need to wait until all XHR / Ajax requests have finished so that the page is in a truly "ready" state. Using timouts and delays is unreliable.

With Puppeteer I used a library Pending XHR Puppeteer https://www.npmjs.com/package/pending-xhr-puppeteer which was designed for this issue specifically

So in node.js I would load the page etc inside a warapper and then when needed I would just call

await pageWrapper.waitForAllXhrFinished()

I am assuming that behind the scenes it is keeping count of the ajax requests sent and returning the function once they have all returned.

Note: for one of my scenarios there are 2 XHR requests set and they are from exactly the same URL.

How can we achieve this in Playwright for .Net ?

Upvotes: 14

Views: 17016

Answers (3)

user7610
user7610

Reputation: 28879

I do agree with the comments that it's normally better to only wait for some locator to match, usually locator for the thing you want to click or assert on, and not to worry about the state of the rest of the page. This way gives you faster and more robust tests.

However, waiting for UI to enter a steady state has uses too. My usecase is taking screenshots that are to be used for product documentation. Rerunning the automation script updates my screenshots for a new version. I naturally want the screenshots be complete.

The Pupeteer and Playwright APIs are very similar. Not surprising, given that Playwright is a further evolution of Pupeteer, even by some of the original developers.

Looking at the Playwright docs, https://playwright.dev/docs/api/class-request, I see nothing in the pending-xhr-puppeteer code that should not work in Playwright. Edit: there was actually something, but it was not hard to fix.

Given that the approach used to work for you, I recommend reimplementing that in your new project. Setup a requests in flight counter and a wait method that returns when the counter reaches zero.

Starting with https://github.com/jtassin/pending-xhr-puppeteer/blob/master/src/index.ts, just replace

import { Request, Page } from 'puppeteer';

with the Playwright import. So far it works for me.

Upvotes: 2

HackSlash
HackSlash

Reputation: 5812

Using await page.WaitForLoadStateAsync(LoadState.NetworkIdle); didn't work for me in my Blazor Server App.

According to the documentation

Optional load state to wait for, defaults to load. If the state has been already reached while loading current document, the method resolves immediately. Can be one of:

'load' - wait for the load event to be fired.
'domcontentloaded' - wait for the DOMContentLoaded event to be fired.
'networkidle' - DISCOURAGED wait until there are no network connections for at least 500 ms. Don't use this method for testing,

rely on web assertions to assess readiness instead.

Neither did the default: await page.WaitForLoadStateAsync(); or the await page.WaitForLoadStateAsync(LoadState.DOMContentLoaded);

These likely work better when you aren't writing a SPA.

If you are specifically waiting on a popup, use:

await Page.RunAndWaitForPopupAsync()

Upvotes: 5

unickq
unickq

Reputation: 3418

Dotnet:

await popup.WaitForLoadStateAsync(LoadState.Networkidle)

https://playwright.dev/dotnet/docs/api/class-page#page-wait-for-load-state

JS:

await page.waitForLoadState("networkidle")

https://playwright.dev/docs/api/class-page#page-wait-for-load-state

Upvotes: 12

Related Questions