cypress-io / cypress

Fast, easy and reliable testing for anything that runs in a browser.
https://cypress.io
MIT License
47.48k stars 3.2k forks source link

Cancelled network requests fail to resolve with cy.wait #19326

Open jeremydorne opened 2 years ago

jeremydorne commented 2 years ago

Current behavior

If a network request is aliased and the network request is cancelled by the browser, cy.wait will timeout waiting for the network request.

Desired behavior

cy.wait should complete with a failed network request and should convey that the request was cancelled.

Test code to reproduce

// Intercept an outbound request with `cy.intercept` and set it to an alias
cy.intercept("route-to-request", req => {
     req.id = "cancelled-request-id"
     req.reply()
}

// Redirect to a new page before the request resolves
cy.visit('http://localhost:3000/path-to-new-url')

// Wait for the cancelled request to resolve
cy.wait("@cancelled-request-id")

Cypress Version

9.1.1

Other

No response

jeremydorne commented 2 years ago

Poking around in the debugger, once cancelled intercepted requests get a response, they are marked with the state ResponseReceived but will never reach the Complete state.

JosiahAllen commented 2 years ago

Hitting this issue as well, seems to block my ability to catch subsequent completed requests as well.

laurence-myers commented 2 years ago

This is a problem for Single Page Applications. For example, in a Vue app that makes GraphQL requests using Apollo, navigating to different page will cancel any requests in progress.

If the tests are written as full E2E tests, hitting a real API and database, and each test clears & seeds data in the database, you might start to see intermittent database deadlocks. This is because some GraphQL query is still in progress and accessing the database, while the DB is attempting to truncate all tables.

When dealing with a large number of existing (legacy) tests, the quick solution is to intercept every GraphQL request in a beforeEach() hook, and wait for each request in an afterEach() hook. Unfortunately, this doesn't work, due to this issue with cancelled requests. A cancelled request will be intercepted, but attempting to wait for it will always fail.

flotwig commented 1 year ago

@mjhenkes this is fixed by #24709, right?

NavyMint commented 1 year ago

@flotwig looks like yes but still reproducible, im using 9.7 version

flotwig commented 1 year ago

@NavyMint try updating to Cypress 12, which is where that fix landed. We don't typically backport fixes to older versions.

Sam152 commented 1 year ago

I seem to be able to reproduce this with 12.5.1 with the following test case:

context('Waiting on cancelled requests', () => {

  it('waiting will resolve when a request is cancelled', () => {
    cy.intercept(/jsonplaceholder.cypress.io/).as('intercepted-example')

    cy.visit('https://example.cypress.io/commands/network-requests')
    cy.get('.network-btn').click();
    cy.visit('https://example.cypress.io/commands/network-requests');

    cy.wait('@intercepted-example');
  });
});
Screenshot 2023-02-17 at 12 12 51 pm
cypress-app-bot commented 1 year ago

This issue has not had any activity in 180 days. Cypress evolves quickly and the reported behavior should be tested on the latest version of Cypress to verify the behavior is still occurring. It will be closed in 14 days if no updates are provided.

NogDar commented 1 year ago

Issue still occurs on 12.17.4

piotrpalek commented 7 months ago

any updates here? 🙏

AshMcConnell commented 6 months ago

I'm having this issue on the latest Cypress. We have a field that we type in and it fire off a network request with every few chars. It's pretty normal to have cancelled requests. We get this when the cancelled request happens: -

image

Is there any way to ignore it?

krzysieknd commented 6 months ago

I have the same problem, is there any solution to ignore the canceled request?

esetnik commented 2 months ago

I have the same issue. Has anyone found a workaround?

vaclavGabriel commented 2 months ago

I have the same issue. Has anyone found a workaround?

My workaround is to mock the status code of such requests:

// adjust status code for each request to prevent
// cypress from skipping requests cancelled by the browser
cy.intercept(/trpc/, (req) => {
    if (req.url.includes('search.searchAll')) {
        req.alias = 'Search'
        req.reply({ statusCode: 200 })
    }
})