From fdc3079d1692866421e16abf141da7e54186c14b Mon Sep 17 00:00:00 2001 From: Adam Alston Date: Wed, 20 Aug 2025 23:26:06 -0400 Subject: [PATCH] fix(navigation): resolve wait on canceled requests --- cli/CHANGELOG.md | 4 +++ .../cypress/e2e/commands/navigation.cy.js | 22 +++++++++++++ packages/driver/src/cy/commands/navigation.ts | 31 +++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index 891f19ac89f..cf7b749e2cd 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -3,6 +3,10 @@ _Released 08/26/2025 (PENDING)_ +**Bugfixes:** + +* Fixed an issue where `cy.wait('@alias')` could time out when the underlying network request was canceled by navigation (e.g., `cy.visit`, `cy.reload`). Fixes [#19326](https://github.com/cypress-io/cypress/issues/19326). + **Dependency Updates:** - Upgraded `tar` from `6.1.5` to `6.2.1`. Addressed in [#32229](https://github.com/cypress-io/cypress/pull/32229). diff --git a/packages/driver/cypress/e2e/commands/navigation.cy.js b/packages/driver/cypress/e2e/commands/navigation.cy.js index 3b9e9de6a22..b0415b402bb 100644 --- a/packages/driver/cypress/e2e/commands/navigation.cy.js +++ b/packages/driver/cypress/e2e/commands/navigation.cy.js @@ -1878,6 +1878,28 @@ describe('src/cy/commands/navigation', () => { }) }) }) + + it('should resolve wait for a request canceled by navigation', () => { + const alias = crypto.randomUUID() + + cy.intercept(/jsonplaceholder.cypress.io/).as(alias) + + 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(`@${alias}`).then((interception) => { + const actual = JSON.parse( + JSON.stringify(interception, (_, value) => value), + ) + + cy.wrap(actual).should('deep.equal', { + ...actual, + state: 'Errored', + error: { ...interception.error }, + }) + }) + }) }) // TODO(webkit): fix+unskip for webkit release diff --git a/packages/driver/src/cy/commands/navigation.ts b/packages/driver/src/cy/commands/navigation.ts index 4ff70ec2f6a..c173bc8e384 100644 --- a/packages/driver/src/cy/commands/navigation.ts +++ b/packages/driver/src/cy/commands/navigation.ts @@ -176,6 +176,18 @@ const pageLoading = (bool, Cypress, state) => { Cypress.action('app:page:loading', bool) } +const markRequestAsCancelled = (request: any) => { + if ( + request && + request.state === 'Received' && + !request.response && + !request.error + ) { + request.state = 'Errored' + request.error = new Error('Request was cancelled due to navigation.') + } +} + const stabilityChanged = async (Cypress, state, config, stable) => { debug('stabilityChanged:', stable) @@ -188,6 +200,25 @@ const stabilityChanged = async (Cypress, state, config, stable) => { return } + // Mark inflight requests as canceled at navigation start. + try { + const routes = state('routes') ?? {} + + _.forEach(routes, ({ requests }) => { + _.forEach(requests, markRequestAsCancelled) + }) + + const aliasedRequests = state('aliasedRequests') ?? [] + + aliasedRequests.forEach(({ request }) => { + markRequestAsCancelled(request) + }) + } catch (_) { + // TODO: Should I use `$errUtils.logError` or another method from + // `$errUtils` here? Alternatively, should I do nothing, since canceled + // requests aren't necessarily a problem in Cypress? + } + // if we purposefully just caused the page to load // (and thus instability) don't log this out if (knownCommandCausedInstability) {