🐛 Fixed missing error notification when attempting to activate an invalid theme

no issue
- updates error handling to work with new v2 error response formats
  - `.errorType` -> `.error`
  - `.errorDetails` -> `.details`
This commit is contained in:
Kevin Ansfield 2019-03-25 11:29:14 +00:00
parent 98a93b5251
commit d0a834b477
27 changed files with 44 additions and 44 deletions

View File

@ -129,7 +129,7 @@ export default ModalComponent.extend({
uploadFailed(error) {
if (isThemeValidationError(error)) {
let errors = error.payload.errors[0].errorDetails;
let errors = error.payload.errors[0].details;
let fatalErrors = [];
let normalErrors = [];

View File

@ -146,7 +146,7 @@ export default Controller.extend({
}
}).catch((error) => {
if (isThemeValidationError(error)) {
let errors = error.payload.errors[0].errorDetails;
let errors = error.payload.errors[0].details;
let fatalErrors = [];
let normalErrors = [];

View File

@ -29,7 +29,7 @@ export function isVersionMismatchError(errorOrStatus, payload) {
if (isAjaxError(errorOrStatus)) {
return errorOrStatus instanceof VersionMismatchError;
} else {
return get(payload || {}, 'errors.firstObject.errorType') === 'VersionMismatchError';
return get(payload || {}, 'errors.firstObject.type') === 'VersionMismatchError';
}
}
@ -109,7 +109,7 @@ export function isThemeValidationError(errorOrStatus, payload) {
if (isAjaxError(errorOrStatus)) {
return errorOrStatus instanceof ThemeValidationError;
} else {
return get(payload || {}, 'errors.firstObject.errorType') === 'ThemeValidationError';
return get(payload || {}, 'errors.firstObject.type') === 'ThemeValidationError';
}
}

View File

@ -18,7 +18,7 @@ export default function mockAuthentication(server) {
errors: [
{
message: 'There is no user with that email address.',
errorType: 'NotFoundError'
type: 'NotFoundError'
}
]
});

View File

@ -14,7 +14,7 @@ export default function mockIntegrations(server) {
if (!params.name) {
return new Response(422, {}, {errors: [{
errorType: 'ValidationError',
type: 'ValidationError',
message: 'Name is required',
property: 'name'
}]});
@ -22,7 +22,7 @@ export default function mockIntegrations(server) {
if (integrations.findBy({name: params.name}) || params.name.match(/Duplicate/i)) {
return new Response(422, {}, {errors: [{
errorType: 'ValidationError',
type: 'ValidationError',
message: 'Name has already been used',
property: 'name'
}]});

View File

@ -11,7 +11,7 @@ export default function mockInvites(server) {
return invite || new Response(404, {}, {
errors: [{
errorType: 'NotFoundError',
type: 'NotFoundError',
message: 'Invite not found.'
}]
});

View File

@ -9,7 +9,7 @@ export default function mockMembers(server) {
return member || new Response(404, {}, {
errors: [{
errorType: 'NotFoundError',
type: 'NotFoundError',
message: 'Member not found.'
}]
});

View File

@ -97,7 +97,7 @@ export default function mockPages(server) {
return page || new Response(404, {}, {
errors: [{
errorType: 'NotFoundError',
type: 'NotFoundError',
message: 'Page not found.'
}]
});

View File

@ -97,7 +97,7 @@ export default function mockPosts(server) {
return post || new Response(404, {}, {
errors: [{
errorType: 'NotFoundError',
type: 'NotFoundError',
message: 'Post not found.'
}]
});

View File

@ -12,7 +12,7 @@ export default function mockSubscribers(server) {
if (subscriber) {
return new Response(422, {}, {
errors: [{
errorType: 'ValidationError',
type: 'ValidationError',
message: 'Email already exists.',
property: 'email'
}]

View File

@ -10,7 +10,7 @@ export default function mockUsers(server) {
return user;
} else {
return new Response(404, {}, {errors: [
{message: 'Not found', errorType: 'NotFoundError'}
{message: 'Not found', type: 'NotFoundError'}
]});
}
});

View File

@ -11,7 +11,7 @@ export default function mockWebhooks(server) {
if (!attrs.name) {
errors.push({
errorType: 'ValidationError',
type: 'ValidationError',
message: 'Name is required',
property: 'name'
});
@ -19,7 +19,7 @@ export default function mockWebhooks(server) {
if (!attrs.event) {
errors.push({
errorType: 'ValidationError',
type: 'ValidationError',
message: 'Event is required',
property: 'event'
});
@ -27,7 +27,7 @@ export default function mockWebhooks(server) {
if (!attrs.targetUrl) {
errors.push({
errorType: 'ValidationError',
type: 'ValidationError',
message: 'Target URL is required',
property: 'target_url'
});
@ -35,7 +35,7 @@ export default function mockWebhooks(server) {
if (attrs.name && (webhooks.findBy({name: attrs.name, integrationId: attrs.integrationId}) || attrs.name.match(/Duplicate/i))) {
errors.push({
errorType: 'ValidationError',
type: 'ValidationError',
message: 'Name has already been used',
property: 'name'
});
@ -44,7 +44,7 @@ export default function mockWebhooks(server) {
// TODO: check server-side validation
if (webhooks.findBy({targetUrl: attrs.targetUrl, event: attrs.event})) {
errors.push({
errorType: 'ValidationError',
type: 'ValidationError',
message: 'Target URL has already been used for this event',
property: 'target_url'
});

View File

@ -59,7 +59,7 @@ export function paginateModelCollection(modelName, collection, page, limit) {
export function maintenanceResponse() {
return new Response(503, {}, {
errors: [{
errorType: 'Maintenance'
type: 'Maintenance'
}]
});
}
@ -67,7 +67,7 @@ export function maintenanceResponse() {
export function versionMismatchResponse() {
return new Response(400, {}, {
errors: [{
errorType: 'VersionMismatchError'
type: 'VersionMismatchError'
}]
});
}

View File

@ -51,7 +51,7 @@ describe('Acceptance: Authentication', function () {
// return a 401 when attempting to retrieve users
this.server.get('/users/', () => new Response(401, {}, {
errors: [
{message: 'Access denied.', errorType: 'UnauthorizedError'}
{message: 'Access denied.', type: 'UnauthorizedError'}
]
}));
@ -116,7 +116,7 @@ describe('Acceptance: Authentication', function () {
if (attrs.mobiledoc.cards[0][1].markdown === 'Edited post body') {
return new Response(401, {}, {
errors: [
{message: 'Access denied.', errorType: 'UnauthorizedError'}
{message: 'Access denied.', type: 'UnauthorizedError'}
]
});
} else {

View File

@ -427,7 +427,7 @@ describe('Acceptance: Editor', function () {
this.server.put('/posts/:id/', function () {
return new Mirage.Response(422, {}, {
errors: [{
errorType: 'ValidationError',
type: 'ValidationError',
message: 'Error test'
}]
});

View File

@ -293,8 +293,8 @@ describe('Acceptance: Settings - Design', function () {
errors: [
{
message: 'Theme is not compatible or contains errors.',
errorType: 'ThemeValidationError',
errorDetails: [
type: 'ThemeValidationError',
details: [
{
level: 'error',
rule: 'Assets such as CSS & JS must use the <code>{{asset}}</code> helper',
@ -491,8 +491,8 @@ describe('Acceptance: Settings - Design', function () {
errors: [
{
message: 'Theme is not compatible or contains errors.',
errorType: 'ThemeValidationError',
errorDetails: [
type: 'ThemeValidationError',
details: [
{
level: 'error',
rule: 'Assets such as CSS & JS must use the <code>{{asset}}</code> helper',

View File

@ -133,7 +133,7 @@ describe('Acceptance: Settings - General', function () {
this.server.post('/images/upload/', function () {
return {
errors: [{
errorType: 'ValidationError',
type: 'ValidationError',
message: 'Wrong icon size'
}]
};
@ -202,7 +202,7 @@ describe('Acceptance: Settings - General', function () {
this.server.post('/images/upload/', function () {
return {
errors: [{
errorType: 'ValidationError',
type: 'ValidationError',
message: 'Wrong logo size'
}]
};
@ -271,7 +271,7 @@ describe('Acceptance: Settings - General', function () {
this.server.post('/images/upload/', function () {
return {
errors: [{
errorType: 'ValidationError',
type: 'ValidationError',
message: 'Wrong coverImage size'
}]
};

View File

@ -125,7 +125,7 @@ describe('Acceptance: Settings - Labs', function () {
// failed upload
this.server.post('/redirects/json/', {
errors: [{
errorType: 'BadRequestError',
type: 'BadRequestError',
message: 'Test failure message'
}]
}, 400);
@ -238,7 +238,7 @@ describe('Acceptance: Settings - Labs', function () {
// failed upload
this.server.post('/settings/routes/yaml/', {
errors: [{
errorType: 'BadRequestError',
type: 'BadRequestError',
message: 'Test failure message'
}]
}, 400);

View File

@ -98,7 +98,7 @@ describe('Acceptance: Settings - Integrations - Slack', function () {
return new Mirage.Response(422, {}, {
errors: [
{
errorType: 'ValidationError',
type: 'ValidationError',
message: 'Test error'
}
]

View File

@ -309,7 +309,7 @@ describe('Acceptance: Settings - Tags', function () {
it('redirects to 404 when tag does not exist', async function () {
this.server.get('/tags/slug/unknown/', function () {
return new Response(404, {'Content-Type': 'application/json'}, {errors: [{message: 'Tag not found.', errorType: 'NotFoundError'}]});
return new Response(404, {'Content-Type': 'application/json'}, {errors: [{message: 'Tag not found.', type: 'NotFoundError'}]});
});
errorOverride();

View File

@ -151,7 +151,7 @@ describe('Acceptance: Setup', function () {
return new Response(422, {}, {
errors: [
{
errorType: 'ValidationError',
type: 'ValidationError',
message: 'Server response message'
}
]
@ -198,7 +198,7 @@ describe('Acceptance: Setup', function () {
return new Response(401, {}, {
errors: [
{
errorType: 'UnauthorizedError',
type: 'UnauthorizedError',
message: 'Access Denied from url: unknown.com. Please use the url configured in config.js.'
}
]
@ -241,7 +241,7 @@ describe('Acceptance: Setup', function () {
return new Response(422, {}, {
errors: [
{
errorType: 'ValidationError',
type: 'ValidationError',
message: 'Dummy validation error'
}
]

View File

@ -43,7 +43,7 @@ describe('Acceptance: Signin', function () {
} else {
return new Response(401, {}, {
errors: [{
errorType: 'UnauthorizedError',
type: 'UnauthorizedError',
message: 'Invalid Password'
}]
});

View File

@ -874,7 +874,7 @@ describe('Acceptance: Staff', function () {
it('redirects to 404 when user does not exist', async function () {
this.server.get('/users/slug/unknown/', function () {
return new Response(404, {'Content-Type': 'application/json'}, {errors: [{message: 'User not found.', errorType: 'NotFoundError'}]});
return new Response(404, {'Content-Type': 'application/json'}, {errors: [{message: 'User not found.', type: 'NotFoundError'}]});
});
errorOverride();
@ -898,7 +898,7 @@ describe('Acceptance: Staff', function () {
this.server.get('/invites/', function () {
return new Response(403, {}, {
errors: [{
errorType: 'NoPermissionError',
type: 'NoPermissionError',
message: 'You do not have permission to perform this action'
}]
});

View File

@ -27,7 +27,7 @@ const stubFailedUpload = function (server, code, error, delay = 0) {
server.post('/ghost/api/v2/admin/images/', function () {
return [code, {'Content-Type': 'application/json'}, JSON.stringify({
errors: [{
errorType: error,
type: error,
message: `Error: ${error}`
}]
})];

View File

@ -38,7 +38,7 @@ const stubFailedUpload = function (server, code, error, delay = 0) {
server.post('/ghost/api/v2/admin/images/upload/', function () {
return [code, {'Content-Type': 'application/json'}, JSON.stringify({
errors: [{
errorType: error,
type: error,
message: `Error: ${error}`
}]
})];

View File

@ -17,7 +17,7 @@ const stubFailedUpload = function (server, code, error, delay = 0) {
server.post('/ghost/api/v2/admin/images/upload/', function () {
return [code, {'Content-Type': 'application/json'}, JSON.stringify({
errors: [{
errorType: error,
type: error,
message: `Error: ${error}`
}]
})];

View File

@ -131,7 +131,7 @@ describe('Integration: Service: ajax', function () {
{'Content-Type': 'application/json'},
JSON.stringify({
errors: [{
errorType: 'VersionMismatchError',
type: 'VersionMismatchError',
statusCode: 400
}]
})