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
4 Answers
Reset to default 6I 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
});
}
}
},
});