Cypress: Stub response for same route with three d

2019-05-06 23:38发布

问题:

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?

回答1:

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'
      : ''
  }
})


回答2:

I did one dirty work around that worked, I didn't like it but I am out of options.

I simply combined all the responses in the same response.

My Mock Response

{
  balance: {..},
  transactionHistory: {..},
  currencyRates: {..}
}

The each response handler simply processes part it is interested in, if one of the response is array, we'll need to change it to an object.

I'll be on a lookout for a better work around.



回答3:

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 )