javascriptautomated-testsplaywrightcucumberjsplaywright-typescript

Playwright - How to test that a network request have finished after on click event


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 combine 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 coming assertion to fail as it was not completed.

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?


Solution

  • The 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 commas 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