chore: 🤖 add convenience identifiers to error objects
This commit is contained in:
2 files changed
+68
-5
No files matched your search
@@ -4,6 +4,7 @@ import { get } from '@ember/object';
|
||||
import { InvalidError } from '@ember-data/adapter/error';
|
||||
import { dasherize } from '@ember/string';
|
||||
import { pluralize } from 'ember-inflector';
|
||||
import { isArray } from '@ember/array';
|
||||
|
||||
export default class ApplicationAdapter extends RESTAdapter {
|
||||
// =attributes
|
||||
@@ -91,6 +92,53 @@ export default class ApplicationAdapter extends RESTAdapter {
|
||||
return super.handleResponse(status, headers, payload, requestData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add convenience booleans to each error within the errors list indicating
|
||||
* the type of error that occurred. This is useful in downstream templates,
|
||||
* e.g. `{{if error.isForbidden}}`.
|
||||
*
|
||||
* Error booleans are attached based on the error status code:
|
||||
*
|
||||
* - `401 isUnauthenticated`: the session isn't authenticated
|
||||
* - `403 isForbidden`: the session is authenticated but does not have
|
||||
* permission to perform the requested action
|
||||
* - `404 isNotFound`: the requested resource could not be found
|
||||
* - `500 isServer`: an internal server error occurred
|
||||
* - `isUnknown`: an error occurred, but we don't know which or
|
||||
* we don't distinguish it yet
|
||||
*
|
||||
* @override
|
||||
* @method normalizeErrorResponse
|
||||
* @param {Number} status
|
||||
* @param {Object} headers
|
||||
* @param {Object} payload
|
||||
* @return {Array} errors payload
|
||||
*/
|
||||
normalizeErrorResponse(/*status, headers, payload*/) {
|
||||
const errors = super.normalizeErrorResponse(...arguments);
|
||||
if (isArray(errors)) {
|
||||
errors.forEach(error => {
|
||||
switch (Number(error.status)) {
|
||||
case 401:
|
||||
error.isUnauthenticated = true;
|
||||
break;
|
||||
case 403:
|
||||
error.isForbidden = true;
|
||||
break;
|
||||
case 404:
|
||||
error.isNotFound = true;
|
||||
break;
|
||||
case 500:
|
||||
error.isServer = true;
|
||||
break;
|
||||
default:
|
||||
error.isUnknown = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the errors found in a payload from our API into JSON API
|
||||
* error format.
|
||||
@@ -103,6 +151,7 @@ export default class ApplicationAdapter extends RESTAdapter {
|
||||
// Normalize the primary error message into "base", which is an error
|
||||
// that applies to the whole model instance
|
||||
const baseError = {
|
||||
isInvalid: true,
|
||||
status: payload.source,
|
||||
code: payload.code,
|
||||
detail: payload.message,
|
||||
|
||||
@@ -38,23 +38,37 @@ module('Unit | Adapter | application', function (hooks) {
|
||||
});
|
||||
|
||||
test('it returns an proper InvalidError from handleResponse', function (assert) {
|
||||
assert.expect(3);
|
||||
assert.expect(4);
|
||||
const adapter = this.owner.lookup('adapter:application');
|
||||
let payload = {
|
||||
const payload = {
|
||||
status: 400,
|
||||
code: 'invalid_argument',
|
||||
message: 'The request was invalid.',
|
||||
};
|
||||
let handledResponse = adapter.handleResponse(400, {}, payload);
|
||||
const handledResponse = adapter.handleResponse(400, {}, payload);
|
||||
assert.ok(handledResponse instanceof InvalidError);
|
||||
assert.equal(handledResponse.errors.length, 1);
|
||||
assert.equal(handledResponse.message, 'The request was invalid.');
|
||||
assert.ok(handledResponse.errors[0].isInvalid);
|
||||
});
|
||||
|
||||
test('it assigns convenience booleans for error types', function (assert) {
|
||||
assert.expect(6);
|
||||
const adapter = this.owner.lookup('adapter:application');
|
||||
const getResponse = (status) =>
|
||||
adapter.handleResponse(status, {}, { status });
|
||||
assert.ok(getResponse(401).errors[0].isUnauthenticated);
|
||||
assert.ok(getResponse(403).errors[0].isForbidden);
|
||||
assert.ok(getResponse(404).errors[0].isNotFound);
|
||||
assert.ok(getResponse(500).errors[0].isServer);
|
||||
assert.ok(getResponse(0).errors[0].isUnknown);
|
||||
assert.ok(getResponse(false).errors[0].isUnknown);
|
||||
});
|
||||
|
||||
test('it returns field-level errors in InvalidError from handleResponse', function (assert) {
|
||||
assert.expect(1);
|
||||
const adapter = this.owner.lookup('adapter:application');
|
||||
let payload = {
|
||||
const payload = {
|
||||
status: 400,
|
||||
code: 'invalid_argument',
|
||||
message: 'The request was invalid.',
|
||||
@@ -62,7 +76,7 @@ module('Unit | Adapter | application', function (hooks) {
|
||||
fields: [{ name: 'name', message: 'Name is wrong.' }],
|
||||
},
|
||||
};
|
||||
let handledResponse = adapter.handleResponse(400, {}, payload);
|
||||
const handledResponse = adapter.handleResponse(400, {}, payload);
|
||||
assert.equal(
|
||||
handledResponse.errors.length,
|
||||
2,
|
||||
|
||||
Reference in new issue
Block a user