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

View File

@ -3,6 +3,7 @@ import Mirage, {faker} from 'ember-cli-mirage';
export default Mirage.Factory.extend({
uuid(i) { return `post-${i}`; },
title(i) { return `Post ${i}`; },
description(i) { return `Title for post ${i}.`; },
slug(i) { return `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});
},
showErrorAlert(prevStatus, status, errors, delay) {
showErrorAlert(prevStatus, status, error, delay) {
let message = this.messageMap.errors.post[prevStatus][status];
let notifications = this.get('notifications');
let error;
let errorMessage;
function isString(str) {
/*global toString*/
return toString.call(str) === '[object String]';
}
if (errors && isString(errors)) {
error = errors;
} else if (errors && errors[0] && isString(errors[0])) {
error = errors[0];
} else if (errors && errors[0] && errors[0].message && isString(errors[0].message)) {
error = errors[0].message;
if (error && isString(error)) {
errorMessage = error;
} else if (error && error.errors && error.errors[0].message) {
errorMessage = error.errors[0].message;
} else {
error = 'Unknown Error';
errorMessage = 'Unknown Error';
}
message += `: ${error}`;
message += `: ${errorMessage}`;
message = htmlSafe(message);
notifications.showAlert(message, {type: 'error', delayed: delay, key: 'post.save'});

View File

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

View File

@ -108,7 +108,6 @@ describe('Acceptance: Editor', function() {
// saves the post with the new date
fillIn('input[name="post-setting-date"]', '10 May 16 @ 10:00');
// return pauseTest();
triggerEvent('input[name="post-setting-date"]', 'blur');
// saving
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 () {
/* jscs:disable requireCamelCaseOrUpperCaseIdentifiers */
let clock = sinon.useFakeTimers(moment().valueOf());

View File

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