Reputation: 3755
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
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
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
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