Cypress: How to access the body of a POST-request? - integration-testing

Is there a way in Cypress to check the body of a POST-request?
E.g.: I have entered some data in a form, then pressed "Submit".
The form-data is send via POST-request, separated by a blank line from the header-data.
I would like to check the form-data. If all data, which I have entered, are included and if they are correct.
Is that possible with Cypress?
cy.get('#login').then(function (xhr) {
const body = xhr.requestBody;
console.log(xhr);
expect(xhr.method).to.eq('POST');
});
The xhr-object doesn't have the transferred data included.

It should be possible.
describe('Capturing data sent by the form via POST method', () => {
before(() => {
Cypress.config('baseUrl', 'https://www.reddit.com');
cy.server();
cy.route({
method: 'POST',
url: '/login'
}).as('redditLogin');
});
it('should capture the login and password', () => {
cy.visit('/login');
cy.get('#loginUsername').type('username');
cy.get('#loginPassword').type('password');
cy.get('button[type="submit"]').click();
cy.wait('#redditLogin').then(xhr => {
cy.log(xhr.responseBody);
cy.log(xhr.requestBody);
expect(xhr.method).to.eq('POST');
})
});
});
This is how you can inspect your data in Chrome Developer Tool.
You should see the same thing you've seen from Chrome Developer Tool when you run your test in Cypress.

I was Googling the same problem and somehow landed here before reaching the documentation.
Anyway, have you tried something like:
cy.wait('#login').should((xhr) => {
const body = xhr.request.body
expect(body).to.match(/email/)
})
I haven't tested it out with a multipart/form-data encoded request, but I suspect that you'll also find the request body that way.
Good luck!

It's better to use cy.intercept() in order to spy, stub and assert network requests and responses.
// assert that a request to this route
// was made with a body that included 'user'
cy.wait('#someRoute').its('request.body').should('include', 'user')
// assert that a request to this route
// received a response with HTTP status 500
cy.wait('#someRoute').its('response.statusCode').should('eq', 500)
// assert that a request to this route
// received a response body that includes 'id'
cy.wait('#someRoute').its('response.body').should('include', 'id')
Link to the docs

Related

Request has incorrect content type when using Twilio and Google Cloud Functions

I am following this Twilio tutorial on how to reply to SMS messages with my app:
https://www.twilio.com/docs/sms/tutorials/how-to-receive-and-reply-node-js
The tutorial assumes you're using Express, but I am doing this with a Cloud Function, so my code looks a bit different:
exports.sms = functions.https.onCall((req: any, res: any) => {
const twiml = new MessagingResponse();
if (req.body.Body === 'hello') {
twiml.message('Hi!');
} else if (req.body.Body === 'bye') {
twiml.message('Goodbye');
} else {
twiml.message(
'No Body param match, Twilio sends this in the request to your server.',
);
}
res.writeHead(200, { 'Content-Type': 'text/xml' });
res.end(twiml.toString());
});
When I text my Twilio #, it hits that endpoint, but I get the following error:
Request has incorrect Content-Type. application/x-www-form-urlencoded
How do I get around this?
It looks like you're mixing up callable type functions and normal HTTP type functions. Please read the documentation to understand the difference. Callable functions are intended to be invoked directly from your mobile app using the provided client SDK. They provide two arguments: an input data object, and a context. Callables do NOT provide "req" and "res". If you want control over the the response, you should be using a normal HTTP function with "onRequest" instead of "onCall".

angular5 how to make asyc request?

In my project i made multiple request to server to get data for single page. I want to make all request asyc. Right now until i get the response from first request,the response of second request is not load.
So basically i just want to achive asyc request and response so one request will not wait for other request to finish.
Right now it's like first come first serve fashion.
But i want from multiple request which request get first response should load first.
this is code of my component
constructor(private _dashboardService: DashboardService) {
this.getLineChart();
this.todayPaymentDetails();
this.todayPaymentMethod();
this.rewardCustomers();
this.getAverageBill();
this.getItemByVolumn();
this.getItemBySales();
}
todayPaymentMethod(id=null){
this.paymentMethodsLoader=0;
this._dashboardService.getTodayPaymentMethod(id).subscribe(res =>{
if(null != res.data && '' != res.data){
this.location = res.data.location;
this.payment_methods = res.data.payment_methods;
}
this.paymentMethodsLoader=1;
});
}
this is my service code:
getTodayTotalPayment(id) : Observable<any> {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this._http.get(environment.apiUrl + constants.API_V1 + 'today-total-payment/'+id, options)
.map(res => res.json())
.catch((error: any) => Observable.throw(error.json().error || error));
}
Here shows code for only one request but as shown in constructor i send multiple request at a time.
FIrst it is not a good practise to call function like this in constructor.
For running multiple request or observable together use operators i.e. switchMap etc.
Follow this video link related to event loop in JavaScript this will improve your JavaScript execution , event loop concepts . also explains how asynchronous code executed.
Hope it will help.

How to deal with OPTION request?

I have the following code:
window.fetch(myServerURL, {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: "POST",
body: JSON.stringify(app.jsonRequest)
})
.then(res => res.json())
.then(json => {
if (json.affectedRows === 1) {
okMessage("Be welcome and check your email!");
} else {
errorMessage('Sorry! Please try again later.');
}
})
which is entitled to send a post message to my backend server and register a new user to my system using a MySQL database. And this is working fine, but my messages are not showing.
(Yes, I konw I should test more than just json.affectedRows to make sure the register was inserted fine, but I am simplifying the problem to make things clear here.)
It happens than I am detecing a preflight request OPTIONS and this is making my logic blow away, 'cause it seems it receives the OPTIONS answer first and do NOT have an affectedRows to compare. In fact, the OPTIONS request generates just OK, since server-side is configured with CORS.
On the other hand, when I write
.then(json => {
console.log(json);
}
to try to capture this OK answer to the OPTIONS request, the answer is
{"fieldCount":0,"affectedRows":1,"insertId":1845,"serverStatus":2,"warningCount":0,"message":"","protocol41":true,"changedRows":0}
as if there had been no OPTIONS request.
After trying other possible solutions with no success, Id would like to ask you all how should I deal with this in order to get my messages shown?

Angular2 display .NET API validation messages

I am transacting .NET API through Angular2(honestly.. 5) I implement server side-model validation using Data Annotations Attributes. As such, the API returns bad request(404) with the validation messages attached:
if (!ModelState.IsValid)
return this.BadRequest(ModelState);
My issue has to do on how to display those messages in my angular view.
My Angular service:
submitForm(formObj: FormDto) {
let headers = new HttpHeaders();
headers = headers.append('Content-Type', 'application/json; charset=utf-8');
return this.http.post("/api/Forms", JSON.stringify(formObj), { headers })
.map((res: Response) => console.log(res));
//need a .catch here obviously ??????
}
and the way I call the service from the component itself:
submitForm() {
this.formService.submitForm(this.formObj)
.subscribe(res => { console.log(res);
//update this bit to display error messages ?????
});
}
Again, my issue is how to display properly the returned validation error messages coming from the .NET API.
Let's star with the fact that the modelState is coming as an object(key-value pairs). Thus, you can access the object in view by a specific key. You can have a variable in your component and store the modelState object in it.
To the point....
I wouldn't touch the Angular service at all, but the way you subscribe to it in order to separate success and failed callback:
submitForm() {
this.formService.submitForm(this.formObj)
.subscribe((data) => //do what ever on success,
(err) => { this.errors= err.error; });
}
After that, you are able to see your error messages in the view. Something like:
<span class="error-message">{{errors['EmailAddress']}}</span>
Put the line above to every input it's needed but change the key to view the right message. I've done a quick demo and is working.
I hope that helped.

Express.js get http method in controller

I am building a registration form (passport-local as authentication, forms as form helper).
Because the registration only knows GET and POST I would like to do the whole handling in one function.
With other words I am searching after something like:
exports.register = function(req, res){
if (req.isPost) {
// do form handling
}
res.render('user/registration.html.swig', { form: form.toHTML() });
};
The answer was quite easy
exports.register = function(req, res) {
if (req.method == "POST") {
// do form handling
}
res.render('user/registration.html.swig', { form: form.toHTML() });
};
But I searched a long time for this approach in the express guide.
Finally the node documentation has such detailed information:
http://nodejs.org/api/http.html#http_http_request_options_callback
Now you can use a package in npm => "method-override", which provides a middle-ware layer that overrides the "req.method" property.
Basically your client can send a POST request with a modified "req.method", something like /registration/passportID?_method=PUT.
The
?_method=XXXXX
portion is for the middle-ware to identify that this is an undercover PUT request.
The flow is that the client sends a POST req with data to your server side, and the middle-ware translates the req and run the corresponding "app.put..." route.
I think this is a way of compromise. For more info: method-override

Resources