Getting 'expected { Object (message, detail) } to have property 'count' error in API testing using cypress - rest

I want to assert the total count received from the response.
This is my code:
cy.request({
method:'GET',
url:'https://ibis-qa.droicelabs.us/api/practice/orders/?q=&limit=100',
failOnStatusCode: false,
headers:{
accept: "application/json"
}
}).then(Response => {
let body = JSON.parse(JSON.stringify(Response.body))
cy.log(body)
expect(body).has.property('count','27')
})
and this is the error that I have got

Please use
expect(body).has.property('count', 27)
as the value is a number
(see screen-shot, there are no quotes around 27)
You are not getting the JSON response you think you should have.
If go to the URL in the browser, I get this
{"message":"field required","detail":[{"loc":["header","authorization"],"msg":"field required","type":"value_error.missing"}]}
which is what is partially shown in the screenshot of the error message.
This is an error response from the server, and it means your request is not correct.

Then you can directly use the assertion like this. You don't need to parse or stringify.
expect(Response.body).to.have.property('count',27)
You can check this example from the cypress docs.

Related

I POST my image by python through WP REST API, but the response is just the array of items in media library

First of all, I have found out what's wrong with my python code, but I really want some one to tell me how it popped out because I'm just a noob amateur.
I tried to post my album collected on my wordpress by using my python script as usual, but I got an unexpected throw-out when it start to image upload. My img upload function just like this:
def restImgUL(imgPath,imgName,token):
url='http://www.rainloongmusic.com/wp-json/wp/v2/media/'
file_extension = os.path.splitext(imgPath)[-1]
img = open(imgPath,'rb')
imgName = imgName.replace(";","")
_json = {
"title":imgName,
'caption': imgName,
"alt_text":imgName,
"description":imgName,
"status":"publish"
}
image_name = f"{imgName}{file_extension}"
headers = { 'Content-Type': '','Content-Disposition' : 'attachment; filename=%s'%image_name.encode("utf-8").decode("latin1"),"Authorization":"Bearer %s"%token}
res = requests.post(url=url,data=img,headers=headers,json=_json)
rrr = res.json()
if "id" in rrr:
return rrr["id"]
else:
print(rrr)
sys.exit()
The wrong response is an array include items in my first page of media library. I found some clues in rest api handbooks. If I attempt to GET /wp/v2/media, response will be like what I've recieved. But I use POST type request in my python code, I don't really understand what happened there. I have no choice but to try some other methods to bypass this problem. I tried to make a new endpoint and write something like this:
add_action( 'rest_api_init', function () {
register_rest_route( 'rlra/v1', '/media', array(
'methods' => 'POST',
'callback' => 'cmupload',
) );
} );
function cmupload(){
return "This is a test!!!"
}
However, I got rest_no_route when I POST to it. I changed the methods to GET eventually, and got the right text from my server. I think maybe something changed my POST request into a GET one? I tried to figure out with Charles, and found my connection with 302 permanent redirect. So I check my request link and change http into https, everything works.
So, could anyone tell me why a 302 redirect will change my POST request into GET, I've been worn-out due to the lost letter "s" in these days.

Angular 2 how to read Custom error message from backend

My problem with Angular 2 that was not exist in AngularJS, that I was sending the error message as a string with backend API call in case I have error, with error status 401 as example, the problem now that I can't read this message from Angular2 http response message, while I can do that from AngularJS:
I tried the following codes and nothing was helpful:
Promise:
this._http.post('/login',{email: 'email#example.com', password: '123'})
.toPromise()
.then((resp) => console.log(resp), (error) => console.log(error));
Observable:
this._http.post('/login',{email: 'email#example.com', password: '123'})
.subscribe(response =>console.log(response), (error) => console.log(error));
And from back-end I send response as a text, for OK or Unauthorized, for OK i send back String token == UUID.randomUUID().toString();, for error I send back message like String error = " Invalid credentials ";, the problem is that the console.log works and print the text for success (token in this case), but in case error, its just prints: Response with status: 200 for URL: null.
If I change code to JSON.stringify(error) I get something like this:
{"_body":{},"status":401,"ok":false,"statusText":"Unauthorized","headers":{"null":["HTTP/1.1 401 Unauthorized"],"Access-Control-Allow-Headers":["Origin"," X-Requested-With"," Content-Type"," Accept"," Referer"," User-Agent"],"Access-Control-Allow-Met
hods":["POST"," GET"," PUT"," DELETE"," OPTIONS"],"Access-Control-Allow-Origin":["*"],"Allow":["*"],"Content-Length":["36"],"Content-Type":["text/plain; charset=utf-8"],"Date":["Tue"," 23 Aug 2016 14:53:25 GMT"]},"type":2,"url":null}
As you can see the error test not even mentioned inside the Object !!
I tried to change the response for error from backend to return json like this:
{
"message": "invalid email or password"
}
I can get the result inside _body, and I can only read it like this: console.log(error._body.message) ! but i feel its something wrong this way, and I don't want to response as a json in this case.
For angularjs (angular 1), its so simple just to print the response and everything is cool, while in angular 2 its a really problem.
What the problem, and how I can solve this issue without any refactor to backend?
Edit:
I'm using Angular 2.0.0-rc.4 and same for http : `"#angular/http": "2.0.0-rc.4"
Mothanfar
In my case I'm working with the Asp Web Api as back end,this thing is making me crazy as well, the only solution I found is transform in a json and read the message, I know is really ugly but works for me.
Regards.
CheckError(error: any) {
let servermsg: any = JSON.parse(error._body)["ModelState"]["Login"][0];
if (servermsg) {
this.showMsg = true;
this.msg = servermsg;
}
}
If you are returning JSON object from the server, you may use the below code at client side:
let errMsg: ErrorMessage = err.json();
console.log(errMsg.message)
export class ErrorMessage {
message:string;
}

xhrPost seems to be modifying the URL resulting in either 404 or 405?

xhrPost seems to be modifying the URL resulting in either 404 or 405.
This is from a custom widget and attempting to go to a REST service on a WebSphere Liberty server.
The rest service responds correctly when using RESTClient and building the request manually.
I am using var jsonData = JSON.stringify(domForm.toObject("TaskTemplate")); so I can verify the data is correct and sending the data as that string:
data: jsonData,
the URL is hardcoded in the form and no substitution is currently being used:
<form id="TaskTemplate" name="TaskTemplate"
data-dojo-attach-point="taskTemplateNode"
method="POST"
action="http://localhost:9080/test2/rm/tasks/64/update">
I also have a GET with a URL of "http://localhost:9080/test2/rm/tasks/64/" that is working fine.
Seems to be associated with PUT or POST...
When I do the xhrPost, I am getting the following error:
"NetworkError: 404 Not Found - http://localhost:9080/test2/undefined"
since "undefined" is seen, it is like xhrPost is doing some substitution in the hardcode URL...
I am using 1.9.2-20140219-IBM version of dojo which comes with Rational Application Developer.
I have tried both xhrPost and xhrPut with the same results.
Here is the method that is invoked when the button is pushed:
applySubmit: function() {
console.log("inside applySubmit");
var jsonData = JSON.stringify(domForm.toObject("TaskTemplate"));
console.log(jsonData);
var xhrArgs = {
// url: "http://localhost:9080/test2/rm/tasks/64/update",
data: jsonData,
preventCache: true,
timeout: 10000,
handleAs: "text",
contentType: "application/json",
load: function(data) {
console.debug("applySubmit success:" + data);
},
error: function(data) {
console.debug("applySubmit error:");
}
};
console.log("doing dojo.xhrPxxx(xhrArgs);");
var deferred = dojo.xhrPost(xhrArgs); // any need to save local var and exit?
}
In the server logs, I am seeing [WARNING ] SRVE0190E: File not found: /undefined
and that is coming from the webcontainer (makes sense given the error msg above)
So, this means it is not related to my rest service, never gets to it.
This is really starting to delay our project, so any ideas about why this might be occurring would be greatly appreciated!

PUT Request not happening at all in Fantom

I am having some trouble with PUT requests to the google sheets api.
I have this code
spreadsheet_inputer := WebClient(`$google_sheet_URI_cells/R3C6?access_token=$accesstoken`)
xml_test := XDoc{
XElem("entry")
{
addAttr("xmlns","http://www.w3.org/2005/Atom")
addAttr("xmlns:gs","http://schemas.google.com/spreadsheets/2006")
XElem("id") { XText("https://spreadsheets.google.com/feeds/cells/$spreadsheet_id/1/private/full/R3C6?access_token=$accesstoken"), },
XElem("link") { addAttr("rel","edit");addAttr("type","application/atom+xml");addAttr("href","https://spreadsheets.google.com/feeds/cells/$spreadsheet_id/1/private/full/R3C6?access_token=$accesstoken"); },
XElem("gs:cell") { addAttr("row","3");addAttr("col","6");addAttr("inputValue","testing 123"); },
},
}
spreadsheet_inputer.reqHeaders["If-match"] = "*"
spreadsheet_inputer.reqHeaders["Content-Type"] = "application/atom+xml"
spreadsheet_inputer.reqMethod = "PUT"
spreadsheet_inputer.writeReq
spreadsheet_inputer.reqOut.writeXml(xml_test.writeToStr).close
echo(spreadsheet_inputer.resStr)
Right now it returns
sys::IOErr: No input stream for response 0
at the echo statement.
I have all the necessary data (at least i'm pretty sure) and it works here https://developers.google.com/oauthplayground/
Just to note, it does not accurately update the calendars.
EDIT: I had it return the response code and it was a 0, any pointers on what this means from the google sheets api? Or the fantom webclient?
WebClient.resCode is a non-nullable Int so it is 0 by default hence the problem would be either the request not being sent or the response not being read.
As you are obviously writing the request, the problem should the latter. Try calling WebClient.readRes() before resStr.
This readRes()
Read the response status line and response headers. This method may be called after the request has been written via writeReq and reqOut. Once this method completes the response status and headers are available. If there is a response body, it is available for reading via resIn. Throw IOErr if there is a network or protocol error. Return this.
Try this:
echo(spreadsheet_inputer.readRes.resStr)
I suspect the following line will also cause you problems:
spreadsheet_inputer.reqOut.writeXml(xml_test.writeToStr).close
becasue writeXml() escapes the string to be XML safe, whereas you'll want to just print the string. Try this:
spreadsheet_inputer.reqOut.writeChars(xml_test.writeToStr).close

What changed in jQuery 1.9 to cause a $.ajax call to fail with syntax error

I'm making a REST DELETE call, which returns a 204. In jQuery 1.8.3 this works, and hits the request.done callback. But if I use 1.9 it goes to request.fail with a parsererror in the textStatus and a 'SyntaxError: Unexpected end of input' in the errorThrown.
remove = function (complete) {
var self = this;
var request = $.ajax({
context: self,
url: "/v1/item/" + itemId,
dataType: "json",
type: "DELETE"
});
request.done(removeCallback);
request.fail(function (xhr, textStatus, errorThrown) {
alert(errorThrown);
});
},
Anyone know what has changed in 1.9 that would cause this to fail, and what needs to change in order to fix it?
So, answering my own question it looks like this is in fact the problem:
From the jQuery upgrade guide
jQuery.ajax returning a JSON result of an empty string
Prior to 1.9, an ajax call that expected a return data type of JSON or JSONP would consider a return value of an empty string to be a success case, but return a null to the success handler or promise. As of 1.9, an empty string returned for JSON data is considered to be malformed JSON (because it is); this will now throw an error. Use the error handler to catch such cases.
So, if remove the dataType
dataType: "json",
It works in jQuery 1.8.3 and 1.9.
An HTTP 204 response is not an empty string: it means there is no data. This is a valid response for delete and update operations.
This looks like a bug introduced in JQuery 1.9.
The reason removing the dataType property fixes this is because when it's set to "json" JQuery attempts to parse the content using JSON.parse and failing as a result. From the ticket:
This won't fail with any other dataType than "json" because the
regression is due to the re-alignment of parseJSON with native
JSON.parse (throwing an exception for null/undefined values).
Don't try the workaround suggested in the ticket of adding a handler for the 204 via the statusCode property, because both that handler and the error handler will be triggered. A possible solution is the following:
$.ajax(url, {
type: "DELETE",
dataType: "json",
error: function (error) {
if (error.status === 204) {
// Success stuff
}
else {
// fail
}
}});
I was having a very similar problem, and you helped my find my answer - so thank you. My solution, however is slightly different, so I figured I would share it.
As stated in the question, on the JQuery website it says:
Prior to 1.9, an ajax call that expected a return data type of JSON or JSONP would consider a return value of an empty string to be a success case, but return a null to the success handler or promise. As of 1.9, an empty string returned for JSON data is considered to be malformed JSON (because it is); this will now throw an error. Use the error handler to catch such cases.
I was passing JSON data to a method on my server with "void" as a return type because I did not need to do anything with returned data in the success function. You can no longer return null when passing JSON in an AJAX request in JQuery 1.9 +. This was possible in previous versions of JQuery however.
To stop getting an error and get the success function to fire instead, you must simply return valid JSON in your AJAX request. It doesn't matter what you pass, as long as it's valid, because (in my case anyways) you are not using the returned data.
The problem seems to be that jQuery treats the empty body (where Content-Length is 0) of a 204 response as "". Which is one interpretation, but the downside is that "" gets treated like any other response string. So if you have called jQuery.ajax() with the dataType:json option, jQuery tries to convert "" to an object and throws an exception ("" is invalid JSON).
jQuery catches the exception and recovers, but if you prefer to avoid the exception altogether (in your development environment) you might do something like the following. Add in the "converters" option to jQuery.ajax() and use it to change "" responses to nulls (I do this when dataType is json). Something like :
var ajax_options =
{
/* ... other options here */
"converters" :
{
"text json" :
function( result )
{
if ( result === "" ) result = null;
return jQuery.parseJSON( result );
}
}
};
var dfd = jQuery.ajax( ajax_options );