🐛 Fixed async helpers nested in template helpers
closes #10643 The async resolver in express-hbs relies on storing the state of the promises on the `this` value inside of a helper, which is always set to the `context`. This patch updates our helpers which render templates, to use `this` as the context when rendering their templates.
This commit is contained in:
parent
0e2ce29468
commit
15585971e2
@ -75,8 +75,11 @@ module.exports = function navigation(options) {
|
||||
return out;
|
||||
});
|
||||
|
||||
const context = _.merge({}, this, options.hash, {navigation: output});
|
||||
// CASE: The navigation helper should have access to the navigation items at the top level.
|
||||
this.navigation = output;
|
||||
// CASE: The navigation helper will forward attributes passed to it.
|
||||
_.merge(this, options.hash);
|
||||
const data = createFrame(options.data);
|
||||
|
||||
return templates.execute('navigation', context, {data});
|
||||
return templates.execute('navigation', this, {data});
|
||||
};
|
||||
|
@ -41,10 +41,14 @@ pagination = function (options) {
|
||||
!_.isNumber(this.pagination.total) || !_.isNumber(this.pagination.limit)) {
|
||||
throw new errors.IncorrectUsageError({message: i18n.t('warnings.helpers.pagination.valuesMustBeNumeric')});
|
||||
}
|
||||
const context = _.merge({}, this, options.hash, this.pagination);
|
||||
|
||||
// CASE: The pagination helper should have access to the pagination properties at the top level.
|
||||
_.merge(this, this.pagination);
|
||||
// CASE: The pagination helper will forward attributes passed to it.
|
||||
_.merge(this, options.hash);
|
||||
const data = createFrame(options.data);
|
||||
|
||||
return templates.execute('pagination', context, {data});
|
||||
return templates.execute('pagination', this, {data});
|
||||
};
|
||||
|
||||
module.exports = pagination;
|
||||
|
@ -1,18 +1,14 @@
|
||||
var should = require('should'),
|
||||
hbs = require('../../../frontend/services/themes/engine'),
|
||||
const should = require('should');
|
||||
const hbs = require('../../../frontend/services/themes/engine');
|
||||
const configUtils = require('../../utils/configUtils');
|
||||
const path = require('path');
|
||||
const helpers = require('../../../frontend/helpers');
|
||||
|
||||
configUtils = require('../../utils/configUtils'),
|
||||
path = require('path'),
|
||||
|
||||
helpers = require('../../../frontend/helpers');
|
||||
const runHelper = data => helpers.navigation.call({}, data);
|
||||
const runHelperThunk = data => () => runHelper(data);
|
||||
|
||||
describe('{{navigation}} helper', function () {
|
||||
var runHelper = function (data) {
|
||||
return function () {
|
||||
helpers.navigation(data);
|
||||
};
|
||||
},
|
||||
optionsData;
|
||||
let optionsData;
|
||||
|
||||
before(function (done) {
|
||||
hbs.express4({
|
||||
@ -26,6 +22,7 @@ describe('{{navigation}} helper', function () {
|
||||
// The navigation partial expects this helper
|
||||
// @TODO: change to register with Ghost's own registration tools
|
||||
hbs.registerHelper('url', helpers.url);
|
||||
hbs.registerHelper('foreach', helpers.foreach);
|
||||
});
|
||||
|
||||
beforeEach(function () {
|
||||
@ -44,24 +41,24 @@ describe('{{navigation}} helper', function () {
|
||||
it('should throw errors on invalid data', function () {
|
||||
// Test 1: navigation = string
|
||||
optionsData.data.blog.navigation = 'not an object';
|
||||
runHelper(optionsData).should.throwError('navigation data is not an object or is a function');
|
||||
runHelperThunk(optionsData).should.throwError('navigation data is not an object or is a function');
|
||||
|
||||
// Test 2: navigation = function
|
||||
optionsData.data.blog.navigation = function () {
|
||||
};
|
||||
runHelper(optionsData).should.throwError('navigation data is not an object or is a function');
|
||||
runHelperThunk(optionsData).should.throwError('navigation data is not an object or is a function');
|
||||
|
||||
// Test 3: invalid label
|
||||
optionsData.data.blog.navigation = [{label: 1, url: 'bar'}];
|
||||
runHelper(optionsData).should.throwError('Invalid value, Url and Label must be strings');
|
||||
runHelperThunk(optionsData).should.throwError('Invalid value, Url and Label must be strings');
|
||||
|
||||
// Test 4: invalid url
|
||||
optionsData.data.blog.navigation = [{label: 'foo', url: 1}];
|
||||
runHelper(optionsData).should.throwError('Invalid value, Url and Label must be strings');
|
||||
runHelperThunk(optionsData).should.throwError('Invalid value, Url and Label must be strings');
|
||||
});
|
||||
|
||||
it('can render empty nav', function () {
|
||||
var rendered = helpers.navigation(optionsData);
|
||||
var rendered = runHelper(optionsData);
|
||||
|
||||
should.exist(rendered);
|
||||
rendered.string.should.be.equal('');
|
||||
@ -73,7 +70,7 @@ describe('{{navigation}} helper', function () {
|
||||
delete optionsData.data.root.relativeUrl;
|
||||
|
||||
optionsData.data.blog.navigation = [singleItem];
|
||||
rendered = helpers.navigation(optionsData);
|
||||
rendered = runHelper(optionsData);
|
||||
rendered.string.should.containEql('li');
|
||||
rendered.string.should.containEql('nav-foo');
|
||||
rendered.string.should.containEql('/foo');
|
||||
@ -85,7 +82,7 @@ describe('{{navigation}} helper', function () {
|
||||
rendered;
|
||||
|
||||
optionsData.data.blog.navigation = [singleItem];
|
||||
rendered = helpers.navigation(optionsData);
|
||||
rendered = runHelper(optionsData);
|
||||
|
||||
should.exist(rendered);
|
||||
rendered.string.should.containEql('li');
|
||||
@ -101,7 +98,7 @@ describe('{{navigation}} helper', function () {
|
||||
rendered;
|
||||
|
||||
optionsData.data.blog.navigation = [firstItem, secondItem];
|
||||
rendered = helpers.navigation(optionsData);
|
||||
rendered = runHelper(optionsData);
|
||||
|
||||
should.exist(rendered);
|
||||
rendered.string.should.containEql('nav-foo');
|
||||
@ -117,7 +114,7 @@ describe('{{navigation}} helper', function () {
|
||||
|
||||
optionsData.data.blog.navigation = [firstItem, secondItem];
|
||||
optionsData.data.root.relativeUrl = '/foo';
|
||||
rendered = helpers.navigation(optionsData);
|
||||
rendered = runHelper(optionsData);
|
||||
|
||||
should.exist(rendered);
|
||||
rendered.string.should.containEql('nav-foo');
|
||||
@ -133,7 +130,7 @@ describe('{{navigation}} helper', function () {
|
||||
|
||||
optionsData.data.blog.navigation = [firstItem, secondItem];
|
||||
optionsData.data.root.relativeUrl = '/foo/';
|
||||
rendered = helpers.navigation(optionsData);
|
||||
rendered = runHelper(optionsData);
|
||||
|
||||
should.exist(rendered);
|
||||
rendered.string.should.containEql('nav-foo');
|
||||
@ -147,7 +144,7 @@ describe('{{navigation}} helper', function () {
|
||||
rendered;
|
||||
|
||||
optionsData.data.blog.navigation = [firstItem];
|
||||
rendered = helpers.navigation(optionsData);
|
||||
rendered = runHelper(optionsData);
|
||||
|
||||
should.exist(rendered);
|
||||
rendered.string.should.not.containEql('=');
|
||||
@ -160,7 +157,7 @@ describe('{{navigation}} helper', function () {
|
||||
rendered;
|
||||
|
||||
optionsData.data.blog.navigation = [firstItem];
|
||||
rendered = helpers.navigation(optionsData);
|
||||
rendered = runHelper(optionsData);
|
||||
|
||||
should.exist(rendered);
|
||||
rendered.string.should.containEql('foo=space%20bar');
|
||||
@ -173,7 +170,7 @@ describe('{{navigation}} helper', function () {
|
||||
rendered;
|
||||
|
||||
optionsData.data.blog.navigation = [firstItem];
|
||||
rendered = helpers.navigation(optionsData);
|
||||
rendered = runHelper(optionsData);
|
||||
|
||||
should.exist(rendered);
|
||||
rendered.string.should.not.containEql('foo=space%2520bar');
|
||||
@ -213,7 +210,7 @@ describe('{{navigation}} helper with custom template', function () {
|
||||
// Set @blog.title
|
||||
optionsData.data.blog.title = 'Chaos is a ladder.';
|
||||
|
||||
rendered = helpers.navigation(optionsData);
|
||||
rendered = runHelper(optionsData);
|
||||
|
||||
should.exist(rendered);
|
||||
rendered.string.should.containEql('Chaos is a ladder');
|
||||
@ -229,7 +226,7 @@ describe('{{navigation}} helper with custom template', function () {
|
||||
// Simulate {{navigation isHeader=true}}
|
||||
optionsData.hash = {isHeader: true};
|
||||
|
||||
rendered = helpers.navigation(optionsData);
|
||||
rendered = runHelper(optionsData);
|
||||
|
||||
should.exist(rendered);
|
||||
rendered.string.should.not.containEql('Chaos is a ladder');
|
||||
|
Loading…
Reference in New Issue
Block a user