🐛 {{access}} property incorrect when using get/next-post/prev-post helpers (#14256)
refs https://github.com/TryGhost/Team/issues/1367 - The {{access}} property of a post always returned false for non-public content - Added the member context to the get, next-post and prev-post helpers - The get, next-post and prev-post helpers didn't add the member context to the internal API calls - Added the members context to these calls - Added tests that check if the member context is passed to the API calls - Transformed next_post helper tests to async await syntax - Transformed prev_post helper tests to async await syntax
This commit is contained in:
parent
e97abeceb5
commit
f389bab6ab
@ -156,6 +156,7 @@ module.exports = function get(resource, options) {
|
||||
|
||||
// Parse the options we're going to pass to the API
|
||||
apiOptions = parseOptions(ghostGlobals, this, apiOptions);
|
||||
apiOptions.context = {member: data.member};
|
||||
|
||||
// @TODO: https://github.com/TryGhost/Ghost/issues/10548
|
||||
return controller[action](apiOptions).then(function success(result) {
|
||||
|
@ -32,7 +32,8 @@ const buildApiOptions = function buildApiOptions(options, post) {
|
||||
limit: 1,
|
||||
// This line deliberately uses double quotes because GQL cannot handle either double quotes
|
||||
// or escaped singles, see TryGhost/GQL#34
|
||||
filter: "slug:-" + slug + "+published_at:" + op + "'" + publishedAt + "'" // eslint-disable-line quotes
|
||||
filter: "slug:-" + slug + "+published_at:" + op + "'" + publishedAt + "'", // eslint-disable-line quotes
|
||||
context: {member: options.data.member}
|
||||
};
|
||||
|
||||
if (get(options, 'hash.in')) {
|
||||
@ -48,6 +49,11 @@ const buildApiOptions = function buildApiOptions(options, post) {
|
||||
return apiOptions;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {*} options
|
||||
* @param {*} data
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
const fetch = function fetch(options, data) {
|
||||
const self = this;
|
||||
const apiOptions = buildApiOptions(options, this);
|
||||
@ -77,6 +83,10 @@ const fetch = function fetch(options, data) {
|
||||
// If prevNext method is called without valid post data then we must return a promise, if there is valid post data
|
||||
// then the promise is handled in the api call.
|
||||
|
||||
/**
|
||||
* @param {*} options
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
module.exports = function prevNext(options) {
|
||||
options = options || {};
|
||||
|
||||
|
@ -295,4 +295,33 @@ describe('{{#get}} helper', function () {
|
||||
browseStub.firstCall.args[0].limit.should.eql(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('auth', function () {
|
||||
/**
|
||||
* @type sinon.SinonStub<any[], any>
|
||||
*/
|
||||
let browseStub;
|
||||
let member;
|
||||
|
||||
beforeEach(function () {
|
||||
browseStub = sinon.stub().resolves();
|
||||
member = {uuid: 'test'};
|
||||
|
||||
sinon.stub(api, 'postsPublic').get(() => {
|
||||
return {
|
||||
browse: browseStub
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
it('should pass the member context', async function () {
|
||||
locals = {root: {_locals: {apiVersion: API_VERSION}}, member};
|
||||
await get.call(
|
||||
{},
|
||||
'posts',
|
||||
{hash: {}, data: locals, fn: fn, inverse: inverse}
|
||||
);
|
||||
browseStub.firstCall.args[0].context.member.should.eql(member);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -4,6 +4,7 @@ const Promise = require('bluebird');
|
||||
const markdownToMobiledoc = require('../../../utils/fixtures/data-generator').markdownToMobiledoc;
|
||||
const next_post = require('../../../../core/frontend/helpers/prev_post');
|
||||
const api = require('../../../../core/server/api');
|
||||
const should = require('should');
|
||||
|
||||
describe('{{next_post}} helper', function () {
|
||||
const apiVersion = 'canary';
|
||||
@ -42,12 +43,12 @@ describe('{{next_post}} helper', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('shows \'if\' template with next post data', function (done) {
|
||||
it('shows \'if\' template with next post data', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'next_post', data: locals, fn: fn, inverse: inverse};
|
||||
|
||||
next_post
|
||||
await next_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
@ -56,20 +57,15 @@ describe('{{next_post}} helper', function () {
|
||||
slug: 'current',
|
||||
published_at: new Date(0),
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
}, optionsData);
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
});
|
||||
});
|
||||
|
||||
@ -84,12 +80,12 @@ describe('{{next_post}} helper', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('shows \'else\' template', function (done) {
|
||||
it('shows \'else\' template', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'next_post', data: locals, fn: fn, inverse: inverse};
|
||||
|
||||
next_post
|
||||
await next_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
@ -98,18 +94,13 @@ describe('{{next_post}} helper', function () {
|
||||
slug: 'current',
|
||||
published_at: new Date(0),
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.true();
|
||||
}, optionsData);
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.true();
|
||||
|
||||
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);
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
||||
@ -122,21 +113,16 @@ describe('{{next_post}} helper', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('shows \'else\' template', function (done) {
|
||||
it('shows \'else\' template', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'next_post', data: locals, fn: fn, inverse: inverse};
|
||||
|
||||
next_post
|
||||
.call({}, optionsData)
|
||||
.then(function () {
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.true();
|
||||
browsePostsStub.called.should.be.false();
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
await next_post
|
||||
.call({}, optionsData);
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.true();
|
||||
browsePostsStub.called.should.be.false();
|
||||
});
|
||||
});
|
||||
|
||||
@ -158,12 +144,12 @@ describe('{{next_post}} helper', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('shows \'else\' template', function (done) {
|
||||
it('shows \'else\' template', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'next_post', data: locals, fn: fn, inverse: inverse};
|
||||
|
||||
next_post
|
||||
await next_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
@ -173,14 +159,9 @@ describe('{{next_post}} helper', function () {
|
||||
published_at: new Date(0),
|
||||
url: '/current/',
|
||||
page: true
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.true();
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
}, optionsData);
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.true();
|
||||
});
|
||||
});
|
||||
|
||||
@ -202,12 +183,12 @@ describe('{{next_post}} helper', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('shows \'else\' template', function (done) {
|
||||
it('shows \'else\' template', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'next_post', data: locals, fn: fn, inverse: inverse};
|
||||
|
||||
next_post
|
||||
await next_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'draft',
|
||||
@ -216,14 +197,9 @@ describe('{{next_post}} helper', function () {
|
||||
slug: 'current',
|
||||
created_at: new Date(0),
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.true();
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
}, optionsData);
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.true();
|
||||
});
|
||||
});
|
||||
|
||||
@ -238,12 +214,12 @@ describe('{{next_post}} helper', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('shows \'if\' template with prev post data with primary_tag set', function (done) {
|
||||
it('shows \'if\' template with prev post data with primary_tag set', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'next_post', data: locals, fn: fn, inverse: inverse, hash: {in: 'primary_tag'}};
|
||||
|
||||
next_post
|
||||
await next_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
@ -253,29 +229,25 @@ describe('{{next_post}} helper', function () {
|
||||
published_at: new Date(0),
|
||||
primary_tag: {slug: 'test'},
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
}, optionsData);
|
||||
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
browsePostsStub.firstCall.args[0].filter.should.match(/\+primary_tag:test/);
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
browsePostsStub.firstCall.args[0].filter.should.match(/\+primary_tag:test/);
|
||||
});
|
||||
|
||||
it('shows \'if\' template with prev post data with primary_author set', function (done) {
|
||||
it('shows \'if\' template with prev post data with primary_author set', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'next_post', data: locals, fn: fn, inverse: inverse, hash: {in: 'primary_author'}};
|
||||
|
||||
next_post
|
||||
await next_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
@ -285,29 +257,25 @@ describe('{{next_post}} helper', function () {
|
||||
published_at: new Date(0),
|
||||
primary_author: {slug: 'hans'},
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
}, optionsData);
|
||||
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
browsePostsStub.firstCall.args[0].filter.should.match(/\+primary_author:hans/);
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
browsePostsStub.firstCall.args[0].filter.should.match(/\+primary_author:hans/);
|
||||
});
|
||||
|
||||
it('shows \'if\' template with prev post data with author set', function (done) {
|
||||
it('shows \'if\' template with prev post data with author set', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'next_post', data: locals, fn: fn, inverse: inverse, hash: {in: 'author'}};
|
||||
|
||||
next_post
|
||||
await next_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
@ -317,29 +285,25 @@ describe('{{next_post}} helper', function () {
|
||||
published_at: new Date(0),
|
||||
author: {slug: 'author-name'},
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
}, optionsData);
|
||||
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
browsePostsStub.firstCall.args[0].filter.should.match(/\+author:author-name/);
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
browsePostsStub.firstCall.args[0].filter.should.match(/\+author:author-name/);
|
||||
});
|
||||
|
||||
it('shows \'if\' template with prev post data & ignores in author if author isnt present', function (done) {
|
||||
it('shows \'if\' template with prev post data & ignores in author if author isnt present', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'next_post', data: locals, fn: fn, inverse: inverse, hash: {in: 'author'}};
|
||||
|
||||
next_post
|
||||
await next_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
@ -348,29 +312,25 @@ describe('{{next_post}} helper', function () {
|
||||
slug: 'current',
|
||||
published_at: new Date(0),
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
}, optionsData);
|
||||
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
browsePostsStub.firstCall.args[0].filter.should.not.match(/\+author:/);
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
browsePostsStub.firstCall.args[0].filter.should.not.match(/\+author:/);
|
||||
});
|
||||
|
||||
it('shows \'if\' template with prev post data & ignores unknown in value', function (done) {
|
||||
it('shows \'if\' template with prev post data & ignores unknown in value', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'next_post', data: locals, fn: fn, inverse: inverse, hash: {in: 'magic'}};
|
||||
|
||||
next_post
|
||||
await next_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
@ -380,21 +340,17 @@ describe('{{next_post}} helper', function () {
|
||||
published_at: new Date(0),
|
||||
author: {slug: 'author-name'},
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
}, optionsData);
|
||||
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
browsePostsStub.firstCall.args[0].filter.should.not.match(/\+magic/);
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
browsePostsStub.firstCall.args[0].filter.should.not.match(/\+magic/);
|
||||
});
|
||||
});
|
||||
|
||||
@ -405,12 +361,12 @@ describe('{{next_post}} helper', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle error from the API', function (done) {
|
||||
it('should handle error from the API', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'next_post', data: locals, fn: fn, inverse: inverse};
|
||||
|
||||
next_post
|
||||
await next_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
@ -419,37 +375,80 @@ describe('{{next_post}} helper', function () {
|
||||
slug: 'current',
|
||||
published_at: new Date(0),
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.called.should.be.false();
|
||||
inverse.calledOnce.should.be.true();
|
||||
}, optionsData);
|
||||
|
||||
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/);
|
||||
fn.called.should.be.false();
|
||||
inverse.calledOnce.should.be.true();
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
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/);
|
||||
});
|
||||
|
||||
it('should show warning for call without any options', function (done) {
|
||||
it('should show warning for call without any options', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'next_post', data: {root: {}}};
|
||||
|
||||
next_post
|
||||
await next_post
|
||||
.call(
|
||||
{},
|
||||
optionsData
|
||||
)
|
||||
.then(function () {
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.false();
|
||||
);
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.false();
|
||||
});
|
||||
});
|
||||
|
||||
describe('auth', function () {
|
||||
let member;
|
||||
|
||||
beforeEach(function () {
|
||||
member = {uuid: 'test'};
|
||||
browsePostsStub = sinon.stub().callsFake(function (options) {
|
||||
return Promise.resolve({
|
||||
posts: [{slug: '/next/', title: 'post 3'}]
|
||||
});
|
||||
});
|
||||
locals = {
|
||||
root: {
|
||||
_locals: {
|
||||
apiVersion: apiVersion
|
||||
},
|
||||
context: ['post']
|
||||
},
|
||||
member
|
||||
};
|
||||
});
|
||||
|
||||
it('should pass the member context', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'next_post', data: locals, fn: fn, inverse: inverse};
|
||||
|
||||
await next_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
mobiledoc: markdownToMobiledoc('ff'),
|
||||
title: 'post2',
|
||||
slug: 'current',
|
||||
published_at: new Date(0),
|
||||
url: '/current/'
|
||||
}, optionsData);
|
||||
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
|
||||
// Check context passed
|
||||
browsePostsStub.firstCall.args[0].context.member.should.eql(member);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -4,6 +4,7 @@ const Promise = require('bluebird');
|
||||
const markdownToMobiledoc = require('../../../utils/fixtures/data-generator').markdownToMobiledoc;
|
||||
const prev_post = require('../../../../core/frontend/helpers/prev_post');
|
||||
const api = require('../../../../core/server/api');
|
||||
const should = require('should');
|
||||
|
||||
describe('{{prev_post}} helper', function () {
|
||||
const apiVersion = 'canary';
|
||||
@ -42,12 +43,12 @@ describe('{{prev_post}} helper', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('shows \'if\' template with previous post data', function (done) {
|
||||
it('shows \'if\' template with previous post data', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'prev_post', data: locals, fn: fn, inverse: inverse};
|
||||
|
||||
prev_post
|
||||
await prev_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
@ -56,20 +57,16 @@ describe('{{prev_post}} helper', function () {
|
||||
slug: 'current',
|
||||
published_at: new Date(0),
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
}, optionsData);
|
||||
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
});
|
||||
});
|
||||
|
||||
@ -82,12 +79,12 @@ describe('{{prev_post}} helper', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('shows \'else\' template', function (done) {
|
||||
it('shows \'else\' template', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'prev_post', data: locals, fn: fn, inverse: inverse};
|
||||
|
||||
prev_post
|
||||
await prev_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
@ -96,18 +93,14 @@ describe('{{prev_post}} helper', function () {
|
||||
slug: 'current',
|
||||
published_at: new Date(0),
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.true();
|
||||
}, optionsData);
|
||||
|
||||
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');
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.true();
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
||||
@ -120,21 +113,17 @@ describe('{{prev_post}} helper', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('shows \'else\' template', function (done) {
|
||||
it('shows \'else\' template', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'prev_post', data: locals, fn: fn, inverse: inverse};
|
||||
|
||||
prev_post
|
||||
.call({}, optionsData)
|
||||
.then(function () {
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.true();
|
||||
browsePostsStub.called.should.be.false();
|
||||
await prev_post
|
||||
.call({}, optionsData);
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.true();
|
||||
browsePostsStub.called.should.be.false();
|
||||
});
|
||||
});
|
||||
|
||||
@ -156,12 +145,12 @@ describe('{{prev_post}} helper', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('shows \'else\' template', function (done) {
|
||||
it('shows \'else\' template', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'prev_post', data: locals, fn: fn, inverse: inverse};
|
||||
|
||||
prev_post
|
||||
await prev_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
@ -171,14 +160,10 @@ describe('{{prev_post}} helper', function () {
|
||||
published_at: new Date(0),
|
||||
url: '/current/',
|
||||
page: true
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.true();
|
||||
}, optionsData);
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.true();
|
||||
});
|
||||
});
|
||||
|
||||
@ -200,12 +185,12 @@ describe('{{prev_post}} helper', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('shows \'else\' template', function (done) {
|
||||
it('shows \'else\' template', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'prev_post', data: locals, fn: fn, inverse: inverse};
|
||||
|
||||
prev_post
|
||||
await prev_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'draft',
|
||||
@ -214,14 +199,10 @@ describe('{{prev_post}} helper', function () {
|
||||
slug: 'current',
|
||||
created_at: new Date(0),
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.true();
|
||||
}, optionsData);
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.true();
|
||||
});
|
||||
});
|
||||
|
||||
@ -236,12 +217,12 @@ describe('{{prev_post}} helper', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('shows \'if\' template with prev post data with primary_tag set', function (done) {
|
||||
it('shows \'if\' template with prev post data with primary_tag set', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'prev_post', data: locals, fn: fn, inverse: inverse, hash: {in: 'primary_tag'}};
|
||||
|
||||
prev_post
|
||||
await prev_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
@ -251,29 +232,25 @@ describe('{{prev_post}} helper', function () {
|
||||
published_at: new Date(0),
|
||||
primary_tag: {slug: 'test'},
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
}, optionsData);
|
||||
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
browsePostsStub.firstCall.args[0].filter.should.match(/\+primary_tag:test/);
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
browsePostsStub.firstCall.args[0].filter.should.match(/\+primary_tag:test/);
|
||||
});
|
||||
|
||||
it('shows \'if\' template with prev post data with primary_author set', function (done) {
|
||||
it('shows \'if\' template with prev post data with primary_author set', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'prev_post', data: locals, fn: fn, inverse: inverse, hash: {in: 'primary_author'}};
|
||||
|
||||
prev_post
|
||||
await prev_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
@ -283,29 +260,25 @@ describe('{{prev_post}} helper', function () {
|
||||
published_at: new Date(0),
|
||||
primary_author: {slug: 'hans'},
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
}, optionsData);
|
||||
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
browsePostsStub.firstCall.args[0].filter.should.match(/\+primary_author:hans/);
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
browsePostsStub.firstCall.args[0].filter.should.match(/\+primary_author:hans/);
|
||||
});
|
||||
|
||||
it('shows \'if\' template with prev post data with author set', function (done) {
|
||||
it('shows \'if\' template with prev post data with author set', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'prev_post', data: locals, fn: fn, inverse: inverse, hash: {in: 'author'}};
|
||||
|
||||
prev_post
|
||||
await prev_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
@ -315,29 +288,25 @@ describe('{{prev_post}} helper', function () {
|
||||
published_at: new Date(0),
|
||||
author: {slug: 'author-name'},
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
}, optionsData);
|
||||
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
browsePostsStub.firstCall.args[0].filter.should.match(/\+author:author-name/);
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
browsePostsStub.firstCall.args[0].filter.should.match(/\+author:author-name/);
|
||||
});
|
||||
|
||||
it('shows \'if\' template with prev post data & ignores in author if author isnt present', function (done) {
|
||||
it('shows \'if\' template with prev post data & ignores in author if author isnt present', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'prev_post', data: locals, fn: fn, inverse: inverse, hash: {in: 'author'}};
|
||||
|
||||
prev_post
|
||||
await prev_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
@ -346,29 +315,25 @@ describe('{{prev_post}} helper', function () {
|
||||
slug: 'current',
|
||||
published_at: new Date(0),
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
}, optionsData);
|
||||
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
browsePostsStub.firstCall.args[0].filter.should.not.match(/\+author:/);
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
browsePostsStub.firstCall.args[0].filter.should.not.match(/\+author:/);
|
||||
});
|
||||
|
||||
it('shows \'if\' template with prev post data & ignores unknown in value', function (done) {
|
||||
it('shows \'if\' template with prev post data & ignores unknown in value', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'prev_post', data: locals, fn: fn, inverse: inverse, hash: {in: 'magic'}};
|
||||
|
||||
prev_post
|
||||
await prev_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
@ -378,21 +343,17 @@ describe('{{prev_post}} helper', function () {
|
||||
published_at: new Date(0),
|
||||
author: {slug: 'author-name'},
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
}, optionsData);
|
||||
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
browsePostsStub.firstCall.args[0].filter.should.not.match(/\+magic/);
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
browsePostsStub.firstCall.args[0].filter.should.not.match(/\+magic/);
|
||||
});
|
||||
});
|
||||
|
||||
@ -403,12 +364,12 @@ describe('{{prev_post}} helper', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle error from the API', function (done) {
|
||||
it('should handle error from the API', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'prev_post', data: locals, fn: fn, inverse: inverse};
|
||||
|
||||
prev_post
|
||||
await prev_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
@ -417,37 +378,80 @@ describe('{{prev_post}} helper', function () {
|
||||
slug: 'current',
|
||||
published_at: new Date(0),
|
||||
url: '/current/'
|
||||
}, optionsData)
|
||||
.then(function () {
|
||||
fn.called.should.be.false();
|
||||
inverse.calledOnce.should.be.true();
|
||||
}, optionsData);
|
||||
|
||||
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/);
|
||||
fn.called.should.be.false();
|
||||
inverse.calledOnce.should.be.true();
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
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/);
|
||||
});
|
||||
|
||||
it('should show warning for call without any options', function (done) {
|
||||
it('should show warning for call without any options', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'prev_post', data: {root: {}}};
|
||||
|
||||
prev_post
|
||||
await prev_post
|
||||
.call(
|
||||
{},
|
||||
optionsData
|
||||
)
|
||||
.then(function () {
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.false();
|
||||
);
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
fn.called.should.be.false();
|
||||
inverse.called.should.be.false();
|
||||
});
|
||||
});
|
||||
|
||||
describe('auth', function () {
|
||||
let member;
|
||||
|
||||
beforeEach(function () {
|
||||
member = {uuid: 'test'};
|
||||
browsePostsStub = sinon.stub().callsFake(function (options) {
|
||||
return Promise.resolve({
|
||||
posts: [{slug: '/next/', title: 'post 3'}]
|
||||
});
|
||||
});
|
||||
locals = {
|
||||
root: {
|
||||
_locals: {
|
||||
apiVersion: apiVersion
|
||||
},
|
||||
context: ['post']
|
||||
},
|
||||
member
|
||||
};
|
||||
});
|
||||
|
||||
it('should pass the member context', async function () {
|
||||
const fn = sinon.spy();
|
||||
const inverse = sinon.spy();
|
||||
const optionsData = {name: 'prev_post', data: locals, fn: fn, inverse: inverse};
|
||||
|
||||
await prev_post
|
||||
.call({
|
||||
html: 'content',
|
||||
status: 'published',
|
||||
mobiledoc: markdownToMobiledoc('ff'),
|
||||
title: 'post2',
|
||||
slug: 'current',
|
||||
published_at: new Date(0),
|
||||
url: '/current/'
|
||||
}, optionsData);
|
||||
|
||||
fn.calledOnce.should.be.true();
|
||||
inverse.calledOnce.should.be.false();
|
||||
|
||||
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');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].include.should.eql('author,authors,tags,tiers');
|
||||
|
||||
// Check context passed
|
||||
browsePostsStub.firstCall.args[0].context.member.should.eql(member);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user