diff --git a/packages/driver/cypress/integration/commands/net_stubbing_spec.ts b/packages/driver/cypress/integration/commands/net_stubbing_spec.ts index 720073ff3c..1ae34d9992 100644 --- a/packages/driver/cypress/integration/commands/net_stubbing_spec.ts +++ b/packages/driver/cypress/integration/commands/net_stubbing_spec.ts @@ -256,6 +256,11 @@ describe('network stubbing', { retries: { runMode: 2, openMode: 0 } }, function cy.wait('@create') }) + // @see https://github.com/cypress-io/cypress/issues/16117 + it('can statically stub a url response with headers', () => { + cy.intercept('/url', { headers: { foo: 'bar' }, body: 'something' }) + }) + // TODO: implement warning in cy.intercept if appropriate // https://github.com/cypress-io/cypress/issues/2372 it.skip('warns if a percent-encoded URL is used', function () { diff --git a/packages/driver/src/cy/net-stubbing/add-command.ts b/packages/driver/src/cy/net-stubbing/add-command.ts index 8c2d1f2299..85a055105d 100644 --- a/packages/driver/src/cy/net-stubbing/add-command.ts +++ b/packages/driver/src/cy/net-stubbing/add-command.ts @@ -19,7 +19,6 @@ import { validateStaticResponse, getBackendStaticResponse, hasStaticResponseKeys, - hasRouteMatcherKeys, } from './static-response-utils' import { registerEvents } from './events' import $errUtils from '../../cypress/error_utils' @@ -27,6 +26,10 @@ import $utils from '../../cypress/utils' const lowercaseFieldNames = (headers: { [fieldName: string]: any }) => _.mapKeys(headers, (v, k) => _.toLower(k)) +export function hasOnlyRouteMatcherKeys (obj: any) { + return !_.isEmpty(obj) && !_.isArray(obj) && _.isEmpty(_.omit(obj, _.concat(PLAIN_FIELDS, STRING_MATCHER_FIELDS, DICT_STRING_MATCHER_FIELDS))) +} + /** * Get all STRING_MATCHER_FIELDS paths plus any extra fields the user has added within * DICT_STRING_MATCHER_FIELDS objects @@ -280,7 +283,7 @@ export function addCommand (Commands, Cypress: Cypress.Cypress, cy: Cypress.cy, function intercept (matcher: RouteMatcher, handler?: RouteHandler | StringMatcher | RouteMatcherOptions, arg2?: RouteHandler) { function getMatcherOptions (): RouteMatcherOptions { - if (_.isString(matcher) && hasRouteMatcherKeys(handler)) { + if (_.isString(matcher) && hasOnlyRouteMatcherKeys(handler)) { // url, mergeRouteMatcher, handler // @ts-ignore if (handler.url) { diff --git a/packages/driver/src/cy/net-stubbing/events/before-request.ts b/packages/driver/src/cy/net-stubbing/events/before-request.ts index 66b179a3ca..5f02b61545 100644 --- a/packages/driver/src/cy/net-stubbing/events/before-request.ts +++ b/packages/driver/src/cy/net-stubbing/events/before-request.ts @@ -94,24 +94,6 @@ export const onBeforeRequest: HandlerFn = (Cypre requestWaited: false, responseWaited: false, subscriptions: [], - on (eventName, handler) { - if (!validEvents.includes(eventName)) { - return $errUtils.throwErrByPath('net_stubbing.request_handling.unknown_event', { - args: { - validEvents, - eventName, - }, - }) - } - - if (!_.isFunction(handler)) { - return $errUtils.throwErrByPath('net_stubbing.request_handling.event_needs_handler') - } - - subscribe(eventName, handler) - - return request - }, } } @@ -122,7 +104,24 @@ export const onBeforeRequest: HandlerFn = (Cypre const userReq: CyHttpMessages.IncomingHttpRequest = { ...req, - on: request.on, + on (eventName, handler) { + if (!validEvents.includes(eventName)) { + return $errUtils.throwErrByPath('net_stubbing.request_handling.unknown_event', { + args: { + validEvents, + eventName, + }, + }) + } + + if (!_.isFunction(handler)) { + return $errUtils.throwErrByPath('net_stubbing.request_handling.event_needs_handler') + } + + subscribe(eventName, handler) + + return userReq + }, continue (responseHandler?) { if (resolved) { return $errUtils.throwErrByPath('net_stubbing.request_handling.completion_called_after_resolved', { args: { cmd: 'continue' } }) diff --git a/packages/driver/src/cy/net-stubbing/static-response-utils.ts b/packages/driver/src/cy/net-stubbing/static-response-utils.ts index 1bcf4150be..d3ae109b9a 100644 --- a/packages/driver/src/cy/net-stubbing/static-response-utils.ts +++ b/packages/driver/src/cy/net-stubbing/static-response-utils.ts @@ -4,9 +4,6 @@ import { StaticResponse, BackendStaticResponse, FixtureOpts, - PLAIN_FIELDS, - STRING_MATCHER_FIELDS, - DICT_STRING_MATCHER_FIELDS, } from '@packages/net-stubbing/lib/types' import $errUtils from '../../cypress/error_utils' @@ -125,7 +122,3 @@ export function getBackendStaticResponse (staticResponse: Readonly void | Promise): Interception + on(eventName: 'after:response', cb: (res: CyHttpMessages.IncomingResponse) => void | Promise): this } /** * Request/response cycle. */ -export interface Interception extends InterceptionEvents { +export interface Interception { id: string routeId: string /* @internal */ @@ -342,7 +342,7 @@ export interface RouteMatcherOptionsGeneric { */ method?: S /** - * If `true`, this will pass the request on to the next `RouteMatcher` after the request handler completes. + * If `true`, this handler will be called before any non-`middleware` handlers, in the order it was defined. * Can only be used with a dynamic request handler. * @default false */ @@ -413,7 +413,7 @@ export interface GenericStaticResponse { */ forceNetworkError?: boolean /** - * Kilobits per second to send 'body'. + * Kilobytes per second to send 'body'. */ throttleKbps?: number /**