Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cypress: Stub response for same route with three different responses

I have a single endpoint in the application. We hit the same api for each request with different action in the params.

URL:

/application/api

Sample Request Payload 1:

{
  "action": "CARD_TRANSACTION_HISTORY",
  "data": {
    "date_from": "2018-12-01",
    "date_to": "2018-12-31",
    "total": 5
  },
  "meta": {}
}

Sample Request Payload 2:

{
  "action": "CARD_BALANCE",
  "data": {
    "date_from": "2018-12-01",
    "date_to": "2018-12-31",
    "total": 5
  },
  "meta": {}
}

Sample Request Payload 3:

{
  "action": "CURRENCY_RATES",
  "data": {
    "date_from": "2018-12-01",
    "date_to": "2018-12-31",
    "total": 5
  },
  "meta": {}
}

the action in above request changes for different requests.

When the dashboard page is loaded, we trigger 3 concurrent AJAX POST requests with different actions.

Problem with cypress is you can only specify one response for a route, and other way to handle this is make sequential requests (which we can't do)

Even if we write response as a function it gets called only once.

Any ideas on how we can mock data on the basis of payload?

like image 767
Digvijay Upadhyay Avatar asked Dec 06 '18 15:12

Digvijay Upadhyay


People also ask

What is the difference between Cy request and Cy intercept?

cy. intercept does not make a request, but rather "listens" to requests that occur on the network layer. If we "ask" Cypress to name a certain request that we expect to occur after some action, we can also "ask" it to wait for it before moving on when it notices that such a request occurred. That is, cy.

What is the use of intercept in Cypress?

By specifying a routeHandler function as the last argument to cy.intercept , you'll have access to the entire request-response session, enabling you to modify the outgoing request, manipulate the real response, make assertions, etc.


2 Answers

I had the exact same problem and found @Richard Matsen's answer very useful, however when using the whitelist option it isn't possible to access proxy.request, which returns undefined. But if you use onRequest instead of whitelist, you can access the request and thus implement any action depending on that request's body.

So this should work:

cy.server({
  onRequest: (xhr) => {
    xhr.url = xhr.url + 
      xhr.request.body.action  == 'CARD_TRANSACTION_HISTORY' ? '?transactionHistory'
      : xhr.request.body.action  == 'CARD_BALANCE' ? '?balance'
      : xhr.request.body.action  == 'CURRENCY_RATES' ? '?currencyRates'
      : ''
  }
})
like image 74
nicojonck Avatar answered Sep 20 '22 07:09

nicojonck


Here is another hack. It relies on your api ignoring url parameters and that the cy.server whitelist function is called before the request is made.

cy.server({
  whitelist: (proxy) => {
    proxy.url = proxy.url + 
      proxy.request.body.action  == 'CARD_TRANSACTION_HISTORY' ? '?transactionHistory'
      : proxy.request.body.action  == 'CARD_BALANCE' ? '?balance'
      : proxy.request.body.action  == 'CURRENCY_RATES' ? '?currencyRates'
      : ''
  }
})

const apiMocks = {
  balance: {..},
  transactionHistory: {..},
  currencyRates: {..}
}
cy.route('/application/api?balance', apiMocks.balance).as('balance')
cy.route('/application/api?transactionHistory', apiMocks.transactionHistory)
  .as('transactionHistory')
cy.route('/application/api?currencyRates', apiMocks.currencyRates).as('currencyRates')

cy.visit(...)

cy.wait('@balance').then(xhr => //should see correct mock here )
like image 36
Richard Matsen Avatar answered Sep 18 '22 07:09

Richard Matsen