Skip to content

Commit 40c81d0

Browse files
AtofStrykerCopilot
andauthored
fix: proxy spec flake in firefox due to improper sweeping and correlation (#31651)
* fix: don't automatically remove requests when cdpRequestWillBeSentReceivedTimestamp is set to 0. Also, do not ass hashes to prerequest url as the urls do not have hashes when coming through the middleware * Update packages/server/lib/browsers/bidi_automation.ts Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Copilot <[email protected]>
1 parent 4712750 commit 40c81d0

File tree

6 files changed

+49
-3
lines changed

6 files changed

+49
-3
lines changed

cli/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ _Released 6/17/2025_
1010
**Bugfixes:**
1111

1212
- Fixed an issue when using `Cypress.stop()` where a run may be aborted prior to receiving the required runner events causing Test Replay to not be available. Addresses [#31781](https://github.com/cypress-io/cypress/issues/31781).
13+
- Fixed an issue where prerequests with Firefox BiDi were prematurely being removed or matched incorrectly. Addresses [#31482](https://github.com/cypress-io/cypress/issues/31482).
1314

1415
## 14.4.1
1516

packages/proxy/lib/http/util/prerequests.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ export class PreRequests {
141141
const now = Date.now()
142142

143143
this.pendingPreRequests.removeMatching(({ cdpRequestWillBeSentReceivedTimestamp, browserPreRequest }) => {
144-
if (cdpRequestWillBeSentReceivedTimestamp + this.sweepInterval < now) {
144+
if (cdpRequestWillBeSentReceivedTimestamp !== 0 && (cdpRequestWillBeSentReceivedTimestamp + this.sweepInterval < now)) {
145145
debugVerbose('timed out unmatched pre-request: %o', browserPreRequest)
146146
metrics.unmatchedPreRequests++
147147

packages/proxy/test/unit/http/util/prerequests.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,4 +309,20 @@ describe('http/util/prerequests', () => {
309309
expect(preRequests.pendingPreRequests.length).to.eq(1)
310310
expect(preRequests.pendingPreRequests.shift('GET-foo|bar')).not.to.be.undefined
311311
})
312+
313+
it('does not remove pre-requests when sweeping if cdpRequestWillBeSentReceivedTimestamp is 0', async () => {
314+
// set the current time to 1000 ms
315+
sinon.stub(Date, 'now').returns(1000)
316+
317+
// set a sweeper timer of 10 ms
318+
preRequests = new PreRequests(10, 10)
319+
preRequests.setProtocolManager(protocolManager)
320+
321+
preRequests.addPending({ requestId: '1234', url: 'foo', method: 'GET', cdpRequestWillBeSentReceivedTimestamp: 0 } as BrowserPreRequest)
322+
323+
// give the sweeper plenty of time to run. Iur request should still not be removed
324+
await new Promise((resolve) => setTimeout(resolve, 1000))
325+
326+
expect(preRequests.pendingPreRequests.length).to.eq(1)
327+
})
312328
})

packages/server/lib/browsers/bidi_automation.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,13 @@ export class BidiAutomation {
172172

173173
const resourceType = normalizeResourceType(params.request.initiatorType)
174174

175+
const urlWithoutHash = url.includes('#') ? url.substring(0, url.indexOf('#')) : url
176+
175177
const browserPreRequest: BrowserPreRequest = {
176178
requestId: params.request.request,
177179
method: params.request.method,
178-
url,
180+
// urls coming into the http middleware contain query params, but lack the hash. To get an accurate key to match on the prerequest, we need to remove the hash.
181+
url: urlWithoutHash,
179182
headers: parsedHeaders,
180183
resourceType,
181184
originalResourceType: params.request.initiatorType || params.request.destination,

packages/server/lib/project-base.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,7 @@ export class ProjectBase extends EE {
641641

642642
if (this.browser.family !== 'chromium') {
643643
// If we're not in chromium, our strategy for correlating service worker prerequests doesn't work in non-chromium browsers (https://github.com/cypress-io/cypress/issues/28079)
644-
// in order to not hang for 2 seconds, we override the prerequest timeout to be 500 ms (which is what it has been historically)
644+
// in order to not hang for 2 seconds, we override the prerequest timeout to be 500 ms (which is what it has been historically).
645645
this._server?.setPreRequestTimeout(500)
646646
}
647647
}

packages/server/test/unit/browsers/bidi_automation_spec.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,32 @@ describe('lib/browsers/bidi_automation', () => {
382382

383383
expect(mockAutomationClient.onRemoveBrowserPreRequest).to.have.been.calledWith('request1')
384384
})
385+
386+
it('strips hashes out of the url when adding the prerequest', async () => {
387+
BidiAutomation.create(mockWebdriverClient, mockAutomationClient)
388+
389+
mockRequest.request.url = 'https://www.foobar.com?foo=bar#hash'
390+
391+
mockWebdriverClient.emit('network.beforeRequestSent', mockRequest)
392+
393+
await flushPromises()
394+
395+
expect(mockAutomationClient.onBrowserPreRequest).to.have.been.calledWith({
396+
requestId: 'request1',
397+
method: 'GET',
398+
url: 'https://www.foobar.com?foo=bar',
399+
resourceType: 'xhr',
400+
originalResourceType: 'xmlhttprequest',
401+
initiator: {
402+
type: 'preflight',
403+
},
404+
headers: {
405+
foo: 'bar',
406+
},
407+
cdpRequestWillBeSentTimestamp: 0,
408+
cdpRequestWillBeSentReceivedTimestamp: 0,
409+
})
410+
})
385411
})
386412

387413
describe('responseStarted / responseCompleted', () => {

0 commit comments

Comments
 (0)