JSON.stringify in response option of cy.route is not working - reactjs

I'm currently writing tests on Cypress for an application writen in react and using redux and redux-saga. For one of my tests, I'm trying to stub a request and returning a response that the code is expecting to be an 'stringified' array by JSON so it can be parsed later.
I've tried to specify a response in the cy.route() command using JSON.stringify([desiredResponse]) but that is not working, response keeps being kind of parsed by Cypress or some other middleware before getting to the saga.
I've also tried to intercept the response in the onResponse option but seems to me like that's being executed once the response was delivered (not sure about this, made a couple of vague tests only)
// This is how my cy.route() config looks like
cy.route({
method: 'POST',
url: 'someUrl',
response: JSON.stringify([myResponse]),
});
And in my saga:
// I call the url via axios and immediately after I try to parse it
try {
const parsed = JSON.parse(response.data);
} catch (err) {
const parsed = [];
}
I would expect my response in the saga to be something like: "[myResponse]" but I got the raw array instead

Out of curiosity: have you tried avoiding to wrap [myResponse] into JSON.stringify()?
Something like
cy.route({
method: 'POST',
url: 'someUrl',
response: [myResponse],
});
Anyway: in my app, with your exact situation, my only difference with your code is that I leverage the Cypress fixtures .
Could you share a simple GitHub repo with your simplified code?

Related

Getting json data from url

How do I get a JSON response from URL?
In my case, the URL is https://api.mathjs.org/v4/?expr=2*2 JSON response and then whenever someone types !test it sends the json/data from the URL.
Here is some sample code using node-fetch, I cant guarantee it will work well
const fetch = require('node-fetch')
(async () => {
const response = await fetch(`https://api.mathjs.org/v4/?expr=${encodeURIComponent(2*2)}`).then(r => r.text())
console.log(response)
})()
this logs 4.
this is a sample code as i said,
you would have to modify it to your needs, i used a iife as fetch method returns a promise
you can do:
<message>.channel.send(`the result is ${response}`)
as a example adapted from the above given code
ps: rather than using a api for math you could use mathjs package (which your using, just its the api version)
Edited: forgot of encodeURIComponent in fetch request url, or you will get a Only absolute URLs are supported error
You don't need JSON just to get the value of the query parameter from the URL. If you just need to get the number you can try it with URLSearchParams:
console.log(window.location.search); //output: '?expr=2*2'
var params = new URLSearchParams('?expr=2*2');
console.log(params.has('expr')); //output: 'true';
console.log(params.get('expr')); //output: '2*2';
you get the value from params.get('expr'));

Receiving Json data in groovy app

I´m working on this app which will be a frontend consuming data from other applications but in first stance, it will be posting credentials to another app already running in production, and after credentials are accepted it should redirect to that app with user logged in.
Here comes the problem. I´ve already tested sending data to the other application data is being received as
params: [{"j_username":"username","j_password":"password","instance":"http:8080/TERA/authAuto"}:, action:authAuto, controller:login]
username: null
Prueba: null
I have tried to receive this as it follows all without success
request.JSON.j_username
params.j_username
params["j_username"]
The params: is actually params received by groovy being printed.
I´ll now add my angularJs code
vm.login = function(){
$http({
method: 'POST',
url: "http://t0002161750:8080/TERA/authAuto",
data: {j_username: vm.user.username, j_password: vm.user.password, instance: "http://t0002161750:8080/TERA/authAuto"},
headers:{
'Content-Type': 'application/x-www-form-urlencoded;charset=utf8'
}
}).success(function(response){
$window.location.href = "http://t0002161750:8080/TERA/";
});
}
}
Im doing this tests with a companion having the other app running on his PC.
I may be doing something wrong conceptually speaking. I know that by sending the params in the $window.location.href = url+params will work but i dont want the credentials travelling in the url. I know i can encode them but lets try something else before giving up if it is possible.
The problem here is using the wrong Content-Type for the submission. The server will look for POST-vars in the body. The proper value to use is:
Content-Type: application/json
(instead of application/x-www-form-urlencoded;charset=utf8)

"Failed to parse UUID" error message on attempting to login via TrueVault api

On attempting to login via the truvault api using angular js, I am getting this error message: Failed to parse UUID. I am passing the username, password and account_id as params. I am successful using the curl command and get the success response.
The 400 error is not described in the api docs for authorization. I am not sure about if this UUID is linked to the schema_id. Would anyone (truevault guys!!) know what I am doing wrong?
I contacted truevault support on this one. Dan helped me get through it.
I was passing the username/password/account_id as url string query parameters. I had to make two changes to the code:
1. Pass the above as form data parameters
2. add the angular-post-fix.js to my project.
(Note: I am not adding the link as there are editors who will disallow the post with links to elsewhere. It has happened in the past!)
When using Node.js, the querystring API is really useful. Just pass an object to the querystring.stringify() function, and the resulting output is ready to be sent to TrueVault for login.
Additionally, I found that adding the header 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8' might be necessary (which is one of the things the Angular post-fix library does).
#orthodoc is right, but is kind of tricky how to actually build the request. Lets say we are using fetch with formData params, I'd like to add an example of a successful request:
...
var formData = new FormData();
formData.append('username', username);
formData.append('password', password);
formData.append('account_id', accountId);
return fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
},
body: formData
});
...

Recaptcha angularjs verify user's answer

I am using the following plugin https://github.com/VividCortex/angular-recaptcha in order to use recaptcha at a login form.
I am using the following code for verification
$http({
url: 'https://www.google.com/recaptcha/api/verify',
method: 'POST',
params: {privatekey: "key", remoteip: "userip", challenge: "challenge", response: "user_answer" },
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}).success(function(data) {
console.log(data);
if (valid) {
console.log('Success');
alert('Success');
} else {
console.log('Failed validation');
alert('Fail');
// In case of a failed validation you need to reload the captcha because each challenge can be checked just once
//vcRecaptchaService.reload();
}
});
But google server is not returning anything.
I updated the code but no luck.
I think you have a typo in your code:
post: 'GET'
Change that to method: 'GET' or method: 'POST'.
You can check out angular documentation on http to make sure you've written all the params right.
If this wasn't the source of your problems, you should post more details about your issue (what do you see in your networkl console for example).
Keep in mind that recaptcha validation must be done at server-side. I'm not 100% sure that you are doing that in the browser, but your code looks like it.
As Miguel Trias stated, you shall not validate directly from angularjs/javascript client, instead you should send the challenge and response field to your server and validate then.
Therefore you can use the uri you used (https://www.google.com/recaptcha/api/verify) or a plugin, e.g. if you use php see https://developers.google.com/recaptcha/docs/php. I'd prefer a plugin because it will save work.
Furthermore keep in mind that your private key should not be used in the client, this is why it is called private. It is only used to communicate between your server and the reCaptcha servers. The public key is used to communicate between your client and the reCaptcha servers.
For more info read the Overview

angularjs custom REST action and error handling

I'm having some trouble with error handling in a little angularjs application. I'm interacting with a Flask backend and a Postgres DB.
I have a factory service
appointServices.factory('Appointments', ['$resource', function($resource){
return $resource(someUrl, {}, {
query: { ... }
,
create: {
method: 'POST'
,url: 'http://somedomain:port/new/:name/:start/:end/:treatment'
,params: { start: '#start', end: '#end', name: '#name', treatment: '#treatment' }
,isArray:false
}
});
}
]);
Inside a controller I'm making the following call
Appointments.create($scope.appointment, function(value, responseHeaders) {
// success handler
console.debug('success: ', JSON.stringify(value));
}, function(httpResponse) {
// error handler
console.debug('error: ', JSON.stringify(httpResponse));
});
Here $scope.appointment contains the relevant parameters for the create action.
Now, in the backend I'm able to catch DB errors involving constraints and I'm trying to return an error code with a 'meaningful' message. So I have a python method
def create(name, start, end, treatment):
try:
...
transaction_status = 'ok'
code = 200
except IntegrityError as e:
...
transaction_status = 'IntegrityError'
code = 500
finally:
...
return make_response(transaction_status, code)
Everything works fine, I'm able to talk to the backend, create new data and insert this in the DB. As I said, any violation of the constraints is detected and the backend responds
curl -X POST "http://somedomain:port/new/foo/bar/baz/qux" -v
...
< HTTP/1.0 500 INTERNAL SERVER ERROR
...
IntegrityError
So, the problem is, no matter whether the action create was successful or not, the intended error handler specified inside the controller is always fired. Moreover, I always end up with a status code 404 in the httpResponse. Firebug shows correctly the code 500 as above, though.
Anybody has any idea of why I'm getting this behavior?
Any suggestions on how to improve the error handling mechanism are also welcome.
Thx in advance.
P.S. Following the documentation on $resource I have also tried variations on the factory service call, e.g.
Appointments.create({}, $scope.appointment, successCallback, errorCallback);
Appointments.create($scope.appointment, {}, successCallback, errorCallback);
with the same results.
Update:
Forgot to mention the important fact that I'm interacting with the backend via CORS requests. The POST request in create above is having place with the OPTIONS method instead. As I mentioned everything is working correctly except for the error response.
Under further investigation, I tried to isolate the factory service, in case I did something wrong, and I also tried the approach shown in the credit card example ($resource docs), but with no positive result.
However, I came up with two workarounds. Firstly, I was able to create a plain JQuery POST request, as in the example shown in the docs. This time, the request is not replaced by OPTIONS and I got the error code correctly.
I also managed to connect to the backend with the low-level $http service as follows:
var urlBase = 'http://somedomain:port/new/:name/:start/:end/:treatment';
var url = urlBase.replace(/:name/g, $scope.appointment.name);
url = url.replace(/:start/g, $scope.appointment.start);
url = url.replace(/:end/g, $scope.appointment.end);
url = url.replace(/:treatment/g, $scope.appointment.treatment);
// force method to be POST
var futureResponse = $http({ method: 'POST', url: url });
futureResponse.success(function (data, status, headers, config) {
console.debug('success: ', JSON.stringify(data));
});
futureResponse.error(function (data, status, headers, config) {
console.group('Error');
console.debug(JSON.stringify(status));
console.debug(JSON.stringify(data));
console.groupEnd();
});
This time, as in the case of JQuery, the request is done effectively with POST and error codes are correctly received.
Notice also that I'm not calling $http.post but I set the method to POST as part of the object parameter to $http, otherwise the connection takes places with OPTIONS as before.
Still trying to figure out what is happening with $resource.

Resources