diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index 390f71d085b1..d4ceb84f6e12 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -11,6 +11,10 @@ _Released 6/4/2024 (PENDING)_ - Pre-emptively fix behavior with Chrome for when `unload` events are forcefully deprecated by using `pagehide` as a proxy. Fixes [#29241](https://github.com/cypress-io/cypress/issues/29241). +**Misc:** + +- Enhanced the type definitions available to `cy.intercept` and `cy.wait`. The `body` property of both the request and response in an interception can optionally be specified with user-defined types. Addresses [#29507](https://github.com/cypress-io/cypress/issues/29507). + ## 13.10.0 _Released 5/21/2024_ diff --git a/cli/types/tests/cypress-tests.ts b/cli/types/tests/cypress-tests.ts index b41822ec2cdb..d4a38fb61983 100644 --- a/cli/types/tests/cypress-tests.ts +++ b/cli/types/tests/cypress-tests.ts @@ -513,7 +513,7 @@ describe('then', () => { cy.wait(['@foo', '@bar']) .then(([first, second]) => { - first // $ExpectType Interception + first // $ExpectType Interception }) cy.wait(1234) // $ExpectType Chainable diff --git a/cli/types/tests/net-stubbing-tests.ts b/cli/types/tests/net-stubbing-tests.ts new file mode 100644 index 000000000000..0af4230846c9 --- /dev/null +++ b/cli/types/tests/net-stubbing-tests.ts @@ -0,0 +1,608 @@ +import { + CyHttpMessages, + HttpRequestInterceptor, + HttpResponseInterceptor, + Interception, + Route, + RouteHandler, + RouteHandlerController, + RouteMap, + RouteMatcher, + StringMatcher +} from 'cypress/types/net-stubbing' + +interface CustomRequest { + payload: object +} + +interface CustomResponse { + data: object +} + +describe('net stubbing types', () => { + describe('BaseMessage', () => { + it('has any body by default', () => { + const sut: CyHttpMessages.BaseMessage = undefined! + sut.body // $ExpectType any + }) + + it('has typed body if given', () => { + const sut: CyHttpMessages.BaseMessage = undefined! + sut.body // $ExpectType CustomRequest + }) + }) + + describe('IncomingResponse', () => { + it('has any body by default', () => { + const sut: CyHttpMessages.IncomingResponse = undefined! + sut.body // $ExpectType any + }) + + it('has typed body if given', () => { + const sut: CyHttpMessages.IncomingResponse = undefined! + sut.body // $ExpectType CustomResponse + }) + }) + + describe('IncomingHttpResponse', () => { + it('has any body by default', () => { + const sut: CyHttpMessages.IncomingHttpResponse = undefined! + sut.body // $ExpectType any + }) + + it('has typed body if given', () => { + const sut: CyHttpMessages.IncomingHttpResponse = undefined! + sut.body // $ExpectType CustomResponse + }) + + it('returns the typed body from setDelay', () => { + const sut: CyHttpMessages.IncomingHttpResponse = undefined! + sut.setDelay(0) // $ExpectType IncomingHttpResponse + }) + + it('returns the typed body from setThrottle', () => { + const sut: CyHttpMessages.IncomingHttpResponse = undefined! + sut.setThrottle(0) // $ExpectType IncomingHttpResponse + }) + }) + + describe('IncomingRequest', () => { + it('has any body by default', () => { + const sut: CyHttpMessages.IncomingRequest = undefined! + sut.body // $ExpectType any + }) + + it('has typed body if given', () => { + const sut: CyHttpMessages.IncomingRequest = undefined! + sut.body // $ExpectType CustomRequest + }) + }) + + describe('IncomingHttpRequest', () => { + it('has any body by default', () => { + const sut: CyHttpMessages.IncomingHttpRequest = undefined! + sut.body // $ExpectType any + }) + + it('has typed body if given', () => { + const sut: CyHttpMessages.IncomingHttpRequest = undefined! + sut.body // $ExpectType CustomRequest + }) + + it('accepts a typed interceptor, of the same expected response type, in continue()', () => { + const sut: CyHttpMessages.IncomingHttpRequest = undefined! + const input: HttpResponseInterceptor = undefined! + + sut.continue(input) + }) + + it('accepts a typed interceptor, of the same expected response type, in reply()', () => { + const sut: CyHttpMessages.IncomingHttpRequest = undefined! + const input: HttpResponseInterceptor = undefined! + + sut.reply(input) + }) + }) + + describe('ResponseComplete', () => { + it('has any finalResBody by default', () => { + const sut: CyHttpMessages.ResponseComplete = undefined! + sut.finalResBody // $ExpectType any + }) + + it('has typed finalResBody if given', () => { + const sut: CyHttpMessages.ResponseComplete = undefined! + sut.finalResBody // $ExpectType CustomResponse | undefined + }) + }) + + describe('HttpRequestInterceptor', () => { + it('accepts a request with any req/res body by default', () => { + const sut: HttpRequestInterceptor = undefined! + const request: CyHttpMessages.IncomingHttpRequest = undefined! + + sut(request) + }) + + it('accepts a request with a typed req/res body if given', () => { + const sut: HttpRequestInterceptor = undefined! + const request: CyHttpMessages.IncomingHttpRequest = undefined! + + sut(request) + }) + + it('does not accept a request with a typed req/res body if mismatched', () => { + const sut: HttpRequestInterceptor = undefined! + + // Request and response are flipped, which is incorrect. + const request: CyHttpMessages.IncomingHttpRequest = undefined! + + // @ts-expect-error -- Argument of type ... is not assignable. + sut(request) + }) + }) + + describe('HttpResponseInterceptor', () => { + it('accepts a response with any body by default', () => { + const sut: HttpResponseInterceptor = undefined! + const response: CyHttpMessages.IncomingHttpResponse = undefined! + + sut(response) + }) + + it('accepts a response with a typed body if given', () => { + const sut: HttpResponseInterceptor = undefined! + const response: CyHttpMessages.IncomingHttpResponse = undefined! + + sut(response) + }) + + it('does not accept a response with a typed body if mismatched', () => { + const sut: HttpResponseInterceptor = undefined! + + // Expecting a custom response, but response is just a string. + const response: CyHttpMessages.IncomingHttpResponse = undefined! + + // @ts-expect-error -- Argument of type ... is not assignable. + sut(response) + }) + }) + + describe('RequestEvents (via IncomingHttpRequest)', () => { + it('accepts a response with any body by default, in each on()', () => { + const sut: CyHttpMessages.IncomingHttpRequest = undefined! + const cb: HttpResponseInterceptor = undefined! + const cbAfter: (res: CyHttpMessages.IncomingResponse) => void = undefined! + + sut.on('before:response', cb) // $ExpectType IncomingHttpRequest + sut.on('response', cb) // $ExpectType IncomingHttpRequest + sut.on('after:response', cbAfter) // $ExpectType IncomingHttpRequest + }) + + it('accepts a response with a typed body if given', () => { + const sut: CyHttpMessages.IncomingHttpRequest = undefined! + const cb: HttpResponseInterceptor = undefined! + const cbAfter: (res: CyHttpMessages.IncomingResponse) => void = undefined! + + sut.on('before:response', cb) // $ExpectType IncomingHttpRequest + sut.on('response', cb) // $ExpectType IncomingHttpRequest + sut.on('after:response', cbAfter) // $ExpectType IncomingHttpRequest + }) + + it('does not accept a response with a typed body if given but mismatched', () => { + const sut: CyHttpMessages.IncomingHttpRequest = undefined! + + // Expecting a custom response, but callbacks just have mismatched string responses. + const cb: HttpResponseInterceptor = undefined! + const cbAfter: (res: CyHttpMessages.IncomingResponse) => void = undefined! + + // @ts-expect-error -- Argument of type ... is not assignable. + sut.on('before:response', cb) + + // @ts-expect-error -- Argument of type ... is not assignable. + sut.on('response', cb) + + // @ts-expect-error -- Argument of type ... is not assignable. + sut.on('after:response', cbAfter) + }) + }) + + describe('Interception', () => { + it('has any req/res body by default', () => { + const sut: Interception = undefined! + + sut.request.body // $ExpectType any + sut.response!.body // $ExpectType any + }) + + it('has typed req/res body if given', () => { + const sut: Interception = undefined! + + sut.request.body // $ExpectType CustomRequest + sut.response!.body // $ExpectType CustomResponse + }) + }) + + describe('Route', () => { + it('has a handler typed as any by default', () => { + const sut: Route = undefined! + const request: CyHttpMessages.IncomingHttpRequest = undefined! + + sut.handler // $ExpectType RouteHandler + + if (typeof sut.handler === 'function') { + sut.handler(request) + } + }) + + it('has a typed handler if given', () => { + const sut: Route = undefined! + const request: CyHttpMessages.IncomingHttpRequest = undefined! + + sut.handler // $ExpectType RouteHandler + + if (typeof sut.handler === 'function') { + sut.handler(request) + } + }) + + it('does not accept a typed handler if given but mismatched', () => { + const sut: Route = undefined! + + // Request and response are flipped, which is incorrect. + const request: CyHttpMessages.IncomingHttpRequest = undefined! + + if (typeof sut.handler === 'function') { + // @ts-expect-error -- Argument of type ... is not assignable. + sut.handler(request) + } + }) + + it('contains requests with interceptions of any req/res body by default', () => { + const sut: Route = undefined! + sut.requests['r'] // $ExpectType Interception + }) + + it('contains requests with interceptions of typed req/res body if given', () => { + const sut: Route = undefined! + sut.requests['r'] // $ExpectType Interception + }) + + it('contains requests with interceptions, which do not accept mismatches, of typed req/res body if given', () => { + const sut: Route = undefined! + + // Request and response are flipped, which is incorrect. + const interception: Interception = undefined! + + // @ts-expect-error -- Type ... is not assignable. + sut.requests['r'] = interception + }) + }) + + describe('RouteMap', () => { + it('each item has a handler typed as any by default', () => { + const sut: RouteMap = undefined! + const request: CyHttpMessages.IncomingHttpRequest = undefined! + + sut['r'] // $ExpectType Route + + if (typeof sut['r'].handler === 'function') { + sut['r'].handler(request) + } + }) + + it('each item has a typed handler if given', () => { + const sut: RouteMap = undefined! + const request: CyHttpMessages.IncomingHttpRequest = undefined! + + sut['r'] // $ExpectType Route + + if (typeof sut['r'].handler === 'function') { + sut['r'].handler(request) + } + }) + + it('each item does not accept a typed handler if given but mismatched', () => { + const sut: RouteMap = undefined! + + // Request and response are flipped, which is incorrect. + const request: CyHttpMessages.IncomingHttpRequest = undefined! + + if (typeof sut['r'].handler === 'function') { + // @ts-expect-error -- Argument of type ... is not assignable. + sut['r'].handler(request) + } + }) + + it('each item contains requests with interceptions of any req/res body by default', () => { + const sut: RouteMap = undefined! + + sut['r'] // $ExpectType Route + sut['r'].requests['r'] // $ExpectType Interception + }) + + it('each item contains requests with interceptions of typed req/res body if given', () => { + const sut: RouteMap = undefined! + + sut['r'] // $ExpectType Route + sut['r'].requests['r'] // $ExpectType Interception + }) + + it('each item contains requests with interceptions, which do not accept mismatches, of typed req/res body if given', () => { + const sut: RouteMap = undefined! + + // Request and response are flipped, which is incorrect. + const interception: Interception = undefined! + + // @ts-expect-error -- Type ... is not assignable. + sut['r'].requests['r'] = interception + }) + }) + + describe('RouteHandlerController', () => { + it('accepts a request with any req/res body by default', () => { + const sut: RouteHandlerController = undefined! + const request: CyHttpMessages.IncomingHttpRequest = undefined! + + sut(request) + }) + + it('accepts a request with a typed req/res body if given', () => { + const sut: RouteHandlerController = undefined! + const request: CyHttpMessages.IncomingHttpRequest = undefined! + + sut(request) + }) + + it('does not accept a request with a typed req/res body if mismatched', () => { + const sut: RouteHandlerController = undefined! + + // Request and response are flipped, which is incorrect. + const request: CyHttpMessages.IncomingHttpRequest = undefined! + + // @ts-expect-error -- Argument of type ... is not assignable. + sut(request) + }) + }) + + describe('RouteHandler', () => { + it('accepts a request with any req/res body by default', () => { + const sut: RouteHandler = () => { } + const request: CyHttpMessages.IncomingHttpRequest = undefined! + + if (typeof sut === 'function') { + sut(request) + } + }) + + it('accepts a request with a typed req/res body if given', () => { + const sut: RouteHandler = () => { } + const request: CyHttpMessages.IncomingHttpRequest = undefined! + + if (typeof sut === 'function') { + sut(request) + } + }) + + it('does not accept a request with a typed req/res body if mismatched', () => { + const sut: RouteHandler = () => { } + + // Request and response are flipped, which is incorrect. + const request: CyHttpMessages.IncomingHttpRequest = undefined! + + if (typeof sut === 'function') { + // @ts-expect-error -- Argument of type ... is not assignable. + sut(request) + } + }) + }) + + describe('cy.intercept', () => { + describe('for a route matcher URL', () => { + it('accepts any req/res body as response handler by default', () => { + const sut: Cypress.Chainable = undefined! + const url: RouteMatcher = undefined! + + sut.intercept(url, (req) => { + req.body // $ExpectType any + + req.continue((res) => { + res.body // $ExpectType any + }) + }) + }) + + it('accepts typed req/res body as response handler if given', () => { + const sut: Cypress.Chainable = undefined! + const url: RouteMatcher = undefined! + + sut.intercept(url, (req) => { + req.body // $ExpectType CustomRequest + + req.continue((res) => { + res.body // $ExpectType CustomResponse + }) + }) + }) + + it('infers types for req/res body if given', () => { + const sut: Cypress.Chainable = undefined! + const url: RouteMatcher = undefined! + + type Req = CyHttpMessages.IncomingHttpRequest + + sut.intercept(url, (req: Req) => { + req.body // $ExpectType CustomRequest + + req.continue((res) => { + res.body // $ExpectType CustomResponse + }) + }) + }) + }) + + describe('for a method-restricted route matcher URL', () => { + it('accepts any req/res body as response handler by default', () => { + const sut: Cypress.Chainable = undefined! + const url: RouteMatcher = undefined! + + sut.intercept('POST', url, (req) => { + req.body // $ExpectType any + + req.continue((res) => { + res.body // $ExpectType any + }) + }) + }) + + it('accepts typed req/res body as response handler if given', () => { + const sut: Cypress.Chainable = undefined! + const url: RouteMatcher = undefined! + + sut.intercept('POST', url, (req) => { + req.body // $ExpectType CustomRequest + + req.continue((res) => { + res.body // $ExpectType CustomResponse + }) + }) + }) + + it('infers types for req/res body if given', () => { + const sut: Cypress.Chainable = undefined! + const url: RouteMatcher = undefined! + + type Req = CyHttpMessages.IncomingHttpRequest + + sut.intercept('POST', url, (req: Req) => { + req.body // $ExpectType CustomRequest + + req.continue((res) => { + res.body // $ExpectType CustomResponse + }) + }) + }) + }) + + describe('for a string matcher URL', () => { + it('accepts any req/res body as response handler by default', () => { + const sut: Cypress.Chainable = undefined! + const url: StringMatcher = undefined! + + sut.intercept(url, { middleware: true }, (req) => { + req.body // $ExpectType any + + req.continue((res) => { + res.body // $ExpectType any + }) + }) + }) + + it('accepts typed req/res body as response handler if given', () => { + const sut: Cypress.Chainable = undefined! + const url: StringMatcher = undefined! + + sut.intercept(url, { middleware: true }, (req) => { + req.body // $ExpectType CustomRequest + + req.continue((res) => { + res.body // $ExpectType CustomResponse + }) + }) + }) + + it('infers types for req/res body if given', () => { + const sut: Cypress.Chainable = undefined! + const url: StringMatcher = undefined! + + type Req = CyHttpMessages.IncomingHttpRequest + + sut.intercept(url, { middleware: true }, (req: Req) => { + req.body // $ExpectType CustomRequest + + req.continue((res) => { + res.body // $ExpectType CustomResponse + }) + }) + }) + }) + }) + + describe('cy.wait', () => { + describe('with a single alias', () => { + it('accepts any req/res body as response handler by default', () => { + const cy: Cypress.Chainable = undefined! + + cy.wait('@a').then(({ request, response }) => { + request.body // $ExpectType any + response!.body // $ExpectType any + }) + }) + + it('accepts typed req/res body as response handler if given', () => { + const cy: Cypress.Chainable = undefined! + + cy.wait('@a').then(({ request, response }) => { + request.body // $ExpectType CustomRequest + response!.body // $ExpectType CustomResponse + }) + }) + + it('infers types for req/res body if given', () => { + const cy: Cypress.Chainable = undefined! + + cy.wait('@a').then(({ request, response }: Interception) => { + request.body // $ExpectType CustomRequest + response!.body // $ExpectType CustomResponse + }) + }) + }) + + describe('with an array of aliases', () => { + interface AReq { a: CustomRequest } + interface BReq { b: CustomRequest } + interface ARes { a: CustomResponse } + interface BRes { b: CustomResponse } + + it('accepts any req/res body as response handler by default', () => { + const cy: Cypress.Chainable = undefined! + + cy.wait([]).then((interceptions) => { + interceptions // $ExpectType Interception[] + }) + + cy.wait(['@a']).then((interceptions) => { + interceptions.forEach(({ request, response }) => { + request.body // $ExpectType any + response!.body // $ExpectType any + }) + }) + + cy.wait(['@a', '@b']).then((interceptions) => { + interceptions.forEach(({ request, response }) => { + request.body // $ExpectType any + response!.body // $ExpectType any + }) + }) + }) + + it('infers types for req/res body if given', () => { + const cy: Cypress.Chainable = undefined! + + cy.wait(['@a']).then((interceptions: Array>) => { + interceptions.forEach(({ request, response }) => { + request.body // $ExpectType AReq + response!.body // $ExpectType ARes + }) + }) + + cy.wait(['@a', '@b']).then((interceptions: Array>) => { + interceptions.forEach(({ request, response }) => { + request.body // $ExpectType AReq | BReq + response!.body // $ExpectType ARes | BRes + }) + }) + }) + }) + }) +}) diff --git a/packages/net-stubbing/lib/external-types.ts b/packages/net-stubbing/lib/external-types.ts index 1d013e555d23..464546d73b3f 100644 --- a/packages/net-stubbing/lib/external-types.ts +++ b/packages/net-stubbing/lib/external-types.ts @@ -1,91 +1,91 @@ // Copied from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/methods/index.d.ts type Method = - | 'ACL' - | 'BIND' - | 'CHECKOUT' - | 'CONNECT' - | 'COPY' - | 'DELETE' - | 'GET' - | 'HEAD' - | 'LINK' - | 'LOCK' - | 'M-SEARCH' - | 'MERGE' - | 'MKACTIVITY' - | 'MKCALENDAR' - | 'MKCOL' - | 'MOVE' - | 'NOTIFY' - | 'OPTIONS' - | 'PATCH' - | 'POST' - | 'PROPFIND' - | 'PROPPATCH' - | 'PURGE' - | 'PUT' - | 'REBIND' - | 'REPORT' - | 'SEARCH' - | 'SOURCE' - | 'SUBSCRIBE' - | 'TRACE' - | 'UNBIND' - | 'UNLINK' - | 'UNLOCK' - | 'UNSUBSCRIBE' - | 'acl' - | 'bind' - | 'checkout' - | 'connect' - | 'copy' - | 'delete' - | 'get' - | 'head' - | 'link' - | 'lock' - | 'm-search' - | 'merge' - | 'mkactivity' - | 'mkcalendar' - | 'mkcol' - | 'move' - | 'notify' - | 'options' - | 'patch' - | 'post' - | 'propfind' - | 'proppatch' - | 'purge' - | 'put' - | 'rebind' - | 'report' - | 'search' - | 'source' - | 'subscribe' - | 'trace' - | 'unbind' - | 'unlink' - | 'unlock' - | 'unsubscribe' + | 'ACL' + | 'BIND' + | 'CHECKOUT' + | 'CONNECT' + | 'COPY' + | 'DELETE' + | 'GET' + | 'HEAD' + | 'LINK' + | 'LOCK' + | 'M-SEARCH' + | 'MERGE' + | 'MKACTIVITY' + | 'MKCALENDAR' + | 'MKCOL' + | 'MOVE' + | 'NOTIFY' + | 'OPTIONS' + | 'PATCH' + | 'POST' + | 'PROPFIND' + | 'PROPPATCH' + | 'PURGE' + | 'PUT' + | 'REBIND' + | 'REPORT' + | 'SEARCH' + | 'SOURCE' + | 'SUBSCRIBE' + | 'TRACE' + | 'UNBIND' + | 'UNLINK' + | 'UNLOCK' + | 'UNSUBSCRIBE' + | 'acl' + | 'bind' + | 'checkout' + | 'connect' + | 'copy' + | 'delete' + | 'get' + | 'head' + | 'link' + | 'lock' + | 'm-search' + | 'merge' + | 'mkactivity' + | 'mkcalendar' + | 'mkcol' + | 'move' + | 'notify' + | 'options' + | 'patch' + | 'post' + | 'propfind' + | 'proppatch' + | 'purge' + | 'put' + | 'rebind' + | 'report' + | 'search' + | 'source' + | 'subscribe' + | 'trace' + | 'unbind' + | 'unlink' + | 'unlock' + | 'unsubscribe' export type ResourceType = 'document' | 'fetch' | 'xhr' | 'websocket' | 'stylesheet' | 'script' | 'image' | 'font' | 'cspviolationreport' | 'ping' | 'manifest' | 'other' export namespace CyHttpMessages { - export interface BaseMessage { + export interface BaseMessage { /** * The body of the HTTP message. * If a JSON Content-Type was used and the body was valid JSON, this will be an object. * If the body was binary content, this will be a buffer. */ - body: any + body: T /** * The headers of the HTTP message. */ headers: { [key: string]: string | string[] } } - export type IncomingResponse = BaseMessage & { + export type IncomingResponse = BaseMessage & { /** * The HTTP status code of the response. */ @@ -104,7 +104,7 @@ export namespace CyHttpMessages { delay?: number } - export type IncomingHttpResponse = IncomingResponse & { + export type IncomingHttpResponse = IncomingResponse & { /** * Continue the HTTP response, merging the supplied values with the real response. */ @@ -118,14 +118,14 @@ export namespace CyHttpMessages { /** * Wait for `delay` milliseconds before sending the response to the client. */ - setDelay: (delay: number) => IncomingHttpResponse + setDelay: (delay: number) => IncomingHttpResponse /** * Serve the response at `throttleKbps` kilobytes per second. */ - setThrottle: (throttleKbps: number) => IncomingHttpResponse + setThrottle: (throttleKbps: number) => IncomingHttpResponse } - export type IncomingRequest = BaseMessage & { + export type IncomingRequest = BaseMessage & { /** * Request HTTP method (GET, POST, ...). */ @@ -137,7 +137,7 @@ export namespace CyHttpMessages { /** * URL query string as object. */ - query: Record + query: Record /** * The HTTP version used in the request. Read only. */ @@ -163,7 +163,7 @@ export namespace CyHttpMessages { alias?: string } - export interface IncomingHttpRequest extends IncomingRequest, RequestEvents { + export interface IncomingHttpRequest extends IncomingRequest, RequestEvents { /** * Destroy the request and respond with a network error. */ @@ -173,7 +173,7 @@ export namespace CyHttpMessages { * If a function is passed, the request will be sent outgoing, and the function will be called * with the response from the upstream server. */ - continue(interceptor?: HttpResponseInterceptor): void + continue(interceptor?: HttpResponseInterceptor): void /** * Control the response to this request. * If a function is passed, the request will be sent outgoing, and the function will be called @@ -181,7 +181,7 @@ export namespace CyHttpMessages { * If a `StaticResponse` is passed, it will be used as the response, and no request will be made * to the upstream server. */ - reply(interceptor?: StaticResponse | HttpResponseInterceptor): void + reply(interceptor?: StaticResponse | HttpResponseInterceptor): void /** * Shortcut to reply to the request with a body and optional headers. */ @@ -197,8 +197,8 @@ export namespace CyHttpMessages { redirect(location: string, statusCode?: number): void } - export interface ResponseComplete { - finalResBody?: BaseMessage['body'] + export interface ResponseComplete { + finalResBody?: BaseMessage['body'] } export interface NetworkError { @@ -220,14 +220,14 @@ export type GlobPattern = string * request to the next handler (if there is one), otherwise the request will be passed to the next * handler synchronously. */ -export type HttpRequestInterceptor = (req: CyHttpMessages.IncomingHttpRequest) => void | Promise +export type HttpRequestInterceptor = (req: CyHttpMessages.IncomingHttpRequest) => void | Promise /** * Interceptor for an HTTP response. If a Promise is returned, it will be awaited before passing the * request to the next handler (if there is one), otherwise the request will be passed to the next * handler synchronously. */ -export type HttpResponseInterceptor = (res: CyHttpMessages.IncomingHttpResponse) => void | Promise +export type HttpResponseInterceptor = (res: CyHttpMessages.IncomingHttpResponse) => void | Promise /** * Matches a single number or any of an array of acceptable numbers. @@ -248,44 +248,44 @@ export interface Subscription { skip?: boolean } -interface RequestEvents { +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): this + 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): this + 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): this + on(eventName: 'after:response', cb: (res: CyHttpMessages.IncomingResponse) => void | Promise): this } /** * Request/response cycle. */ -export interface Interception { +export interface Interception { id: string /* @internal */ browserRequestId?: string routeId: string /* @internal */ setLogFlag: (flag: 'spied' | 'stubbed' | 'reqModified' | 'resModified') => void - request: CyHttpMessages.IncomingRequest + request: CyHttpMessages.IncomingRequest /** * Was `cy.wait()` used to wait on this request? * @internal */ requestWaited: boolean - response?: CyHttpMessages.IncomingResponse + response?: CyHttpMessages.IncomingResponse /** * The error that occurred during this request. */ @@ -312,17 +312,17 @@ export type InterceptionState = 'Complete' | 'Errored' -export interface Route { +export interface Route { alias?: string log: any options: RouteMatcherOptions - handler: RouteHandler + handler: RouteHandler hitCount: number - requests: { [key: string]: Interception } + requests: { [key: string]: Interception } command: any } -export interface RouteMap { [key: string]: Route } +export interface RouteMap { [key: string]: Route } /** * A `RouteMatcher` describes a filter for HTTP requests. @@ -393,9 +393,9 @@ export interface RouteMatcherOptionsGeneric { url?: S } -export type RouteHandlerController = HttpRequestInterceptor +export type RouteHandlerController = HttpRequestInterceptor -export type RouteHandler = string | StaticResponseWithOptions | RouteHandlerController | object +export type RouteHandler = string | StaticResponseWithOptions | RouteHandlerController | object export type InterceptOptions = { /** @@ -510,7 +510,7 @@ declare global { * }) * }) */ - intercept(url: RouteMatcher, response?: RouteHandler): Chainable + intercept(url: RouteMatcher, response?: RouteHandler): Chainable /** * Use `cy.intercept()` to stub and intercept HTTP requests and responses. * @@ -518,7 +518,7 @@ declare global { * @example * cy.intercept('GET', 'http://foo.com/fruits', ['apple', 'banana', 'cherry']) */ - intercept(method: Method, url: RouteMatcher, response?: RouteHandler): Chainable + intercept(method: Method, url: RouteMatcher, response?: RouteHandler): Chainable /** * Use `cy.intercept()` to stub and intercept HTTP requests and responses. * @@ -529,7 +529,7 @@ declare global { * * @param mergeRouteMatcher Additional route matcher options to merge with `url`. Typically used for middleware. */ - intercept(url: StringMatcher, mergeRouteMatcher: Omit, response: RouteHandler): Chainable + intercept(url: StringMatcher, mergeRouteMatcher: Omit, response: RouteHandler): Chainable /** * Wait for a specific request to complete. * @@ -548,7 +548,7 @@ declare global { }) ``` */ - wait(alias: string, options?: Partial): Chainable + wait(alias: string, options?: Partial): Chainable> /** * Wait for list of requests to complete. * @@ -568,7 +568,7 @@ declare global { }) ``` */ - wait(alias: string[], options?: Partial): Chainable + wait(aliases: string[], options?: Partial): Chainable } } }