Skip to content

Commit

Permalink
fix: properly detect cy.intercept(url, routeMatcher, handler) overl…
Browse files Browse the repository at this point in the history
…oad (#16167)
  • Loading branch information
flotwig committed Apr 26, 2021
1 parent a1f2464 commit 338d702
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 () {
Expand Down
7 changes: 5 additions & 2 deletions packages/driver/src/cy/net-stubbing/add-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,17 @@ import {
validateStaticResponse,
getBackendStaticResponse,
hasStaticResponseKeys,
hasRouteMatcherKeys,
} from './static-response-utils'
import { registerEvents } from './events'
import $errUtils from '../../cypress/error_utils'
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
Expand Down Expand Up @@ -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) {
Expand Down
37 changes: 18 additions & 19 deletions packages/driver/src/cy/net-stubbing/events/before-request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,24 +94,6 @@ export const onBeforeRequest: HandlerFn<CyHttpMessages.IncomingRequest> = (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
},
}
}

Expand All @@ -122,7 +104,24 @@ export const onBeforeRequest: HandlerFn<CyHttpMessages.IncomingRequest> = (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' } })
Expand Down
7 changes: 0 additions & 7 deletions packages/driver/src/cy/net-stubbing/static-response-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand Down Expand Up @@ -125,7 +122,3 @@ export function getBackendStaticResponse (staticResponse: Readonly<StaticRespons
export function hasStaticResponseKeys (obj: any) {
return !_.isArray(obj) && (_.intersection(_.keys(obj), STATIC_RESPONSE_KEYS).length || _.isEmpty(obj))
}

export function hasRouteMatcherKeys (obj: any) {
return _.intersection(_.keys(obj), _.concat(PLAIN_FIELDS, STRING_MATCHER_FIELDS, DICT_STRING_MATCHER_FIELDS)).length
}
18 changes: 9 additions & 9 deletions packages/net-stubbing/lib/external-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export namespace CyHttpMessages {
*/
statusMessage: string
/**
* Kilobits per second to send 'body'.
* Kilobytes per second to send 'body'.
*/
throttleKbps?: number
/**
Expand Down Expand Up @@ -152,7 +152,7 @@ export namespace CyHttpMessages {
alias?: string
}

export interface IncomingHttpRequest extends IncomingRequest, InterceptionEvents {
export interface IncomingHttpRequest extends IncomingRequest, RequestEvents {
/**
* Destroy the request and respond with a network error.
*/
Expand Down Expand Up @@ -237,31 +237,31 @@ export interface Subscription {
skip?: boolean
}

interface InterceptionEvents {
interface RequestEvents {
/**
* Emitted before `response` and before any `req.continue` handlers.
* Modifications to `res` will be applied to the incoming response.
* If a promise is returned from `cb`, it will be awaited before processing other event handlers.
*/
on(eventName: 'before:response', cb: HttpResponseInterceptor): Interception
on(eventName: 'before:response', cb: HttpResponseInterceptor): this
/**
* Emitted after `before:response` and after any `req.continue` handlers - before the response is sent to the browser.
* Modifications to `res` will be applied to the incoming response.
* If a promise is returned from `cb`, it will be awaited before processing other event handlers.
*/
on(eventName: 'response', cb: HttpResponseInterceptor): Interception
on(eventName: 'response', cb: HttpResponseInterceptor): this
/**
* Emitted once the response to a request has finished sending to the browser.
* Modifications to `res` have no impact.
* If a promise is returned from `cb`, it will be awaited before processing other event handlers.
*/
on(eventName: 'after:response', cb: (res: CyHttpMessages.IncomingResponse) => void | Promise<void>): Interception
on(eventName: 'after:response', cb: (res: CyHttpMessages.IncomingResponse) => void | Promise<void>): this
}

/**
* Request/response cycle.
*/
export interface Interception extends InterceptionEvents {
export interface Interception {
id: string
routeId: string
/* @internal */
Expand Down Expand Up @@ -342,7 +342,7 @@ export interface RouteMatcherOptionsGeneric<S> {
*/
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
*/
Expand Down Expand Up @@ -413,7 +413,7 @@ export interface GenericStaticResponse<Fixture, Body> {
*/
forceNetworkError?: boolean
/**
* Kilobits per second to send 'body'.
* Kilobytes per second to send 'body'.
*/
throttleKbps?: number
/**
Expand Down

4 comments on commit 338d702

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 338d702 Apr 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/7.2.0/circle-develop-338d702632e2d2a807d74013a5798aecbe45b0db/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 338d702 Apr 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AppVeyor has built the win32 ia32 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/7.2.0/appveyor-develop-338d702632e2d2a807d74013a5798aecbe45b0db/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 338d702 Apr 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AppVeyor has built the win32 x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/7.2.0/appveyor-develop-338d702632e2d2a807d74013a5798aecbe45b0db/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 338d702 Apr 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/7.2.0/circle-develop-338d702632e2d2a807d74013a5798aecbe45b0db/cypress.tgz

Please sign in to comment.