mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 22:43:30 +03:00
🐛 Added error handling to prev/next post helpers
refs #8703 - On API error, call inverse with a data error, the same as the get helper
This commit is contained in:
parent
b6b2930d15
commit
c49dba12a0
@ -103,7 +103,7 @@ get = function get(resource, options) {
|
||||
apiMethod;
|
||||
|
||||
if (!options.fn) {
|
||||
data.error = i18n.t('warnings.helpers.get.mustBeCalledAsBlock');
|
||||
data.error = i18n.t('warnings.helpers.get.mustBeCalledAsBlock', {helperName: 'get'});
|
||||
logging.warn(data.error);
|
||||
return Promise.resolve();
|
||||
}
|
||||
@ -136,6 +136,7 @@ get = function get(resource, options) {
|
||||
blockParams: blockParams
|
||||
});
|
||||
}).catch(function error(err) {
|
||||
logging.error(err);
|
||||
data.error = err.message;
|
||||
return options.inverse(self, {data: data});
|
||||
});
|
||||
|
@ -6,23 +6,36 @@
|
||||
var proxy = require('./proxy'),
|
||||
Promise = require('bluebird'),
|
||||
|
||||
logging = proxy.logging,
|
||||
i18n = proxy.i18n,
|
||||
createFrame = proxy.hbs.handlebars.createFrame,
|
||||
|
||||
api = proxy.api,
|
||||
isPost = proxy.checks.isPost,
|
||||
|
||||
fetch;
|
||||
|
||||
fetch = function fetch(apiOptions, options) {
|
||||
return api.posts.read(apiOptions).then(function (result) {
|
||||
var related = result.posts[0];
|
||||
fetch = function fetch(apiOptions, options, data) {
|
||||
var self = this;
|
||||
|
||||
if (related.previous) {
|
||||
return options.fn(related.previous);
|
||||
} else if (related.next) {
|
||||
return options.fn(related.next);
|
||||
} else {
|
||||
return options.inverse(this);
|
||||
}
|
||||
});
|
||||
return api.posts
|
||||
.read(apiOptions)
|
||||
.then(function handleSuccess(result) {
|
||||
var related = result.posts[0];
|
||||
|
||||
if (related.previous) {
|
||||
return options.fn(related.previous, {data: data});
|
||||
} else if (related.next) {
|
||||
return options.fn(related.next, {data: data});
|
||||
} else {
|
||||
return options.inverse(self, {data: data});
|
||||
}
|
||||
})
|
||||
.catch(function handleError(err) {
|
||||
logging.error(err);
|
||||
data.error = err.message;
|
||||
return options.inverse(self, {data: data});
|
||||
});
|
||||
};
|
||||
|
||||
// If prevNext method is called without valid post data then we must return a promise, if there is valid post data
|
||||
@ -31,14 +44,21 @@ fetch = function fetch(apiOptions, options) {
|
||||
module.exports = function prevNext(options) {
|
||||
options = options || {};
|
||||
|
||||
var apiOptions = {
|
||||
include: options.name === 'prev_post' ? 'previous,previous.author,previous.tags' : 'next,next.author,next.tags'
|
||||
};
|
||||
var data = createFrame(options.data),
|
||||
apiOptions = {
|
||||
include: options.name === 'prev_post' ? 'previous,previous.author,previous.tags' : 'next,next.author,next.tags'
|
||||
};
|
||||
|
||||
if (!options.fn) {
|
||||
data.error = i18n.t('warnings.helpers.mustBeCalledAsBlock', {helperName: options.name});
|
||||
logging.warn(data.error);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
if (isPost(this) && this.status === 'published') {
|
||||
apiOptions.slug = this.slug;
|
||||
return fetch(apiOptions, options);
|
||||
return fetch(apiOptions, options, data);
|
||||
} else {
|
||||
return Promise.resolve(options.inverse(this));
|
||||
return Promise.resolve(options.inverse(this, {data: data}));
|
||||
}
|
||||
};
|
||||
|
@ -487,11 +487,11 @@
|
||||
"helperNotAvailable": "The \\{\\{{helperName}\\}\\} helper is not available.",
|
||||
"flagMustBeEnabled": "The {flagName} flag must be enabled in labs if you wish to use the \\{\\{{helperName}\\}\\} helper.",
|
||||
"seeLink": "See {url}",
|
||||
"mustBeCalledAsBlock": "The \\{\\{{helperName}\\}\\} helper must be called as a block. E.g. \\{\\{#{helperName}\\}\\} \\{\\{/{helperName}\\}\\}",
|
||||
"foreach": {
|
||||
"iteratorNeeded": "Need to pass an iterator to #foreach"
|
||||
},
|
||||
"get": {
|
||||
"mustBeCalledAsBlock": "Get helper must be called as a block",
|
||||
"invalidResource": "Invalid resource given to get helper"
|
||||
},
|
||||
"has": {
|
||||
|
@ -5,6 +5,7 @@ var should = require('should'), // jshint ignore:line
|
||||
// Stuff we are testing
|
||||
helpers = require('../../../server/helpers'),
|
||||
api = require('../../../server/api'),
|
||||
errors = require('../../../server/errors'),
|
||||
|
||||
sandbox = sinon.sandbox.create();
|
||||
|
||||
@ -31,25 +32,29 @@ describe('{{next_post}} helper', function () {
|
||||
inverse = sinon.spy(),
|
||||
optionsData = {name: 'next_post', fn: fn, inverse: inverse};
|
||||
|
||||
helpers.prev_post.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
mobiledoc: markdownToMobiledoc('ff'),
|
||||
title: 'post2',
|
||||
slug: 'current',
|
||||
created_at: new Date(0),
|
||||
url: '/current/'
|
||||
}, optionsData).then(function () {
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
helpers.prev_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
mobiledoc: markdownToMobiledoc('ff'),
|
||||
title: 'post2',
|
||||
slug: 'current',
|
||||
created_at: new Date(0),
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
|
||||
readPostStub.calledOnce.should.be.true();
|
||||
readPostStub.firstCall.args[0].include.should.eql('next,next.author,next.tags');
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
console.log('err ', err);
|
||||
done(err);
|
||||
});
|
||||
console.log(fn.firstCall.args);
|
||||
fn.firstCall.args.should.have.lengthOf(2);
|
||||
fn.firstCall.args[0].should.have.properties('slug', 'title');
|
||||
fn.firstCall.args[1].should.be.an.Object().and.have.property('data');
|
||||
readPostStub.calledOnce.should.be.true();
|
||||
readPostStub.firstCall.args[0].include.should.eql('next,next.author,next.tags');
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
});
|
||||
|
||||
@ -67,20 +72,27 @@ describe('{{next_post}} helper', function () {
|
||||
inverse = sinon.spy(),
|
||||
optionsData = {name: 'next_post', fn: fn, inverse: inverse};
|
||||
|
||||
helpers.prev_post.call({
|
||||
html: 'content',
|
||||
mobiledoc: markdownToMobiledoc('ff'),
|
||||
title: 'post2',
|
||||
slug: 'current',
|
||||
created_at: new Date(0),
|
||||
url: '/current/'
|
||||
}, optionsData).then(function () {
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.true();
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
});
|
||||
helpers.prev_post
|
||||
.call({
|
||||
html: 'content',
|
||||
mobiledoc: markdownToMobiledoc('ff'),
|
||||
title: 'post2',
|
||||
slug: 'current',
|
||||
created_at: new Date(0),
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.true();
|
||||
|
||||
console.log(inverse.firstCall.args);
|
||||
inverse.firstCall.args.should.have.lengthOf(2);
|
||||
inverse.firstCall.args[0].should.have.properties('slug', 'title');
|
||||
inverse.firstCall.args[1].should.be.an.Object().and.have.property('data');
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
});
|
||||
|
||||
@ -98,14 +110,15 @@ describe('{{next_post}} helper', function () {
|
||||
inverse = sinon.spy(),
|
||||
optionsData = {name: 'next_post', fn: fn, inverse: inverse};
|
||||
|
||||
helpers.prev_post.call({}, optionsData).then(function () {
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.true();
|
||||
readPostStub.called.should.be.false();
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
});
|
||||
helpers.prev_post
|
||||
.call({}, optionsData)
|
||||
.then(function () {
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.true();
|
||||
readPostStub.called.should.be.false();
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
});
|
||||
|
||||
@ -125,22 +138,77 @@ describe('{{next_post}} helper', function () {
|
||||
inverse = sinon.spy(),
|
||||
optionsData = {name: 'next_post', fn: fn, inverse: inverse};
|
||||
|
||||
helpers.prev_post.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
mobiledoc: markdownToMobiledoc('ff'),
|
||||
title: 'post2',
|
||||
slug: 'current',
|
||||
created_at: new Date(0),
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
helpers.prev_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'draft',
|
||||
mobiledoc: markdownToMobiledoc('ff'),
|
||||
title: 'post2',
|
||||
slug: 'current',
|
||||
created_at: new Date(0),
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.called.should.be.true();
|
||||
inverse.called.should.be.false();
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.true();
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('general error handling', function () {
|
||||
beforeEach(function () {
|
||||
readPostStub = sandbox.stub(api.posts, 'read', function () {
|
||||
return Promise.reject(new errors.NotFoundError({message: 'Something wasn\'t found'}));
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle error from the API', function (done) {
|
||||
var fn = sinon.spy(),
|
||||
inverse = sinon.spy(),
|
||||
optionsData = {name: 'next_post', fn: fn, inverse: inverse};
|
||||
|
||||
helpers.prev_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
mobiledoc: markdownToMobiledoc('ff'),
|
||||
title: 'post2',
|
||||
slug: 'current',
|
||||
created_at: new Date(0),
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.called.should.be.false();
|
||||
inverse.calledOnce.should.be.true();
|
||||
|
||||
inverse.firstCall.args[1].should.be.an.Object().and.have.property('data');
|
||||
inverse.firstCall.args[1].data.should.be.an.Object().and.have.property('error');
|
||||
inverse.firstCall.args[1].data.error.should.match(/^Something wasn't found/);
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
|
||||
it('should show warning for call without any options', function (done) {
|
||||
var fn = sinon.spy(),
|
||||
inverse = sinon.spy(),
|
||||
optionsData = {name: 'next_post'};
|
||||
|
||||
helpers.prev_post
|
||||
.call(
|
||||
{},
|
||||
optionsData
|
||||
)
|
||||
.then(function () {
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.false();
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user