最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Cypress: Stub response for same route with three different responses - Stack Overflow

programmeradmin10浏览0评论

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?

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?

Share Improve this question edited Nov 4, 2019 at 10:06 Gabriel Felvinczi 331 silver badge8 bronze badges asked Dec 6, 2018 at 15:27 Digvijay UpadhyayDigvijay Upadhyay 7591 gold badge12 silver badges25 bronze badges 4
  • sorry, not understanding does each request have a query string or something that make them unique.. Is the action going in the the body? – Maccurt Commented Dec 6, 2018 at 15:48
  • Just edited the question with more sample payloads. Yes the action in payload is different and unique for each request – Digvijay Upadhyay Commented Dec 6, 2018 at 15:51
  • I was going to suggest writing the response as a function that returns one of the 3 payloads in order, until I read your last line. I think you might be SOL. – Brendan Commented Dec 6, 2018 at 17:37
  • Try this one : softans./question/… – GHULAM NABI Commented Feb 8, 2023 at 12:56
Add a ment  | 

4 Answers 4

Reset to default 6

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

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

I simply bined 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.

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 )

if anyone es to this question I probably found another hack, that worked for me (I'm using unfetch polyfill to work around fetch requests and cypress) - here is the code for one route.

cy.route({
  url: '/api/ngfw/devices/search',
  method: 'POST',

  // Default response, when parametrs doesn't match
  response: [],

  onResponse: (xhr) => {
    xhr.response = { body: [] };
    const { body } = xhr.request;

    if (body.groupBy) {
      const [groupBy] = body.groupBy;
      if (groupBy === 'overallColor') {
        Object.defineProperty(xhr.xhr, 'responseText', {

          // Putting response inside
          value: JSON.stringify(mockData.totalsResult),

          enumerable: true
        });
      }
    }
  },
});

发布评论

评论列表(0)

  1. 暂无评论