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:
parent
b4e812db54
commit
0b2345e635
6 changed files with 80 additions and 32 deletions
|
@ -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();
|
||||||
});
|
});
|
||||||
|
|
|
@ -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}.`; },
|
||||||
|
|
|
@ -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'});
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue