Cypress - get value from json response body - javascript

I'm using Cypress to do some API testing, but I am struggling to access values in the JSON response body; however I can perform assertions against the body which suggests it's receiving it correctly.
Below I am trying to assign the JSON body (response.body) and then get the value of 'id' out of it:
describe('Creating a board', () => {
it('should create a board', () => {
cy.request({
method : 'POST',
url:`${requestUrl}/boards/`,
qs: {
name : "test-board",
token : token,
key : key
}
}).then((response) => {
expect(response).property('status').to.equal(200)
expect(response.body).property('id').to.not.be.oneOf([null, ""])
const body = (response.body)
boardId = body['id']
})
})
I've done numerous searches and can't find a concrete way to do it. Any help would be appreciated...

I managed to solve this by using a Promise;
Doing some further reading, I found out the then function I am executing is synchronous (I'm new to JS, pls don't hurt me).
I refactored the then function to the following:
.then((response) => {
return new Promise(resolve => {
expect(response).property('status').to.equal(200)
expect(response.body).property('id').to.not.be.oneOf([null, ""])
const respBody = response.body;
boardId = respBody['id']
resolve(boardId)
})
It's probably not entirely correct or best practice, but it will do for my demo

Although not needed anymore as you found a workaround, I've looked into my cypress code. I was able to access properties of response body followingly:
cy.request({
...
}.its('body').then((body) => {
const whatever = body.whatever;
})
I believe it basically works the same as your workaround - waiting to resolve body in a promise.

I was able to do it in the following way:
cy.request(
'POST',
url,
payload()).then((response) => {
expect(response.body).to.have.property('ReturnCode', 'Success')
expect(response.body).to.have.property('ReturnText', 'Success')
expect(response.body).to.have.property('PaymentInstructionId')
paymentID = response.body.PaymentInstructionId
})
paymentID is the variable that is filled with the value that i want from the repply.

Related

Axios GET request (from backend) with object as parameter

I'm having a lot of trouble using axios to send requests to this API, which accepts parameters in an object fashion:
GET https://api.osrsbox.com/items?where={ "name": "Abyssal whip", "duplicate": false }
The main problem is that axios automatically encodes the string. Searching for solutions in StackOverflow, i've came to this:
const item = "Abyssal Whip"
const config = {
paramsSerializer: (params) => {
return querystring.stringify(params, { arrayFormat: 'brackets' });
},
params: {
where : {
name: item,
duplicate: false
}
}
}
axios.get("https://api.osrsbox.com/items", config).then( (resp) => {
[...]
})
This results in the following request:
https://api.osrsbox.com/items?where=%7B%22name%22:%22Abyssal%20Whip%22,%22duplicate%22:false%7D
I would like to know what am i doing wrong. Thanks in advance.
PS: I'm making requests from a Node.js environment/server.
That's a really weird format that your API accepts. But I suppose it's what you've got to work with...
It looks to me like you might be successful by changing the relevant part of your code to:
where: JSON.stringify({
name: item,
duplicate: false
})
(I hope the spaces in your example request aren't required, if they are then this won't work)
you have to use npm package "qs"
npm i qs
make a object which has all your request body params eg -
const requestBody = {
....... ;
}
now while making Axios request -
Axios.get("https://api.osrsbox.com/items", qs.stringyfy(requestBody), config)
.then(res => console.log(res)
.catch(err => console.log(err))

Capture all XHR Requests with Cypress.io

When I call the URL, an undefined number of requests are sent.
Now I try to find out if one of the requests contains a certain payload.
cy.server();
cy.visit(url);
cy.route({
method: 'POST',
url: '**/t/e/**',
}).as('xhrRequest');
I have found a similar approach on How to capture all API calls in cypress? so far.
the problem here is that a fixed number of API calls is assumed.
cy.wait(Array(60).fill('#xhrRequest'), { timeout: 30000 }).then((xhrs) => {
xhrs.forEach((res) => {
expect(res.status).not.to.be.null
})
})
How do I get it that all requests are intercepted and fail my test if there is not a single request containing the payload.
I already wrote something like this in puppeteer
let hasSpecialRequest = false;
page.on('request', request => {
if (isSpecialRequest(request)) {
hasSpecialRequest = true;
}
request.continue();
});
await page.setRequestInterception(true);
expect(hasSpecialRequest).to.equal(true);
The system checks whether each request is one of the special requests and sets the variable accordingly. Something like this I try to recreate with Cypress.
You might consider doing cy.exec and run a script in another language and return status from subprocess.
I may have misunderstood the problem but since I got here through my Google expedition maybe this might help someone that had my problem and possibly you.
At first I used the cy.wait(#alias) but could never retrieve all the responses (only one response was being shown and I couldn't figure out how to access ALL the responses). So I ended up immediately storing the responses into another array to access within the test.
let xhrRequests;
function getXhrRequests() {
xhrRequests = [];
cy.intercept('GET', '**', (res) => {
xhrRequests.push(res);
});
return xhrRequests;
}
describe('Some', function () {
it('Thing 1', () => {
let thing1 = getXhrRequests();
cy.visit('http://some.site');
thing1.forEach((res) => {
expect(res.status).not.to.be.null;
})
}
it('Thing 2', () => {
let thing2 = getXhrRequests();
cy.visit('http://some.site/2');
thing2.forEach((res) => {
expect(res.status).not.to.be.null;
})
}
});

React - How to sync front-end with back-end requests without using setTimeout?

When I'm trying to do a validation in react JS I normally have to create a set time out function to sync the fetch api calls with front end as the fetch api calls take a bit of time. Is there are any other way to do this? Something that's under best practices and not recurring codes?
I have been using set time out with 4000-5000, it works, but i feel as if that's not the best way to do so.
edit-
Below is the code snippet of what i did before using timeout, but for some reason when the function runs, 'existingTrains' disappears from state.
async getExistingReservations(date, trackNo, direction, noTickets) {
let self = this;
var trains;
var ticketRange = 100 - noTickets;
var data = {
"date": date,
"trackNo": trackNo,
"direction": direction
}
console.log(data);
//get Existing Reservation Details
await fetch('http://localhost:5000/resRecords/getSeats', {
method: 'POST',
body: JSON.stringify(data),
headers: {'Content-Type': 'application/json'}
})
.then(response => {
return response.json()
})
.then(json => {
console.log(json)
trains = json.find(function (tickets) {
return tickets.noTickets < ticketRange
})
self.setState({
existingTrains: trains
}
)
});
}
The best way to resolve this is by using async -> await.
const getNetworkRequest = async (): string => {
const r = await makeNetworkRequest();
console.log(r);
if(r.data){ return 'got it!' }
return 'no data :(';
}

put request works for one api but not for another api

I tested with two apis for axios put.
for one api its working fine where as with another api it throws an error.
for one api its showing request as options eventhough I gave as put and I am seeing 403 forbidden error
for this api i am facing the issue 'http:///sports/sportsId',
I debugged but still I am not able to find the issue.
is it a back-end issue
can you tell me how to fix it, providing my code snippet below
savesports = () => {
console.log("savesports---->");
console.log(this.state.sports);
let savesports = this.state.sports;
savesports.updatedBy = 'xxx';
savesports.priceRuleDescription = "test description";
let data = {
name: "yyyy",
email: "sda#gmail.com",
phone: "2321313"
};
axios
.put("https://jsonplaceholder.typicode.com/users/1", data)
.then(r => console.log("dada", r));
console.log(JSON.stringify(savesports));
axios
.put(
'http:///sports/sportsId',
savesports
// { headers: { 'Content-Type': 'application/json' } }
)
.then(r => console.log(r))
.catch(e => console.log(e));
//this.toggleDrawer("right", false);
this.setState({ right: false });
this.setState({ snackBarOpen: true });
setTimeout(() => {
this.setState({ snackBarOpen: false });
}, 6000)
};
1. Check if URL is right
I would first check if the URL is right.
Try changing http:///sports/sportsId to http://sports/sportsId if that's actually the URL you are requesting to.
2. Avoid name confusion
Both the method name and the put data variable name are the same (savesports). I would change the put data variable name to something meaningful like
let sportsData = this.state.sports;
sportsData.updatedBy = 'xxx';
sportsData.priceRuleDescription = 'test description';
3. Check authentication
403 might also be to auth error. I would check if the endpoint requires any authentication token or headers.

How do I access data from a fetch in a get method?

Okay, so I feel like this is way more trivial than it needs to be, but for some reason, I cannot get information out of my "body" when it is passed to the get method. I've tried a number of different ways to access it, but nothing sees to do the trick. Guidance is much appreciate. Below is my code:
---------------fetch method----------------
var x = e.target.phone.value;
var y = e.target.email.value;
console.log(x); // proper output
console.log(y); // proper output
fetch('/api/insert',
{
accept: 'application/json',
body: {
phone2: x,
email2: y
}
});
------------get method--------------
app.get('/api/insert', (req, res) => {
const phone = req.body.phone2; <-- Am I accessing the data incorrectly?
const email = req.body.email2; <-- Am I accessing the data incorrectly?
console.log(phone); // getting undefined here... Why?
console.log(email); // and here...
});
});
You need to use req.query.phone2 and req.query.email2.
Parameters for a GET request are sent as query parameters on the URL (no body is sent with a GET request) and Express puts query parameters in req.query.
I think you should call it like this:
fetch('......')
.then((response) => response.json())
.then((responseJson) => {
return responseJson.movies;
})
.catch((error) => {
console.error(error);
});

Categories

Resources