0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-24 23:48:13 -05:00

Fix editor error handling (#128)

closes https://github.com/TryGhost/Ghost/issues/7099
- update editor base controller's `showErrorAlert` method to handle `AdapterError` or `AjaxError` objects
- update PSM's error handling so that we don't pass an error object wrapped in an array to `showAPIError`
- add missing title attribute to Mirage's Post factory
- remove some leftover `console.log`s
This commit is contained in:
Kevin Ansfield 2016-07-19 00:23:43 +01:00 committed by Austin Burdine
parent b4e812db54
commit 0b2345e635
6 changed files with 80 additions and 32 deletions

View file

@ -7,7 +7,6 @@ import {guidFor} from 'ember-metal/utils';
import injectService from 'ember-service/inject'; import injectService from 'ember-service/inject';
import injectController from 'ember-controller/inject'; import injectController from 'ember-controller/inject';
import {htmlSafe} from 'ember-string'; import {htmlSafe} from 'ember-string';
import {isEmberArray} from 'ember-array/utils';
import {isBlank} from 'ember-utils'; import {isBlank} from 'ember-utils';
import observer from 'ember-metal/observer'; import observer from 'ember-metal/observer';
import run from 'ember-runloop'; import run from 'ember-runloop';
@ -184,9 +183,11 @@ export default Controller.extend(SettingsMenuMixin, {
}); });
}), }),
showErrors(errors) { showError(error) {
errors = isEmberArray(errors) ? errors : [errors]; // TODO: remove null check once ValidationEngine has been removed
this.get('notifications').showAPIError(errors); if (error) {
this.get('notifications').showAPIError(error);
}
}, },
actions: { actions: {
@ -203,8 +204,8 @@ export default Controller.extend(SettingsMenuMixin, {
return; return;
} }
this.get('model').save().catch((errors) => { this.get('model').save().catch((error) => {
this.showErrors(errors); this.showError(error);
this.get('model').rollbackAttributes(); this.get('model').rollbackAttributes();
}); });
}, },
@ -218,8 +219,8 @@ export default Controller.extend(SettingsMenuMixin, {
return; return;
} }
this.get('model').save(this.get('saveOptions')).catch((errors) => { this.get('model').save(this.get('saveOptions')).catch((error) => {
this.showErrors(errors); this.showError(error);
this.get('model').rollbackAttributes(); this.get('model').rollbackAttributes();
}); });
}, },
@ -281,8 +282,8 @@ export default Controller.extend(SettingsMenuMixin, {
} }
return this.get('model').save(); return this.get('model').save();
}).catch((errors) => { }).catch((error) => {
this.showErrors(errors); this.showError(error);
this.get('model').rollbackAttributes(); this.get('model').rollbackAttributes();
}); });
}, },
@ -367,8 +368,8 @@ export default Controller.extend(SettingsMenuMixin, {
return; return;
} }
this.get('model').save().catch((errors) => { this.get('model').save().catch((error) => {
this.showErrors(errors); this.showError(error);
this.get('model').rollbackAttributes(); this.get('model').rollbackAttributes();
}); });
}); });
@ -423,8 +424,8 @@ export default Controller.extend(SettingsMenuMixin, {
return; return;
} }
this.get('model').save().catch((errors) => { this.get('model').save().catch((error) => {
this.showErrors(errors); this.showError(error);
this.get('model').rollbackAttributes(); this.get('model').rollbackAttributes();
}); });
}, },
@ -436,8 +437,8 @@ export default Controller.extend(SettingsMenuMixin, {
return; return;
} }
this.get('model').save().catch((errors) => { this.get('model').save().catch((error) => {
this.showErrors(errors); this.showError(error);
this.get('model').rollbackAttributes(); this.get('model').rollbackAttributes();
}); });
}, },
@ -466,8 +467,8 @@ export default Controller.extend(SettingsMenuMixin, {
return; return;
} }
model.save().catch((errors) => { model.save().catch((error) => {
this.showErrors(errors); this.showError(error);
this.set('selectedAuthor', author); this.set('selectedAuthor', author);
model.rollbackAttributes(); model.rollbackAttributes();
}); });

View file

@ -3,6 +3,7 @@ import Mirage, {faker} from 'ember-cli-mirage';
export default Mirage.Factory.extend({ export default Mirage.Factory.extend({
uuid(i) { return `post-${i}`; }, uuid(i) { return `post-${i}`; },
title(i) { return `Post ${i}`; },
description(i) { return `Title for post ${i}.`; }, description(i) { return `Title for post ${i}.`; },
slug(i) { return `post-${i}`; }, slug(i) { return `post-${i}`; },
markdown(i) { return `Markdown for post ${i}.`; }, markdown(i) { return `Markdown for post ${i}.`; },

View file

@ -297,27 +297,25 @@ export default Mixin.create({
notifications.showNotification(message.htmlSafe(), {delayed: delay}); notifications.showNotification(message.htmlSafe(), {delayed: delay});
}, },
showErrorAlert(prevStatus, status, errors, delay) { showErrorAlert(prevStatus, status, error, delay) {
let message = this.messageMap.errors.post[prevStatus][status]; let message = this.messageMap.errors.post[prevStatus][status];
let notifications = this.get('notifications'); let notifications = this.get('notifications');
let error; let errorMessage;
function isString(str) { function isString(str) {
/*global toString*/ /*global toString*/
return toString.call(str) === '[object String]'; return toString.call(str) === '[object String]';
} }
if (errors && isString(errors)) { if (error && isString(error)) {
error = errors; errorMessage = error;
} else if (errors && errors[0] && isString(errors[0])) { } else if (error && error.errors && error.errors[0].message) {
error = errors[0]; errorMessage = error.errors[0].message;
} else if (errors && errors[0] && errors[0].message && isString(errors[0].message)) {
error = errors[0].message;
} else { } else {
error = 'Unknown Error'; errorMessage = 'Unknown Error';
} }
message += `: ${error}`; message += `: ${errorMessage}`;
message = htmlSafe(message); message = htmlSafe(message);
notifications.showAlert(message, {type: 'error', delayed: delay, key: 'post.save'}); notifications.showAlert(message, {type: 'error', delayed: delay, key: 'post.save'});

View file

@ -92,7 +92,6 @@ export default Service.extend({
if (isVersionMismatchError(resp)) { if (isVersionMismatchError(resp)) {
return this.get('upgradeStatus').requireUpgrade(); return this.get('upgradeStatus').requireUpgrade();
} else if (isMaintenanceError(resp)) { } else if (isMaintenanceError(resp)) {
console.log(this.get('upgradeStatus'));
return this.get('upgradeStatus').maintenanceAlert(); return this.get('upgradeStatus').maintenanceAlert();
} }

View file

@ -108,7 +108,6 @@ describe('Acceptance: Editor', function() {
// saves the post with the new date // saves the post with the new date
fillIn('input[name="post-setting-date"]', '10 May 16 @ 10:00'); fillIn('input[name="post-setting-date"]', '10 May 16 @ 10:00');
// return pauseTest();
triggerEvent('input[name="post-setting-date"]', 'blur'); triggerEvent('input[name="post-setting-date"]', 'blur');
// saving // saving
click('.view-header .btn.btn-sm.js-publish-button'); click('.view-header .btn.btn-sm.js-publish-button');
@ -340,6 +339,58 @@ describe('Acceptance: Editor', function() {
}); });
}); });
it('handles validation errors when scheduling', function () {
let saveCount = 0;
server.put('/posts/:id/', function (db, request) {
// we have three saves occurring here :-(
// 1. Auto-save of draft
// 2. Change of publish time
// 3. Pressing the Schedule button
saveCount++;
if (saveCount === 3) {
return new Mirage.Response(422, {}, {
errors: [{
errorType: 'ValidationError',
message: 'Error test'
}]
});
} else {
let {id} = request.params;
let [attrs] = JSON.parse(request.requestBody).posts;
delete attrs.id;
let post = db.posts.update(id, attrs);
return {
posts: [post]
};
}
});
let post = server.create('post', 1);
let plusTenMin = moment().add(10, 'minutes').format('DD MMM YY @ HH:mm').toString();
visit(`/editor/${post.id}`);
fillIn('input[name="post-setting-date"]', plusTenMin);
triggerEvent('input[name="post-setting-date"]', 'blur');
click('.post-save-schedule a');
click('.view-header .btn.btn-sm.js-publish-button');
andThen(() => {
expect(
find('.gh-alert').length,
'number of alerts after failed schedule'
).to.equal(1);
expect(
find('.gh-alert').text(),
'alert text after failed schedule'
).to.match(/Scheduling failed: Error test/);
});
});
it('renders first countdown notification before scheduled time', function () { it('renders first countdown notification before scheduled time', function () {
/* jscs:disable requireCamelCaseOrUpperCaseIdentifiers */ /* jscs:disable requireCamelCaseOrUpperCaseIdentifiers */
let clock = sinon.useFakeTimers(moment().valueOf()); let clock = sinon.useFakeTimers(moment().valueOf());

View file

@ -23,8 +23,6 @@ describe('Unit: Validator: subscriber', function () {
let subscriber = Subscriber.create({}); let subscriber = Subscriber.create({});
let properties = subscriber.get('validators.subscriber.properties'); let properties = subscriber.get('validators.subscriber.properties');
console.log(subscriber);
expect(properties, 'properties').to.include('email'); expect(properties, 'properties').to.include('email');
}); });