From bb1f237d59d4fc418c01f2eeb1db42d77a0cc049 Mon Sep 17 00:00:00 2001 From: Bill Glesias Date: Tue, 6 Sep 2022 15:29:44 -0400 Subject: [PATCH 1/7] feat: add X-Cypress-Request header in extension --- packages/extension/app/background.js | 14 ++++- .../test/integration/background_spec.js | 62 +++++++++++++++++-- 2 files changed, 70 insertions(+), 6 deletions(-) diff --git a/packages/extension/app/background.js b/packages/extension/app/background.js index ed642603b251..1471fd75baf0 100644 --- a/packages/extension/app/background.js +++ b/packages/extension/app/background.js @@ -61,6 +61,16 @@ const connect = function (host, path, extraOpts) { // adds a header to the request to mark it as a request for the AUT frame // itself, so the proxy can utilize that for injection purposes browser.webRequest.onBeforeSendHeaders.addListener((details) => { + const defaultHeaders = { + requestHeaders: [ + ...(details.requestHeaders || []), + ...(details.type === 'xmlhttprequest' ? [{ + name: 'X-Cypress-Request', + value: 'true', + }] : []), + ], + } + if ( // parentFrameId: 0 means the parent is the top-level, so if it isn't // 0, it's nested inside the AUT and can't be the AUT itself @@ -69,11 +79,11 @@ const connect = function (host, path, extraOpts) { || details.type !== 'sub_frame' // is the spec frame, not the AUT || details.url.includes('__cypress') - ) return + ) return defaultHeaders return { requestHeaders: [ - ...details.requestHeaders, + ...defaultHeaders.requestHeaders, { name: 'X-Cypress-Is-AUT-Frame', value: 'true', diff --git a/packages/extension/test/integration/background_spec.js b/packages/extension/test/integration/background_spec.js index 494cd65bc8db..0742a6952074 100644 --- a/packages/extension/test/integration/background_spec.js +++ b/packages/extension/test/integration/background_spec.js @@ -297,7 +297,7 @@ describe('app/background', () => { const result = browser.webRequest.onBeforeSendHeaders.addListener.lastCall.args[0](details) - expect(result).to.be.undefined + expect(result).to.deep.equal({ requestHeaders: [] }) }) it('does not add header if it is a nested frame', async function () { @@ -311,7 +311,7 @@ describe('app/background', () => { const result = browser.webRequest.onBeforeSendHeaders.addListener.lastCall.args[0](details) - expect(result).to.be.undefined + expect(result).to.deep.equal({ requestHeaders: [] }) }) it('does not add header if it is not a sub frame request', async function () { @@ -326,7 +326,7 @@ describe('app/background', () => { const result = browser.webRequest.onBeforeSendHeaders.addListener.lastCall.args[0](details) - expect(result).to.be.undefined + expect(result).to.deep.equal({ requestHeaders: [] }) }) it('does not add header if it is a spec frame request', async function () { @@ -341,7 +341,7 @@ describe('app/background', () => { await this.connect(withExperimentalFlagOn) const result = browser.webRequest.onBeforeSendHeaders.addListener.lastCall.args[0](details) - expect(result).to.be.undefined + expect(result).to.deep.equal({ requestHeaders: [] }) }) it('appends X-Cypress-Is-AUT-Frame header to AUT iframe request', async function () { @@ -373,6 +373,60 @@ describe('app/background', () => { }) }) + it('appends X-Cypress-Request header to request if the resourceType is "xmlhttprequest"', async function () { + const details = { + parentFrameId: 0, + type: 'xmlhttprequest', + url: 'http://localhost:3000/index.html', + requestHeaders: [ + { name: 'X-Foo', value: 'Bar' }, + ], + } + + sinon.stub(browser.webRequest.onBeforeSendHeaders, 'addListener') + + await this.connect(withExperimentalFlagOn) + const result = browser.webRequest.onBeforeSendHeaders.addListener.lastCall.args[0](details) + + expect(result).to.deep.equal({ + requestHeaders: [ + { + name: 'X-Foo', + value: 'Bar', + }, + { + name: 'X-Cypress-Request', + value: 'true', + }, + ], + }) + }) + + it('does not append X-Cypress-Request header to request if the resourceType is not an "xmlhttprequest"', async function () { + const details = { + parentFrameId: 0, + type: 'sub_frame', + url: 'http://localhost:3000/index.html', + requestHeaders: [ + { name: 'X-Foo', value: 'Bar' }, + ], + } + + sinon.stub(browser.webRequest.onBeforeSendHeaders, 'addListener') + + await this.connect(withExperimentalFlagOn) + const result = browser.webRequest.onBeforeSendHeaders.addListener.lastCall.args[0](details) + + expect(result).to.not.deep.equal({ + requestHeaders: [ + { + name: 'X-Cypress-Request', + value: 'true', + }, + ], + }) + }) + it('does not add before-headers listener if in non-Firefox browser', async function () { browser.runtime.getBrowserInfo = undefined From fda83415919643a83fc28f95d116f9cc61cc1cae Mon Sep 17 00:00:00 2001 From: Bill Glesias Date: Tue, 6 Sep 2022 15:35:02 -0400 Subject: [PATCH 2/7] feat: add X-Cypress-Request header in CDP --- packages/server/lib/browsers/chrome.ts | 26 ++++++-- .../server/test/unit/browsers/chrome_spec.js | 64 +++++++++++++++++++ 2 files changed, 84 insertions(+), 6 deletions(-) diff --git a/packages/server/lib/browsers/chrome.ts b/packages/server/lib/browsers/chrome.ts index 5bea2301576f..3c47bb753cb2 100644 --- a/packages/server/lib/browsers/chrome.ts +++ b/packages/server/lib/browsers/chrome.ts @@ -342,19 +342,19 @@ const _listenForFrameTreeChanges = (client) => { client.on('Page.frameDetached', _updateFrameTree(client, 'Page.frameDetached')) } -const _continueRequest = (client, params, header?) => { +const _continueRequest = (client, params, headers?) => { const details: Protocol.Fetch.ContinueRequestRequest = { requestId: params.requestId, } - if (header) { + if (headers && headers.length) { // headers are received as an object but need to be an array // to modify them const currentHeaders = _.map(params.request.headers, (value, name) => ({ name, value })) details.headers = [ ...currentHeaders, - header, + ...headers, ] } @@ -403,20 +403,34 @@ const _handlePausedRequests = async (client) => { // adds a header to the request to mark it as a request for the AUT frame // itself, so the proxy can utilize that for injection purposes client.on('Fetch.requestPaused', async (params: Protocol.Fetch.RequestPausedEvent) => { + const addedHeaders: { + name: string + value: string + }[] = [] + + if (params.resourceType === 'XHR' || params.resourceType === 'Fetch') { + debug('add X-Cypress-Request header to: %s', params.request.url) + addedHeaders.push({ + name: 'X-Cypress-Request', + value: params.resourceType.toLowerCase(), + }) + } + if ( // is a script, stylesheet, image, etc params.resourceType !== 'Document' || !(await _isAUTFrame(params.frameId)) ) { - return _continueRequest(client, params) + return _continueRequest(client, params, addedHeaders) } debug('add X-Cypress-Is-AUT-Frame header to: %s', params.request.url) - - _continueRequest(client, params, { + addedHeaders.push({ name: 'X-Cypress-Is-AUT-Frame', value: 'true', }) + + return _continueRequest(client, params, addedHeaders) }) } diff --git a/packages/server/test/unit/browsers/chrome_spec.js b/packages/server/test/unit/browsers/chrome_spec.js index 428b0a6b6a20..63aef387286d 100644 --- a/packages/server/test/unit/browsers/chrome_spec.js +++ b/packages/server/test/unit/browsers/chrome_spec.js @@ -464,6 +464,70 @@ describe('lib/browsers/chrome', () => { }) }) + it('appends X-Cypress-Request header to fetch request', async function () { + await chrome.open('chrome', 'http://', withExperimentalFlagOn, this.automation) + + this.pageCriClient.on.withArgs('Page.frameAttached').yield() + + await this.pageCriClient.on.withArgs('Fetch.requestPaused').args[0][1]({ + frameId: 'aut-frame-id', + requestId: '1234', + resourceType: 'Fetch', + request: { + url: 'http://localhost:3000/test-request', + headers: { + 'X-Foo': 'Bar', + }, + }, + }) + + expect(this.pageCriClient.send).to.be.calledWith('Fetch.continueRequest', { + requestId: '1234', + headers: [ + { + name: 'X-Foo', + value: 'Bar', + }, + { + name: 'X-Cypress-Request', + value: 'fetch', + }, + ], + }) + }) + + it('appends X-Cypress-Request header to xhr request', async function () { + await chrome.open('chrome', 'http://', withExperimentalFlagOn, this.automation) + + this.pageCriClient.on.withArgs('Page.frameAttached').yield() + + await this.pageCriClient.on.withArgs('Fetch.requestPaused').args[0][1]({ + frameId: 'aut-frame-id', + requestId: '1234', + resourceType: 'XHR', + request: { + url: 'http://localhost:3000/test-request', + headers: { + 'X-Foo': 'Bar', + }, + }, + }) + + expect(this.pageCriClient.send).to.be.calledWith('Fetch.continueRequest', { + requestId: '1234', + headers: [ + { + name: 'X-Foo', + value: 'Bar', + }, + { + name: 'X-Cypress-Request', + value: 'xhr', + }, + ], + }) + }) + it('gets frame tree on Page.frameAttached', async function () { await chrome.open('chrome', 'http://', withExperimentalFlagOn, this.automation) From f9ecb5bad7c0cbfe77167ad775d7e283c9b709ae Mon Sep 17 00:00:00 2001 From: Bill Glesias Date: Tue, 6 Sep 2022 15:39:18 -0400 Subject: [PATCH 3/7] feat: add X-Cypress-Request header in electron --- packages/server/lib/browsers/electron.ts | 13 ++++- .../test/unit/browsers/electron_spec.js | 51 +++++++++++++++++-- 2 files changed, 57 insertions(+), 7 deletions(-) diff --git a/packages/server/lib/browsers/electron.ts b/packages/server/lib/browsers/electron.ts index 639c608b0dbf..d62b0b608dc6 100644 --- a/packages/server/lib/browsers/electron.ts +++ b/packages/server/lib/browsers/electron.ts @@ -384,6 +384,15 @@ export = { // adds a header to the request to mark it as a request for the AUT frame // itself, so the proxy can utilize that for injection purposes win.webContents.session.webRequest.onBeforeSendHeaders((details, cb) => { + const defaultHeaders = { + requestHeaders: { + ...details.requestHeaders, + ...(details.resourceType === 'xhr') ? { + 'X-Cypress-Request': 'true', + } : {}, + }, + } + if ( // isn't an iframe details.resourceType !== 'subFrame' @@ -392,14 +401,14 @@ export = { // is the spec frame, not the AUT || details.url.includes('__cypress') ) { - cb({}) + cb(defaultHeaders) return } cb({ requestHeaders: { - ...details.requestHeaders, + ...defaultHeaders.requestHeaders, 'X-Cypress-Is-AUT-Frame': 'true', }, }) diff --git a/packages/server/test/unit/browsers/electron_spec.js b/packages/server/test/unit/browsers/electron_spec.js index c981ce4f43d7..9786805c9bf4 100644 --- a/packages/server/test/unit/browsers/electron_spec.js +++ b/packages/server/test/unit/browsers/electron_spec.js @@ -358,7 +358,9 @@ describe('lib/browsers/electron', () => { this.win.webContents.session.webRequest.onBeforeSendHeaders.lastCall.args[0](details, cb) expect(cb).to.be.calledOnce - expect(cb).to.be.calledWith({}) + expect(cb).to.be.calledWith({ + requestHeaders: {}, + }) }) }) @@ -378,7 +380,9 @@ describe('lib/browsers/electron', () => { this.win.webContents.session.webRequest.onBeforeSendHeaders.lastCall.args[0](details, cb) expect(cb).to.be.calledOnce - expect(cb).to.be.calledWith({}) + expect(cb).to.be.calledWith({ + requestHeaders: {}, + }) }) }) @@ -402,7 +406,9 @@ describe('lib/browsers/electron', () => { this.win.webContents.session.webRequest.onBeforeSendHeaders.lastCall.args[0](details, cb) expect(cb).to.be.calledOnce - expect(cb).to.be.calledWith({}) + expect(cb).to.be.calledWith({ + requestHeaders: {}, + }) }) }) @@ -424,7 +430,9 @@ describe('lib/browsers/electron', () => { this.win.webContents.session.webRequest.onBeforeSendHeaders.lastCall.args[0](details, cb) - expect(cb).to.be.calledWith({}) + expect(cb).to.be.calledWith({ + requestHeaders: {}, + }) }) }) @@ -441,7 +449,9 @@ describe('lib/browsers/electron', () => { this.win.webContents.session.webRequest.onBeforeSendHeaders.lastCall.args[0](details, cb) - expect(cb).to.be.calledWith({}) + expect(cb).to.be.calledWith({ + requestHeaders: {}, + }) }) }) @@ -475,6 +485,37 @@ describe('lib/browsers/electron', () => { }) }) }) + + it('adds X-Cypress-Request header if xhr request (includes fetch)', function () { + sinon.stub(this.win.webContents.session.webRequest, 'onBeforeSendHeaders') + + return electron._launch(this.win, this.url, this.automation, this.options) + .then(() => { + const details = { + resourceType: 'xhr', + frame: { + parent: { + parent: null, + }, + }, + url: 'http://localhost:3000/test-request', + requestHeaders: { + 'X-Foo': 'Bar', + }, + } + const cb = sinon.stub() + + this.win.webContents.session.webRequest.onBeforeSendHeaders.lastCall.args[0](details, cb) + + expect(cb).to.be.calledOnce + expect(cb).to.be.calledWith({ + requestHeaders: { + 'X-Foo': 'Bar', + 'X-Cypress-Request': 'true', + }, + }) + }) + }) }) }) From fada5f331fcf88b2ba078e77e6aacc271501b5eb Mon Sep 17 00:00:00 2001 From: Bill Glesias Date: Tue, 13 Sep 2022 16:56:51 -0400 Subject: [PATCH 4/7] feat: add ExtractRequestedWithAndCredentialsIfApplicable middleware stub to remove the newly added x-cypress-request header --- packages/proxy/lib/http/request-middleware.ts | 10 ++++++++++ .../test/unit/http/request-middleware.spec.ts | 20 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/packages/proxy/lib/http/request-middleware.ts b/packages/proxy/lib/http/request-middleware.ts index 0ad90c3144ea..8cfd943c598d 100644 --- a/packages/proxy/lib/http/request-middleware.ts +++ b/packages/proxy/lib/http/request-middleware.ts @@ -31,6 +31,15 @@ const ExtractIsAUTFrameHeader: RequestMiddleware = function () { this.next() } +const ExtractRequestedWithAndCredentialsIfApplicable: RequestMiddleware = function () { + if (this.req.headers['x-cypress-request']) { + this.debug(`found x-cypress-request header. Deleting x-cypress-request header.`) + delete this.req.headers['x-cypress-request'] + } + + this.next() +} + const MaybeSimulateSecHeaders: RequestMiddleware = function () { if (!this.config.experimentalModifyObstructiveThirdPartyCode) { this.next() @@ -248,6 +257,7 @@ const SendRequestOutgoing: RequestMiddleware = function () { export default { LogRequest, ExtractIsAUTFrameHeader, + ExtractRequestedWithAndCredentialsIfApplicable, MaybeSimulateSecHeaders, MaybeAttachCrossOriginCookies, MaybeEndRequestWithBufferedResponse, diff --git a/packages/proxy/test/unit/http/request-middleware.spec.ts b/packages/proxy/test/unit/http/request-middleware.spec.ts index bf14243b7542..65c86d4c20fd 100644 --- a/packages/proxy/test/unit/http/request-middleware.spec.ts +++ b/packages/proxy/test/unit/http/request-middleware.spec.ts @@ -12,6 +12,7 @@ describe('http/request-middleware', () => { expect(_.keys(RequestMiddleware)).to.have.ordered.members([ 'LogRequest', 'ExtractIsAUTFrameHeader', + 'ExtractRequestedWithAndCredentialsIfApplicable', 'MaybeSimulateSecHeaders', 'MaybeAttachCrossOriginCookies', 'MaybeEndRequestWithBufferedResponse', @@ -60,6 +61,25 @@ describe('http/request-middleware', () => { }) }) + describe('ExtractRequestedWithAndCredentialsIfApplicable', () => { + const { ExtractRequestedWithAndCredentialsIfApplicable } = RequestMiddleware + + it('removes x-cypress-request header when it exists, sets in on the req', async () => { + const ctx = { + req: { + headers: { + 'x-cypress-request': 'true', + }, + } as Partial, + } + + await testMiddleware([ExtractRequestedWithAndCredentialsIfApplicable], ctx) + .then(() => { + expect(ctx.req.headers['x-cypress-request']).not.to.exist + }) + }) + }) + describe('MaybeSimulateSecHeaders', () => { const { MaybeSimulateSecHeaders } = RequestMiddleware From 3abcf9ec084d28cabc57959f5e4cc23f89ef851f Mon Sep 17 00:00:00 2001 From: Bill Glesias Date: Wed, 14 Sep 2022 14:59:36 -0400 Subject: [PATCH 5/7] chore: change defaultHeaders variable name to requestModifications to more accurately reflect usage --- packages/extension/app/background.js | 6 +++--- packages/server/lib/browsers/electron.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/extension/app/background.js b/packages/extension/app/background.js index 1471fd75baf0..a9853eae5b9c 100644 --- a/packages/extension/app/background.js +++ b/packages/extension/app/background.js @@ -61,7 +61,7 @@ const connect = function (host, path, extraOpts) { // adds a header to the request to mark it as a request for the AUT frame // itself, so the proxy can utilize that for injection purposes browser.webRequest.onBeforeSendHeaders.addListener((details) => { - const defaultHeaders = { + const requestModifications = { requestHeaders: [ ...(details.requestHeaders || []), ...(details.type === 'xmlhttprequest' ? [{ @@ -79,11 +79,11 @@ const connect = function (host, path, extraOpts) { || details.type !== 'sub_frame' // is the spec frame, not the AUT || details.url.includes('__cypress') - ) return defaultHeaders + ) return requestModifications return { requestHeaders: [ - ...defaultHeaders.requestHeaders, + ...requestModifications.requestHeaders, { name: 'X-Cypress-Is-AUT-Frame', value: 'true', diff --git a/packages/server/lib/browsers/electron.ts b/packages/server/lib/browsers/electron.ts index d62b0b608dc6..5c758d53bb72 100644 --- a/packages/server/lib/browsers/electron.ts +++ b/packages/server/lib/browsers/electron.ts @@ -384,7 +384,7 @@ export = { // adds a header to the request to mark it as a request for the AUT frame // itself, so the proxy can utilize that for injection purposes win.webContents.session.webRequest.onBeforeSendHeaders((details, cb) => { - const defaultHeaders = { + const requestModifications = { requestHeaders: { ...details.requestHeaders, ...(details.resourceType === 'xhr') ? { @@ -401,14 +401,14 @@ export = { // is the spec frame, not the AUT || details.url.includes('__cypress') ) { - cb(defaultHeaders) + cb(requestModifications) return } cb({ requestHeaders: { - ...defaultHeaders.requestHeaders, + ...requestModifications.requestHeaders, 'X-Cypress-Is-AUT-Frame': 'true', }, }) From 5a93e0a91ef778dddc14de3a6463c6dfa665696c Mon Sep 17 00:00:00 2001 From: Bill Glesias Date: Wed, 14 Sep 2022 15:03:14 -0400 Subject: [PATCH 6/7] chore: condense ExtractIsAUTFrameHeader and ExtractRequestedWithAndCredentialsIfApplicable into ExtractCypressMetadataHeaders middleware --- packages/proxy/lib/http/request-middleware.ts | 9 ++------- .../test/unit/http/request-middleware.spec.ts | 17 ++++++----------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/packages/proxy/lib/http/request-middleware.ts b/packages/proxy/lib/http/request-middleware.ts index 8cfd943c598d..8a49dc430926 100644 --- a/packages/proxy/lib/http/request-middleware.ts +++ b/packages/proxy/lib/http/request-middleware.ts @@ -21,17 +21,13 @@ const LogRequest: RequestMiddleware = function () { this.next() } -const ExtractIsAUTFrameHeader: RequestMiddleware = function () { +const ExtractCypressMetadataHeaders: RequestMiddleware = function () { this.req.isAUTFrame = !!this.req.headers['x-cypress-is-aut-frame'] if (this.req.headers['x-cypress-is-aut-frame']) { delete this.req.headers['x-cypress-is-aut-frame'] } - this.next() -} - -const ExtractRequestedWithAndCredentialsIfApplicable: RequestMiddleware = function () { if (this.req.headers['x-cypress-request']) { this.debug(`found x-cypress-request header. Deleting x-cypress-request header.`) delete this.req.headers['x-cypress-request'] @@ -256,8 +252,7 @@ const SendRequestOutgoing: RequestMiddleware = function () { export default { LogRequest, - ExtractIsAUTFrameHeader, - ExtractRequestedWithAndCredentialsIfApplicable, + ExtractCypressMetadataHeaders, MaybeSimulateSecHeaders, MaybeAttachCrossOriginCookies, MaybeEndRequestWithBufferedResponse, diff --git a/packages/proxy/test/unit/http/request-middleware.spec.ts b/packages/proxy/test/unit/http/request-middleware.spec.ts index 65c86d4c20fd..9a5e822cb7a8 100644 --- a/packages/proxy/test/unit/http/request-middleware.spec.ts +++ b/packages/proxy/test/unit/http/request-middleware.spec.ts @@ -11,8 +11,7 @@ describe('http/request-middleware', () => { it('exports the members in the correct order', () => { expect(_.keys(RequestMiddleware)).to.have.ordered.members([ 'LogRequest', - 'ExtractIsAUTFrameHeader', - 'ExtractRequestedWithAndCredentialsIfApplicable', + 'ExtractCypressMetadataHeaders', 'MaybeSimulateSecHeaders', 'MaybeAttachCrossOriginCookies', 'MaybeEndRequestWithBufferedResponse', @@ -27,8 +26,8 @@ describe('http/request-middleware', () => { ]) }) - describe('ExtractIsAUTFrameHeader', () => { - const { ExtractIsAUTFrameHeader } = RequestMiddleware + describe('ExtractCypressMetadataHeaders', () => { + const { ExtractCypressMetadataHeaders } = RequestMiddleware it('removes x-cypress-is-aut-frame header when it exists, sets in on the req', async () => { const ctx = { @@ -39,7 +38,7 @@ describe('http/request-middleware', () => { } as Partial, } - await testMiddleware([ExtractIsAUTFrameHeader], ctx) + await testMiddleware([ExtractCypressMetadataHeaders], ctx) .then(() => { expect(ctx.req.headers['x-cypress-is-aut-frame']).not.to.exist expect(ctx.req.isAUTFrame).to.be.true @@ -53,16 +52,12 @@ describe('http/request-middleware', () => { } as Partial, } - await testMiddleware([ExtractIsAUTFrameHeader], ctx) + await testMiddleware([ExtractCypressMetadataHeaders], ctx) .then(() => { expect(ctx.req.headers['x-cypress-is-aut-frame']).not.to.exist expect(ctx.req.isAUTFrame).to.be.false }) }) - }) - - describe('ExtractRequestedWithAndCredentialsIfApplicable', () => { - const { ExtractRequestedWithAndCredentialsIfApplicable } = RequestMiddleware it('removes x-cypress-request header when it exists, sets in on the req', async () => { const ctx = { @@ -73,7 +68,7 @@ describe('http/request-middleware', () => { } as Partial, } - await testMiddleware([ExtractRequestedWithAndCredentialsIfApplicable], ctx) + await testMiddleware([ExtractCypressMetadataHeaders], ctx) .then(() => { expect(ctx.req.headers['x-cypress-request']).not.to.exist }) From 842982174ad9b337f40311a58f684bac5a66949d Mon Sep 17 00:00:00 2001 From: Bill Glesias Date: Wed, 14 Sep 2022 15:04:36 -0400 Subject: [PATCH 7/7] test: add anti assertion for x-cypress-request and remove setting request verbage (as it does nothing yet) --- .../test/unit/http/request-middleware.spec.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/proxy/test/unit/http/request-middleware.spec.ts b/packages/proxy/test/unit/http/request-middleware.spec.ts index 9a5e822cb7a8..7a2968dbeb3b 100644 --- a/packages/proxy/test/unit/http/request-middleware.spec.ts +++ b/packages/proxy/test/unit/http/request-middleware.spec.ts @@ -59,7 +59,7 @@ describe('http/request-middleware', () => { }) }) - it('removes x-cypress-request header when it exists, sets in on the req', async () => { + it('removes x-cypress-request header when it exists', async () => { const ctx = { req: { headers: { @@ -73,6 +73,19 @@ describe('http/request-middleware', () => { expect(ctx.req.headers['x-cypress-request']).not.to.exist }) }) + + it('removes x-cypress-request header when it does not exist', async () => { + const ctx = { + req: { + headers: {}, + } as Partial, + } + + await testMiddleware([ExtractCypressMetadataHeaders], ctx) + .then(() => { + expect(ctx.req.headers['x-cypress-request']).not.to.exist + }) + }) }) describe('MaybeSimulateSecHeaders', () => {