cypress-io / cypress

Fast, easy and reliable testing for anything that runs in a browser.

Home Page:https://cypress.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Enhance typings for cy.intercept and cy.wait

scottmcginness opened this issue · comments

What would you like?

In order to have request and response types for the body property in calls to cy.intercept and cy.wait, I'd like to be able to specify generics for these, so that I don't have to use any in the callbacks.

Specifically:

cy.intercept<CustomRequest, CustomResponse>(url, (req) => {
  req.body // ← this should be a CustomRequest

  req.continue((res) => {
    res.body // ← this should be a CustomResponse
  })
})

and

cy.wait<CustomRequest, CustomResponse>('@alias').then(({ request, response }) => {
  request.body // ← this should be a CustomRequest
  response.body // ← this should be a CustomResponse
})

Why is this needed?

While looking at converting our project to TypeScript, I was surprised that we'd have to either:

  • use any for the body parameter in all callbacks of intercept and wait
  • manually specify the interception type to get types in those calls, such as:
cy.intercept('/url', (req: CyHttpMessages.IncomingHttpRequest) => {
  (req.body as CustomRequest).payload = {};

  req.continue(res => {
    expect((res.body as CustomResponse).data).to.exist;
  })
}).as('alias')

which still requires as if we want to keep full type safety.

This feels especially awkward because we have wrapped some wait calls to their own methods:

const whenComplete = (expectations: ((i: { request: CyHttpMessages.IncomingRequest, response?: CyHttpMessages.IncomingResponse }) => void)) => cy.wait('@alias').then(expectations);

whenComplete(({ request, response }) => {
  expect((request.body as CustomRequest).payload).to.exist
  expect((response?.body as CustomResponse).data).to.exist
})

Instead. with the proposal above, it is marginally easier and less error prone to write:

const whenComplete = (expectations: ((i: Interception<CustomRequest, CustomResponse>) => void)) => cy.wait('@alias').then(expectations);

whenComplete(({ request, response }) => {
  expect(request.body.payload).to.exist // ← here the request type is known
  expect(response?.body.data).to.exist // ← here the response type is known
})

We do have these types (CustomRequest and CustomResponse as examples) already defined, so would be good if we can use them easily everywhere.

Other

I have a fork that puts a type on the core BaseMessage interface, for body. This caused all the related types to have required updates to their types (i.e. made generic too).
I might have missed a better way to think about or do this.