I am making BDD test with a Cucumber-Playwright suit. A page I am making a test for has buttons that will trigger a PUT API request and update the page (Note: The button will not link to new address, just trigger and API request).
I want to make sure that all network events have finished before moving on to the next step as it may try to act too soon before the API request has returned and cause the test to fail.
I want to avoid hard waits so I read the documentation and found a step structure that uses Promise.all([])
to bine two or more steps. From what I understand they will check that each step in the array to be true at the same time before moving on.
So the steps looks like this:
await Promise.all([inviteUserButton.click(), page.waitForLoadState('networkidle')])
await page.goto('https://example/examplepage')
This stage of the test is flaky however, it will work about 2/3 times. From the trace files I read to debug the test I see that the the network response repsondes with net::ERR_ABORTED POST https://.....
I believe this is due to to the page.goto()
step has interrupted the network request/response. Due to this, it will cause the ing assertion to fail as it was not pleted.
Is there a way to test that all the pages network events have finished from a onClick event or similar before moving onto the next step?
I am making BDD test with a Cucumber-Playwright suit. A page I am making a test for has buttons that will trigger a PUT API request and update the page (Note: The button will not link to new address, just trigger and API request).
I want to make sure that all network events have finished before moving on to the next step as it may try to act too soon before the API request has returned and cause the test to fail.
I want to avoid hard waits so I read the documentation and found a step structure that uses Promise.all([])
to bine two or more steps. From what I understand they will check that each step in the array to be true at the same time before moving on.
So the steps looks like this:
await Promise.all([inviteUserButton.click(), page.waitForLoadState('networkidle')])
await page.goto('https://example/examplepage')
This stage of the test is flaky however, it will work about 2/3 times. From the trace files I read to debug the test I see that the the network response repsondes with net::ERR_ABORTED POST https://.....
I believe this is due to to the page.goto()
step has interrupted the network request/response. Due to this, it will cause the ing assertion to fail as it was not pleted.
Is there a way to test that all the pages network events have finished from a onClick event or similar before moving onto the next step?
Share Improve this question asked Oct 24, 2022 at 10:03 Mayur KumarMayur Kumar 671 gold badge1 silver badge6 bronze badges2 Answers
Reset to default 2The correct practice is to wait for response before clicking the button to avoid any race conditions so that it will work correctly every single time
as long as api(s) returning back with ok response.
In this , you may add N number of api calls with mas where response from multiple api is expected.
Note: You may need to change the response status code from 200 to 204 , depending on how the api is implemented.
const [resp]= await Promise.all([
this.page.waitForResponse(resp => resp.url().includes('/api/odata/any unique sub string of API endpoint') && resp.status() === 200),
//API2 ,
//API3,
//APIN,
this.page.click('yourButtonLocator'),
]);
const body= await resp.json() //Next step of your scenario
If you don't wrap it in a promise is it still flaky?
await inviteUserButton.click();
await page.waitForLoadState('networkidle');
await page.goto('https://example/examplepage');
How long do the network requests last? The default timeout is set to 30 seconds, did you try to increase it?
waitForLoadState(state?: "load"|"domcontentloaded"|"networkidle", options?: {
/**
* Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be
* changed by using the
* [browserContext.setDefaultNavigationTimeout(timeout)](https://playwright.dev/docs/api/class-browsercontext#browser-context-set-default-navigation-timeout),
* [browserContext.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-browsercontext#browser-context-set-default-timeout),
* [page.setDefaultNavigationTimeout(timeout)](https://playwright.dev/docs/api/class-page#page-set-default-navigation-timeout)
* or [page.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-page#page-set-default-timeout) methods.
*/
timeout?: number;
}): Promise<void>;
You can try and wait for more milliseconds
await Promise.all([inviteUserButton.click(), page.waitForLoadState('networkidle', { timeout:60_000 })])
await page.goto('https://example/examplepage')