cy.intercept() not stubbing API in Cypress

44.3k views Asked by At

When I use cy.intercept(), the API does not stub.

cy.intercept("GET", `${API}farm/list`, {
  body: {
    statusCode: 200,
    message: "Request successful",
    result: seededFarmList,
  },
});

I am importing the fixture file like this:

import { seededFarmList } from '../../../../../fixtures/farm'; 

My API response looks like this:

{
  "statusCode": 200, 
  "message": "Request successful", 
  "result": [ 
    { "id": 1 "farmName": "ABCD", },
    { "id": 2 "farmName": "EFGH", }
  ]
}

Any help would be appreciated.

7

There are 7 answers

2
Richard Matsen On

I managed to get stubbing working with the pattern @eric99 gave,

cy.intercept(
  'GET',
  'https://jsonplaceholder.typicode.com/todos/1',
  {
    statusCode: 200,
    body: {
      message: 'Request successful',
      result: ['my-data']
    }
  }
)
.as('typicode')

cy.visit('https://jsonplaceholder.typicode.com/')
cy.get('#run-button').click();

cy.wait('@typicode')
.then((interception) => {
  console.log('interception', interception)
})

The page shows the stub information,

{
    "message": "Request successful",
    "result": [
        "my-data"
    ]
}
3
AudioBubble On

I'm not entirely sure why it's not stubbing (presume you mean the server response is getting through?).

In any case, the stubbed response pattern is now a lot more complicated, and it's going to trip up a lot of people.

Here's my interpretation of the documentation,

In cy.route(method, url, response), response documented as body

Supply a response body to stub in the matching route.

In cy.intercept(method, url, routeHandler?), routeHandler is a more complicated beast.

routeHandler (string | object | Function | StaticResponse)

but object and StaticResponse are both objects - Cypress makes the distinction by looking at the object keys, according to this

If an object with no StaticResponse keys is passed, it will be sent as a JSON response body.

StaticResponse keys are

{
  fixture?: string
  body?: string | object | object[]
  headers?: { [key: string]: string }
  statusCode?: number
  forceNetworkError?: boolean
  delayMs?: number
  throttleKbps?: number
}

Since you are sending statusCode, your object is a StaticResponse, and therefore message and result should be moved to body,

cy.intercept('GET',
  `${API}farm/list`,
  {
    statusCode: 200,
    body: {
      message: 'Request successful',
      result: seededFarmList
    }
  }
);

IMO they've over-engineered things a little - the fallback from StaticResponse to object (depending on keys) is a bit unnecessary.


I just found an example in the sample spec network_requests.spec.js (added on Cypress 1st run).

beforeEach(() => {
  cy.visit('https://example.cypress.io/commands/network-requests')
})

...

let message = 'whoa, this comment does not exist'

// Stub a response to PUT comments/ ****
cy.intercept({
  method: 'PUT',
  url: '**/comments/*',
}, {
  statusCode: 404,
  body: { error: message },                         // stub returns above message
  headers: { 'access-control-allow-origin': '*' },
  delayMs: 500,
}).as('putComment')

// we have code that puts a comment when
// the button is clicked in scripts.js
cy.get('.network-put').click()

cy.wait('@putComment')

// our 404 statusCode logic in scripts.js executed
cy.get('.network-put-comment').should('contain', message)
0
Alireza On

I had this issue before then I found out that it was caused by CORS policy.

There are some solutions to overcome this issue:

0
Jakob Jan Kamminga On

Cypress doesn't seem to resolve the route matcher params if you use template literals in the route matcher pattern.

Does not work:

cy.intercept('GET', `/.*${mybaseUrl}\/something\/.*/`)

(even though the pattern is valid, and it even shows up right in Cypress!)

There are 2 ways I have found to make it work.

  1. Explicate the url with the routematcher parameter:
cy.intercept(
          {
            method: 'GET',
            url: `.*${mybaseUrl}\/something\/.*`
          })
  1. Use RegExp constructor
cy.intercept('GET', new RegExp(`.*${mybaseUrl}\/something\/.*`)

It does look like a bug in Cypress, but these are two very acceptable workarounds.

0
Owen Wexler On

Not sure if you are using getServerSideProps() or any of the Next's other SSR methods, but if you are, cy.intercept() will not work as the API call is done server-side. You will have to use nock to intercept and mock any server-side API calls done within getServerSideProps() or any similar server-side methods in Next.

Comprehensive reading on this subject here: https://glebbahmutov.com/blog/mock-network-from-server/

2
darmis On

Make sure the network intercept is registered before the application makes the api call. Notice the cy.intercept is set up before cy.visit.

it('is registered correctly', () => {
  cy.intercept('/todos').as('todos')
  cy.visit('/')
  cy.wait('@todos')
})

In the following example cy.intercept is set up after cy.visit and this might fail.

 it('is registered too late, this might fail', () => {
    cy.visit('/')
    cy.intercept('/todos').as('todos')
    cy.wait('@todos')
  })
0
sofina On

I did this, and it stubbed the API.

cy.intercept(
          {
            method: 'GET',
            url: `${API}farm/list`
          },

          {
            body: {
              statusCode: 200,
              message: 'Request successful',
              result: seededFarmList
            }
          }
        ).as('loadData');