I have a SPA application that talks with API that deployed on another server. For example, when I click a Submit button it sends XHR request to it API, and I need to wait for a response to check it. How can I do this?
Put this in cypress/support/commands.js:
Cypress.Commands.add('manageMyApiRequests', () => {
cy.route('/URL/Of/api/I/Want/To/wait/For').as('myApi')
});
Then in your test or before each call:
cy.server();
cy.manageMyApiRequests();
Then where-ever you want to wait for that api response just do:
cy.wait('#myApi');
The same can also be acheived without the first cypress command manageMyApiRequests but I suggest you use this for better organization of your tests and then later you can also add more apis to the same function.
FYI you can also use .then() it if you want to check something within the response:
cy.wait('#myApi').then((xhr) => {
// we can now access the low level xhr
// that contains the request body,
// response body, status, etc
});
Related
I have an endpoint written in expressjs
router.post("/mkBet", async (req, res) => {
console.log(req.body)
const betToPush = new Bet({
addr: req.body.address,
betAmount: req.body.amount,
outcome: req.body.didWin,
timePlaced: Math.round(+new Date()/1000)
})
try {
const newBet = await betToPush.save()
res.status(201).json(newBet)
} catch(err) {
res.status(400).json({message: err.message})
}})
And I am trying to make it so that it can only be called when an action is performed on the frontend. So users cannot call it with custom arguments to make it so the outcome is always true. What would be the best way to achieve this?
It is not possible to securely tell what client sent the request. In other words, a request from your client and a different one can be identical in general.
Talking about unmodified browsers (as opposed to non-browser tools like Postman), you can tell the origin of the request (~the url loaded in the browser when the request was sent) with some confidence from the Origin and Referer request headers. However, your backend needs authentication and authorization anyway.
With the latter two in place, ie. with proper security implemented on the server-side, it doesn't matter anymore what client sends the requests.
Can't see to find any good docs on how to mock/stub the server Sider side requests with playwright.
An example would be to intercept the getServerSideProps in nextjs: hitting the routes makes the server do a request (db API etc). Then it can do some business logic (which should also be covered by testing) before it is passed to the component as props which is sent to the client (being server side rendered).
Mocking that db API request without having some test logic mixed into the business logic is what I am hoping to find an answer for.
Playwright allows you to do interception and mocking/stubbing.
UI action can triger the API call, and without sending request you can intercept
the response.
And you can use moks and stubs as well.
const mock = { animals: [] }
await page.route('**/Zoo/v1/books', (animals) =>
route.fulfill({
status: 304,
body: JSON.stringify(mock),
})),
);
await page.goto('https://www.demoqa/animals');
See more https://github.com/microsoft/playwright/issues/1774#issuecomment-769247500
And https://playwright.dev/docs/next/network#modify-responses
I'm writing a simple api for training using express. Here's my testing code:
var express = require('express');
var app = express();
app.post("/api/:var_name", function(req, res) {
res.send(req.params.var_name);
});
is simply testing to see if POST is working. When I call http://localhost:3000/api/1 I get Cannot GET /api/1, so the server is obviously interpreting the POST request as GET, what do I need to do to call POST instead?
Anything you call in the address bar of your browser will be sent via get. This is due to the fact that post-messages (and almost all other methods) do have a body-part. But there is no way for your browser to send additional information inside the body of the http packet.
If you want to test your routes for any method other than GET I would suggest you download a tool like postman.
https://www.getpostman.com/
BEWARE: This is my preference. You can of curse also use text based browsers like curl to test it.
The server interprets the request according to the verb you set in the HTTP request. If no method/verb is specified it is interpreted as GET(not sure about this part).
When you call that URL, you need to use the method as well. For example if you use the fetch API, you can call it like:
fetch(url, {method:"POST"})
If you're entering it in your browser and expect it to be interpreted as a post request, it's not. All browser url requests are GET. Use a tool like Postman to call different HTTP verbs. It's really useful when creating such APIs.
You can check out this answer on details of how to add body and headers to a post request: Fetch: POST json data
I'm using React to send a post request to my express server which then returns a response, like so:
app.post('/api/games', function(req, res) {
return res.json();
});
Before I use that response to persist it to a database, I want to be able to see everything within that response. When I console.log it from the server, I get a long list of the JSON object printed, but would ideally like something closer to Chrome's dev tools console where I can click through and inspect everything. How can I send this response JSON back to my React component so that I can console.log it in in the browser?
Thanks!
You can use node-inspector in order to debug your express API.
It uses Chrome Dev Tools so you'll feel like you are debugging your client side!
Remember, a request comes in, and the response goes out.
on a request, the req.body and req.params will contain the body/params of the request.
To respond to a request, use the res.json({someJSONHere}) or you can also res.send({someJson})
You can also console.log inside the server and watch output on the terminal
app.post('/api/games', function(req, res) {
console.log(req.params)
console.log(req.body)
return res.json(
Object.assign({}, req.body, req.params)
);
});
Express request/response Documentation
If you want to view your response in the client-tier here are some of the things you can do using the GoogleChrome asides from the console
1 Use React Developer Tools
2 I like using Postman for viewing and manipulating request/response
I'm trying to do a POST to a service running on localhost with jQuery AJAX, but it keeps returning status code 0 even after I've set jQuery.support.cors = true. I can also navigate to my WCF REST service successfully from my browser. This is what my JavaScript looks like:
<script>
jQuery.support.cors = true;
$(document).ready(function(){
$.ajax({
type: "POST",
url: "http://localhost:8000/Test",
data: '{"test":"test"}',
contentType: "application/json",
dataType: "json",
success: function (msg) {
alert('success');
},
error:function(x,e){
if(x.status==0){
alert('error 0');
}
}
});
});
</script>
Does anyone know what could be causing this? I should also mention that I can't POST to anything on localhost using jQuery.
According to Fiddler, the JSON data is not sent, and a HTTP OPTIONS is done instead of a POST.
try this
var dataObj = {test:"test"};
var json = JSON.stringify(dataObj);
then in your ajax call
data: json,
I didn't want to spend anymore time on this issue, so I resorted to using raw HTML form POST as the usage of JSON wasn't essential in my case.
For anyone else having the same issues outlined in the original post, see this thread for an explanation and a solution: Problem sending JSON data from JQuery to WCF REST method
To summarize, your service needs to be able to handle the HTTP OPTIONS method if it is expected to respond to cross domain calls.
You should use a tool like network monitor etc. to see if the browser is asking the server for the allowed headers (using the OPTIONS header request), you may need to supply the correct headers in an OPTIONS response before the actual request is sent to the server (see the article at the bottom).
Also, you could try adding this to the actual call or the ajaxSetup, as you will need to tell the browser to send credentials and allow the cross domain call (I know someone else already mentioned 'crossDomain'):
$.ajaxSetup({
crossDomain: true,
xhrFields: {
withCredentials: true
}
});
Have a read of this if you get time too.. https://developer.mozilla.org/en/http_access_control
So, when the request is cross domain, jQuery will send your post request as a get request anyways.
Are you accessing "localhost" in the URL but then your application is sending the requests to the local IP of your machine instead of localhost? Because that's technically cross-domain, which means that you won't receive the request in the expected manner.
E.g. (just tested this locally)
Visiting my local site at:
http://localhost/test/
A form on the site submits to my local ip address instead of localhost via $.post():
<form action="http://10.0.0.17/test/" method="post">
....[form stuff...]
</form>
This is a cross-domain request
If you're calling $.post() or jquery's ajax() call set to post, it automatically moves your parameters from the post body into the query string.
If you ARE accessing local host, try hitting the site via whatever address your jquery post() method is using as the domain and see if that helps.
See more on cross-domain policies:
http://en.wikipedia.org/wiki/Same_origin_policy
Send the data as an Object literal instead of a string
data: '{"test":"test"}',
to
data: {test:"test"},