Handling errors with Ember Data JSON-API adapter not working - ember.js

I have a problem Handling errors using JSON-API, I done all steps like wrote in documentation but it's doesn't works.
I have model:
var user = this.get('store').createRecord('user', {
'email': 'test#test.com',
'name': 'Lorem ipsum',
'password': '123',
});
user.save().then(function(){
...
}).catch(function(data){
console.log(user.get('errors'), data);
// data is ErrorClass with deserialize errors inside
});
And API responce (422 Unprocessable Entity):
{
"errors":[
{
"detail":"Email address must be between 6 and 128 characters in length",
"source":{
"pointer":"/data/attributes/password"
}
}
]
}
In this case isError flag is false, user.get('errors') -> empty
I also tried response with 500 Internal Server Error code
In this case isError flag is true (as expected) and error object contain in adapterError
So what I'm doing wrong or what try to check,
thanks in advance

As for the isError flag, it shouldn't be true if you got Validation error (the one that has 422 code). It's described in docs.
Your main problem is that you have a redundant forward slash in the beginning. So you have to change this "pointer":"/data/attributes/password" to this "pointer":"data/attributes/password"
After this change you'll be able to get the errors for this property through user.get('errors.password');
Hope it helps!

Related

Postman - How can I compare a message using vars

can anyone help me, I am almost new in Postman.
my issue is as follow:
I send a POST request and get a message asresponse:
{
"errorCode": 1000,
"errorDescription": "Account is not verified by Admin!"
}
this message is already saved in a var named "messageAccountIsnotVerified"
when I try to use comparison in postman tets script and compare the message with the expected string is working fine:
pm.test("test", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.errorCode).to.eql(1000);
pm.expect(jsonData.errorDescription).to.eql("Account is not verified by Admin!");
});
But When I try to save the String text "Account is not verified by Admin!" in a variable named: messageAccountIsnotVerified
and try to make the same comparison
pm.test("test", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.errorCode).to.eql(1000);
pm.expect(jsonData.errorDescription).to.eql("messageAccountIsnotVerified");
});
or
pm.test("test", function () {
var jsonData = pm.response.json();
var message = pm.environment.get("messageAccountIsnotVerified");
pm.expect(jsonData.errorCode).to.eql(1000);
pm.expect(jsonData.errorDescription).to.eql(message);
});
it failed with error:
test | AssertionError: expected 'Account is not verified by Admin!' to deeply equal 'messageAccountIsnotVerified'
Can someone explain to me
1. what does the "deeply equal" mean and
2. what do I wrong and
3. how can I use the assertion by using the variable
Thanks for any Hint
Just additional Info: I have the same issue when I compare email with
# sign in another message - so I assume may be something to do with special chars
You need to get the variable in the following way:
pm.expect(jsonData.errorDescription).to.deep.equal(pm.environment.get("messageAccountIsnotVerified"))
.to.deep.equal can be used to reference something further down in a nested object.
Add .deep earlier in the chain to use deep equality instead. See the deep-eql project page for info on the deep equality algorithm: https://github.com/chaijs/deep-eql.
Looking at the response body you posted { "errorCode": 1000, "errorDescription": "Account is not verified by Admin!" }, I don't see a problem with the first test but for it to complain about deep equal then this response is probably no exactly as you posted.
You could reduce this all down again if you wanted too:
pm.test("test", () => {
pm.expect(pm.response.json()).to.deep.equal({"errorCode": 1000, "errorDescription": "Account is not verified by Admin!"})
});
That test would do the same as above.
let string = pm.response.json()
pm.expect(string).to.equal("String from Response")

Qunit assert throws not working

I am trying to assert that a few steps in the code (visiting page, providing wrong card-number, password combination and clicking submit)should generate an error from the backend service - I have referred to this already..
and tried the suggestion of using Error Object as the second argument to assert.throws but that doesn't work for me.
i did see this link as well before posting my question,
My problem is - I don't have control over the code that throws the exception/error in this case. (I cannot change it to say Ember.assert etc) I just want to be able to catch an erroneous case.
Secondly, I don't have a component in this case. Its a straight forward API call that's made when click on submit is done, basically an action submitAuthForm is called in controller which calls ember cli mirage scenario that returns the following object problems object.
return new Response(401,{'X-Auth-Token': 'wrong-username-password-combination'},failResponse401);
and the returned object looks like
var failResponse401 = {
problems: [ {
field: null,
index: null,
value: null,
code: '0006',
subCode: '',
details: {},
_type: 'error'
} ]
};
We have a node_module dependency on an in-house exceptions kit that throws an Error object based on this.
Here's my Qunit test
test('ERROR_CASE_visiting /signon, provide cardNumber(2342314) and ' +
'password, submit and expect to see invalid cardnumber/password error',
function (assert) {
assert.expect(2);
assert.throws(
function () {
visit('/signon');
fillIn('#a8n-signon-card-number input', '2342314');
fillIn('#a8n-signon-password input', 'password');
click('#a8n-signon-submit-button button');
},
Error,
"Error Thrown"
);
});
I keep getting this error from Qunit
Error Thrown# 110 ms
Expected:
function Error( a ){
[code]
}
Result:
undefined
Diff:
function Error( a ){
[code]
}defined
Source:
at Object.<anonymous> (http://localhost:7357/assets/tests.js:175:12)
at runTest (http://localhost:7357/assets/test-support.js:3884:30)
at Test.run (http://localhost:7357/assets/test-support.js:3870:6)
at http://localhost:7357/assets/test-support.js:4076:12
at Object.advance (http://localhost:7357/assets/test-support.js:3529:26)
at begin (http://localhost:7357/assets/test-support.js:5341:20)
API rejected the request because of : []# 1634 ms
Expected:
true
Result:
false
Source:
Error: API rejected the request because of : []
at Class.init (http://localhost:7357/assets/vendor.js:172237:14)
at Class.superWrapper [as init] (http://localhost:7357/assets/vendor.js:55946:22)
at new Class (http://localhost:7357/assets/vendor.js:51657:19)
at Function._ClassMixinProps.create (http://localhost:7357/assets/vendor.js:51849:12)
at Function.createException (http://localhost:7357/assets/vendor.js:172664:16)
at Class.<anonymous> (http://localhost:7357/assets/vendor.js:133592:72)
at ComputedPropertyPrototype.get (http://localhost:7357/assets/vendor.js:32450:27)
at Object.get (http://localhost:7357/assets/vendor.js:37456:19)
at Class.get (http://localhost:7357/assets/vendor.js:50194:26)
at http://localhost:7357/assets/vendor.js:133645:30
Is there anything else that i can try to get it to work.
Is there someway i could somehow pass this test, by wrapping the returned response somehow in a way that it doesn't break my test altogether.
I found a workaround following this link
the user pablobm has posted a link to a helper
I used that to workaround this Qunit issue.

Sublimelinter & JSHint complaining about Facebook's Open Graph objects {og:url: "example.com"}

I'm using JSHint and SublimeLinter with Sublime Text 3, but when using Facebooks API it doesnt like the object double : in the structure, eg. { og:url: 'example.com' }
FB.api(
'me/objects/my-app:object',
'post',
{
og:url: http://samples.ogp.me/12345678910,
og:title: Sample Object,
og:type: my-app:object,
og:image: https://fbstatic-a.akamaihd.net/images/devsite/attachment_blank.png,
og:description: ,
fb:app_id: 12345678910,
place:location:latitude: Sample Location: Latitude,
place:location:longitude: Sample Location: Longitude
},
function(response) {
// handle the response
}
);
I know how to ignore certain variables and names in the .jshintrc file on the root of my project, but not sure how to stop it complaining about this structure. I thought since the Facebook API is popular it's worth posting it here.
Wrap them in quotes.
eg. { 'og:url': 'example.com' }

Traverson Library to consume a RESTful webservice throws error with JSONPath

I'm currently trying to get the traverson library to fetch some information from an REST interface provided by SpringBoot.
My goal for now would be to get traverson to follow the path to
http ://localhost/users and fetch the information by using this code
traverson.from('http://localhost:8090')
.json()
.follow('$._links.user')
.getResource(function(err, resource){
if(err){
console.log(err);
return;
}
console.log(resource);
});
The json structure which is returned upon calling the endpoint looks like this:
{
"_links" : {
"ressource" : {
"href" : "http://localhost:8090/ressource{?page,size,sort}",
"templated" : true
},
"user" : {
"href" : "http://localhost:8090/user{?page,size,sort}",
"templated" : true
},
"alert" : {
"href" : "http://localhost:8090/alert{?page,size,sort}",
"templated" : true
}
}
Unfortunately this results in an error:
Uncaught TypeError: a.step.url.search is not a function
However if I just fetch the endpoint without the JSONPath Syntax it provides me the mentioned structure.
It will produce a more sensible error when I mess up the JSONPath Expression:
[Error: JSONPath expression $.links.user returned no match in document:
{"_links":{"ressource":{"href":"http://localhost:8090/ressource{?page,size,sort}
","templated":true},"user":{"href":"http://localhost:8090/user{?page,size,sort}"
,"templated":true},"alert":{"href":"http://localhost:8090/alert{?page,size,sort}
","templated":true}}]
Might be that I'm missing something super obvious which would be nice...
At least thanks for reading this far :)
To whom it might concern,
After some trial and error it turns you have to be very careful about the JSON Path expression you provide.
traverson.from('http://localhost:8090')
.json()
.follow('$._links.user.href')
.getResource(function(err, resource){
if(err){
console.log(err);
return;
}
console.log(resource);
});
This will work while this:
traverson.from('http://localhost:8090')
.json()
.follow('$._links.user')
.getResource(function(err, resource){
if(err){
console.log(err);
return;
}
console.log(resource);
});
will not.
The reason seems to be that $._links.user points to an object not an object attribute (see the endpoint structure above). This causes the evaluating function within the traverson library to cause a somewhat unintelligible error.
Let's hope that someone might make use of this information and doesn't spend hour brooding over this.
EDIT 1: After filling an issue with the library’s owner, this issue should now longer occur

What's the standard pattern for ember-data validations? (invalid state, becameInvalid...)

I've kinda been struggling with this for some time; let's see if somebody can help me out.
Although it's not explicitly said in the Readme, ember-data provides somewhat validations support. You can see that on some parts of the code and documentation:
https://github.com/emberjs/data/blob/master/packages/ember-data/lib/system/model/states.js#L411
https://github.com/emberjs/data/blob/master/packages/ember-data/lib/system/model/states.js#L529
The REST adapter doesn't add validations support on itself, but I found out that if I add something like this in the ajax calls, I can put the model on a "invalid" state with the errors object that came from the server side:
error: function(xhr){
var data = Ember.$.parseJSON(xhr.responseText);
store.recordWasInvalid(record, data.errors);
}
So I can easily to the following:
var transaction = App.store.transaction();
var record = transaction.createRecord(App.Post);
record.set('someProperty', 'invalid value');
transaction.commit()
// This makes the validation fail
record.set('someProperty', 'a valid value');
transaction.commit();
// This doesn't trigger the commit again.
The thing is: As you see, transactions don't try to recommit. This is explained here and here.
So the thing is: If I can't reuse a commit, how should I handle this? I kinda suspect that has something to do to the fact I'm asyncronously putting the model to the invalid state - by reading the documentation, it seems like is something meant for client-side validations. In this case, how should I use them?
I have a pending pull request that should fix this
https://github.com/emberjs/data/pull/539
I tried Javier's answer, but I get "Invalid Path" when doing any record.set(...) with the record in invalid state. What I found worked was:
// with the record in invalid state
record.send('becameValid');
record.set('someProperty', 'a valid value');
App.store.commit();
Alternatively, it seems that if I call record.get(...) first then subsequent record.set(...) calls work. This is probably a bug. But the above work-around will work in general for being able to re-commit the same record even without changing any properties. (Of course, if the properties are still invalid it will just fail again.)
this may seem to be an overly simple answer, but why not create a new transaction and add the pre-existing record to it? i'm also trying to figure out an error handling approach.
also you should probably consider writing this at the store level rather than the adapter level for the sake of re-use.
For some unknown reason, the record becomes part of the store default transaction. This code works for me:
var transaction = App.store.transaction();
var record = transaction.createRecord(App.Post);
record.set('someProperty', 'invalid value');
transaction.commit()
record.set('someProperty', 'a valid value');
App.store.commit(); // The record is created in backend
The problem is that after the first failure, you must always use the App.store.commit() with the problems it has.
Give a look at this gist. Its the pattern that i use in my projects.
https://gist.github.com/danielgatis/5550982
#josepjaume
Take a look at https://github.com/esbanarango/ember-model-validator.
Example:
import Model, { attr } from '#ember-data/model';
import { modelValidator } from 'ember-model-validator';
#modelValidator
export default class MyModel extends Model {
#attr('string') fullName;
#attr('string') fruit;
#attr('string') favoriteColor;
validations = {
fullName: {
presence: true
},
fruit: {
presence: true
},
favoriteColor: {
color: true
}
};
}