Merge pull request #6145 from ErisDS/view-refactor

Unify code for picking a template to render with
This commit is contained in:
Sebastian Gierlinger 2015-12-02 10:02:31 +01:00
commit bc83dbce09
13 changed files with 408 additions and 286 deletions

View File

@ -3,9 +3,9 @@ var config = require('../../config'),
defaults = {
index: {
name: 'home',
name: 'index',
route: '/',
firstPageTemplate: 'home'
frontPageTemplate: 'home'
},
tag: {
name: 'tag',

View File

@ -82,10 +82,9 @@ function processQuery(query, slugParam) {
* Does a first round of formatting on the response, and returns
*
* @param {Object} channelOptions
* @param {String} slugParam
* @returns {Promise} response
*/
function fetchData(channelOptions, slugParam) {
function fetchData(channelOptions) {
// Temporary workaround to make RSS work, moving towards dynamic channels will provide opportunities to
// improve this, I hope :)
function handlePostsPerPage(channelOptions) {
@ -102,10 +101,10 @@ function fetchData(channelOptions, slugParam) {
// All channels must have a posts query, use the default if not provided
postQuery = _.defaultsDeep({}, pageOptions, defaultPostQuery);
props.posts = processQuery(postQuery, slugParam);
props.posts = processQuery(postQuery, channelOptions.slugParam);
_.each(channelOptions.data, function (query, name) {
props[name] = processQuery(query, slugParam);
props[name] = processQuery(query, channelOptions.slugParam);
});
return Promise.props(props).then(function formatResponse(results) {

View File

@ -12,7 +12,7 @@ var _ = require('lodash'),
errors = require('../../errors'),
filters = require('../../filters'),
Promise = require('bluebird'),
template = require('../../helpers/template'),
templates = require('./templates'),
routeMatch = require('path-match')(),
safeString = require('../../utils/index').safeString,
handleError = require('./error'),
@ -21,7 +21,6 @@ var _ = require('lodash'),
channelConfig = require('./channel-config'),
setResponseContext = require('./context'),
setRequestIsSecure = require('./secure'),
getActiveThemePaths = require('./theme-paths'),
frontendControllers,
staticPostPermalink = routeMatch('/:slug/:edit?');
@ -34,8 +33,7 @@ var _ = require('lodash'),
*/
function renderPost(req, res) {
return function renderPost(post) {
var paths = getActiveThemePaths(req),
view = template.getThemeViewForPost(paths, post),
var view = templates.single(req.app.get('activeTheme'), post),
response = formatResponse.single(post);
setResponseContext(req, res, response);
@ -53,6 +51,7 @@ function renderChannel(channelOpts) {
channelOpts.postOptions = channelOpts.postOptions || {};
// Set page on postOptions for the query made later
channelOpts.postOptions.page = pageParam;
channelOpts.slugParam = slugParam;
// @TODO this should really use the url building code in config.url
function createUrl(page) {
@ -75,7 +74,7 @@ function renderChannel(channelOpts) {
}
// Call fetchData to get everything we need from the API
return fetchData(channelOpts, slugParam).then(function handleResult(result) {
return fetchData(channelOpts).then(function handleResult(result) {
// If page is greater than number of pages we have, redirect to last page
if (pageParam > result.meta.pagination.pages) {
return res.redirect(createUrl(result.meta.pagination.pages));
@ -90,17 +89,7 @@ function renderChannel(channelOpts) {
// @TODO: properly design these filters
filters.doFilter('prePostsRender', result.posts, res.locals).then(function then(posts) {
var paths = getActiveThemePaths(req),
view = 'index';
// Calculate which template to use to render the data
if (channelOpts.firstPageTemplate && paths.hasOwnProperty(channelOpts.firstPageTemplate + '.hbs')) {
view = (pageParam > 1) ? 'index' : channelOpts.firstPageTemplate;
} else if (channelOpts.slugTemplate) {
view = template.getThemeViewForChannel(paths, channelOpts.name, slugParam);
} else if (paths.hasOwnProperty(channelOpts.name + '.hbs')) {
view = channelOpts.name;
}
var view = templates.channel(req.app.get('activeTheme'), channelOpts);
// Do final data formatting and then render
result.posts = posts;
@ -248,7 +237,7 @@ frontendControllers = {
},
private: function private(req, res) {
var defaultPage = path.resolve(config.paths.adminViews, 'private.hbs'),
paths = getActiveThemePaths(req),
paths = templates.getActiveThemePaths(req.app.get('activeTheme')),
data = {};
if (res.error) {

View File

@ -0,0 +1,100 @@
// # Templates
//
// Figure out which template should be used to render a request
// based on the templates which are allowed, and what is available in the theme
var _ = require('lodash'),
config = require('../../config');
function getActiveThemePaths(activeTheme) {
return config.paths.availableThemes[activeTheme];
}
/**
* ## Get Channel Template Hierarchy
*
* Fetch the ordered list of templates that can be used to render this request.
* 'index' is the default / fallback
* For channels with slugs: [:channelName-:slug, :channelName, index]
* For channels without slugs: [:channelName, index]
* Channels can also have a front page template which is used if this is the first page of the channel, e.g. 'home.hbs'
*
* @param {Object} channelOpts
* @returns {String[]}
*/
function getChannelTemplateHierarchy(channelOpts) {
var templateList = ['index'];
if (channelOpts.name && channelOpts.name !== 'index') {
templateList.unshift(channelOpts.name);
if (channelOpts.slugTemplate && channelOpts.slugParam) {
templateList.unshift(channelOpts.name + '-' + channelOpts.slugParam);
}
}
if (channelOpts.frontPageTemplate && channelOpts.postOptions.page === 1) {
templateList.unshift(channelOpts.frontPageTemplate);
}
return templateList;
}
/**
* ## Get Single Template Hierarchy
*
* Fetch the ordered list of templates that can be used to render this request.
* 'post' is the default / fallback
* For posts: [post-:slug, post]
* For pages: [page-:slug, page, post]
*
* @param {Object} single
* @returns {String[]}
*/
function getSingleTemplateHierarchy(single) {
var templateList = ['post'],
type = 'post';
if (single.page) {
templateList.unshift('page');
type = 'page';
}
templateList.unshift(type + '-' + single.slug);
return templateList;
}
/**
* ## Pick Template
*
* Taking the ordered list of allowed templates for this request
* Cycle through and find the first one which has a match in the theme
*
* @param {Object} themePaths
* @param {Array} templateList
*/
function pickTemplate(themePaths, templateList) {
var template = _.find(templateList, function (template) {
return themePaths.hasOwnProperty(template + '.hbs');
});
if (!template) {
template = templateList[templateList.length - 1];
}
return template;
}
function getTemplateForSingle(activeTheme, single) {
return pickTemplate(getActiveThemePaths(activeTheme), getSingleTemplateHierarchy(single));
}
function getTemplateForChannel(activeTheme, channelOpts) {
return pickTemplate(getActiveThemePaths(activeTheme), getChannelTemplateHierarchy(channelOpts));
}
module.exports = {
getActiveThemePaths: getActiveThemePaths,
channel: getTemplateForChannel,
single: getTemplateForSingle
};

View File

@ -1,14 +0,0 @@
var config = require('../../config');
/**
* Returns the paths object of the active theme via way of a promise.
* @return {Promise} The promise resolves with the value of the paths.
*/
function getActiveThemePaths(req) {
var activeTheme = req.app.get('activeTheme'),
paths = config.paths.availableThemes[activeTheme];
return paths;
}
module.exports = getActiveThemePaths;

View File

@ -199,12 +199,14 @@ generate = function generate(req, res, next) {
// Set page on postOptions for the query made later
req.channelConfig.postOptions.page = pageParam;
req.channelConfig.slugParam = slugParam;
// No negative pages, or page 1
if (isNaN(pageParam) || pageParam < 1 || (req.params.page !== undefined && pageParam === 1)) {
return res.redirect(baseUrl);
}
return getData(req.channelConfig, slugParam).then(function then(data) {
return getData(req.channelConfig).then(function then(data) {
var maxPage = data.results.meta.pagination.pages;
// If page is greater than number of pages we have, redirect to last page

View File

@ -8,10 +8,9 @@
var hbs = require('express-hbs'),
_ = require('lodash'),
api = require('../api'),
config = require('../config'),
filters = require('../filters'),
template = require('./template'),
// @TODO Fix this
template = require('../controllers/frontend/templates'),
body_class;
body_class = function (options) {
@ -19,7 +18,9 @@ body_class = function (options) {
context = options.data.root.context,
post = this.post,
tags = this.post && this.post.tags ? this.post.tags : this.tags || [],
page = this.post && this.post.page ? this.post.page : this.page || false;
page = this.post && this.post.page ? this.post.page : this.page || false,
activeTheme = options.data.root.settings.activeTheme,
view;
if (post) {
// To be removed from pages by #2597 when we're ready to deprecate this
@ -53,26 +54,20 @@ body_class = function (options) {
classes.push('archive-template');
}
return api.settings.read({context: {internal: true}, key: 'activeTheme'}).then(function (response) {
var activeTheme = response.settings[0],
paths = config.paths.availableThemes[activeTheme.value],
view;
if (post && page) {
view = template.single(activeTheme, post).split('-');
if (post && page) {
view = template.getThemeViewForPost(paths, post).split('-');
if (view[0] === 'page' && view.length > 1) {
classes.push(view.join('-'));
// To be removed by #2597 when we're ready to deprecate this
view.splice(1, 0, 'template');
classes.push(view.join('-'));
}
if (view[0] === 'page' && view.length > 1) {
classes.push(view.join('-'));
// To be removed by #2597 when we're ready to deprecate this
view.splice(1, 0, 'template');
classes.push(view.join('-'));
}
}
return filters.doFilter('body_class', classes).then(function (classes) {
var classString = _.reduce(classes, function (memo, item) { return memo + ' ' + item; }, '');
return new hbs.handlebars.SafeString(classString.trim());
});
return filters.doFilter('body_class', classes).then(function (classes) {
var classString = _.reduce(classes, function (memo, item) { return memo + ' ' + item; }, '');
return new hbs.handlebars.SafeString(classString.trim());
});
};

View File

@ -22,47 +22,4 @@ templates.execute = function (name, context, options) {
return new hbs.handlebars.SafeString(partial(context, options));
};
// Given a theme object and a post object this will return
// which theme template page should be used.
// If given a post object that is a regular post
// it will return 'post'.
// If given a static post object it will return 'page'.
// If given a static post object and a custom page template
// exits it will return that page.
templates.getThemeViewForPost = function (themePaths, post) {
var customPageView = 'page-' + post.slug,
view = 'post';
if (post.page) {
if (themePaths.hasOwnProperty(customPageView + '.hbs')) {
view = customPageView;
} else if (themePaths.hasOwnProperty('page.hbs')) {
view = 'page';
}
}
return view;
};
// Given a theme object and a slug this will return
// which theme template page should be used.
// If no default or custom tag template exists then 'index'
// will be returned
// If no custom template exists but a default does then
// the default will be returned
// If given a slug and a custom template
// exits it will return that view.
templates.getThemeViewForChannel = function (themePaths, channelName, slug) {
var customChannelView = channelName + '-' + slug,
view = channelName;
if (themePaths.hasOwnProperty(customChannelView + '.hbs')) {
view = customChannelView;
} else if (!themePaths.hasOwnProperty(channelName + '.hbs')) {
view = 'index';
}
return view;
};
module.exports = templates;

View File

@ -133,6 +133,7 @@ describe('fetchData', function () {
postOptions: {
filter: 'tags:%s'
},
slugParam: 'testing',
data: {
tag: {
type: 'read',
@ -140,10 +141,9 @@ describe('fetchData', function () {
options: {slug: '%s'}
}
}
},
slugParam = 'testing';
};
fetchData(channelOpts, slugParam).then(function (result) {
fetchData(channelOpts).then(function (result) {
should.exist(result);
result.should.be.an.Object.with.properties('posts', 'meta', 'data');
result.data.should.be.an.Object.with.properties('tag');

View File

@ -987,6 +987,8 @@ describe('Frontend Controller', function () {
}]
}));
config.set({paths: {availableThemes: {casper: casper}}});
var date = moment(mockPosts[1].posts[0].published_at).format('YYYY');
mockPosts[1].posts[0].url = '/' + date + '/' + mockPosts[1].posts[0].slug + '/';
});
@ -1375,6 +1377,8 @@ describe('Frontend Controller', function () {
render: sinon.spy(),
redirect: sinon.spy()
};
config.set({paths: {availableThemes: {casper: {}}}});
});
it('should render draft post', function (done) {

View File

@ -0,0 +1,176 @@
/*globals describe, it, afterEach, beforeEach*/
/*jshint expr:true*/
var should = require('should'),
rewire = require('rewire'),
_ = require('lodash'),
// Stuff we are testing
templates = rewire('../../../../server/controllers/frontend/templates'),
config = require('../../../../server/config'),
origConfig = _.cloneDeep(config);
// To stop jshint complaining
should.equal(true, true);
describe('templates', function () {
afterEach(function () {
config.set(origConfig);
});
describe('utils', function () {
var channelTemplateList = templates.__get__('getChannelTemplateHierarchy');
it('should return just index for empty channelOpts', function () {
channelTemplateList({}).should.eql(['index']);
});
it('should return just index if channel name is index', function () {
channelTemplateList({name: 'index'}).should.eql(['index']);
});
it('should return just index if channel name is index even if slug is set', function () {
channelTemplateList({name: 'index', slugTemplate: true, slugParam: 'test'}).should.eql(['index']);
});
it('should return channel, index if channel has name', function () {
channelTemplateList({name: 'tag'}).should.eql(['tag', 'index']);
});
it('should return channel-slug, channel, index if channel has name & slug + slugTemplate set', function () {
channelTemplateList({name: 'tag', slugTemplate: true, slugParam: 'test'}).should.eql(['tag-test', 'tag', 'index']);
});
it('should return front, channel-slug, channel, index if name, slugParam+slugTemplate & frontPageTemplate+pageParam=1 is set', function () {
channelTemplateList({
name: 'tag', slugTemplate: true, slugParam: 'test', frontPageTemplate: 'front-tag', postOptions: {page: 1}
}).should.eql(['front-tag', 'tag-test', 'tag', 'index']);
});
it('should return home, index for index channel if front is set and pageParam = 1', function () {
channelTemplateList({name: 'index', frontPageTemplate: 'home', postOptions: {page: 1}}).should.eql(['home', 'index']);
});
});
describe('single', function () {
describe('with many templates', function () {
beforeEach(function () {
config.set({
paths: {
availableThemes: {
casper: {
assets: null,
'default.hbs': '/content/themes/casper/default.hbs',
'index.hbs': '/content/themes/casper/index.hbs',
'page.hbs': '/content/themes/casper/page.hbs',
'page-about.hbs': '/content/themes/casper/page-about.hbs',
'post.hbs': '/content/themes/casper/post.hbs',
'post-welcome-to-ghost.hbs': '/content/themes/casper/post-welcome-to-ghost.hbs'
}
}
}
});
});
it('will return correct template for a post WITHOUT custom template', function () {
var view = templates.single('casper', {
page: 0,
slug: 'test-post'
});
view.should.exist;
view.should.eql('post');
});
it('will return correct template for a post WITH custom template', function () {
var view = templates.single('casper', {
page: 0,
slug: 'welcome-to-ghost'
});
view.should.exist;
view.should.eql('post-welcome-to-ghost', 'post');
});
it('will return correct template for a page WITHOUT custom template', function () {
var view = templates.single('casper', {
page: 1,
slug: 'contact'
});
view.should.exist;
view.should.eql('page');
});
it('will return correct template for a page WITH custom template', function () {
var view = templates.single('casper', {
page: 1,
slug: 'about'
});
view.should.exist;
view.should.eql('page-about');
});
});
it('will fall back to post even if no index.hbs', function () {
config.set({paths: {availableThemes: {casper: {
assets: null,
'default.hbs': '/content/themes/casper/default.hbs'
}}}});
var view = templates.single('casper', {page: 1});
view.should.exist;
view.should.eql('post');
});
});
describe('channel', function () {
describe('without tag templates', function () {
beforeEach(function () {
config.set({paths: {availableThemes: {casper: {
assets: null,
'default.hbs': '/content/themes/casper/default.hbs',
'index.hbs': '/content/themes/casper/index.hbs'
}}}});
});
it('will return correct view for a tag', function () {
var view = templates.channel('casper', {name: 'tag', slugParam: 'development', slugTemplate: true});
view.should.exist;
view.should.eql('index');
});
});
describe('with tag templates', function () {
beforeEach(function () {
config.set({paths: {availableThemes: {casper: {
assets: null,
'default.hbs': '/content/themes/casper/default.hbs',
'index.hbs': '/content/themes/casper/index.hbs',
'tag.hbs': '/content/themes/casper/tag.hbs',
'tag-design.hbs': '/content/themes/casper/tag-about.hbs'
}}}});
});
it('will return correct view for a tag', function () {
var view = templates.channel('casper', {name: 'tag', slugParam: 'design', slugTemplate: true});
view.should.exist;
view.should.eql('tag-design');
});
it('will return correct view for a tag', function () {
var view = templates.channel('casper', {name: 'tag', slugParam: 'development', slugTemplate: true});
view.should.exist;
view.should.eql('tag');
});
});
it('will fall back to index even if no index.hbs', function () {
config.set({paths: {availableThemes: {casper: {
assets: null,
'default.hbs': '/content/themes/casper/default.hbs'
}}}});
var view = templates.channel('casper', {name: 'tag', slugParam: 'development', slugTemplate: true});
view.should.exist;
view.should.eql('index');
});
});
});

View File

@ -1,26 +1,16 @@
/*globals describe, before, after, it*/
/*globals describe, before, beforeEach, after, it*/
/*jshint expr:true*/
var should = require('should'),
sinon = require('sinon'),
Promise = require('bluebird'),
hbs = require('express-hbs'),
utils = require('./utils'),
// Stuff we are testing
handlebars = hbs.handlebars,
helpers = require('../../../server/helpers'),
api = require('../../../server/api');
helpers = require('../../../server/helpers');
describe('{{body_class}} helper', function () {
var sandbox;
var options = {};
before(function () {
sandbox = sinon.sandbox.create();
sandbox.stub(api.settings, 'read', function () {
return Promise.resolve({
settings: [{value: 'casper'}]
});
});
utils.loadHelpers();
utils.overrideConfig({paths: {
availableThemes: {
@ -36,9 +26,19 @@ describe('{{body_class}} helper', function () {
}});
});
beforeEach(function () {
options = {
data: {
root: {
context: [],
settings: {activeTheme: 'casper'}
}
}
};
});
after(function () {
utils.restoreConfig();
sandbox.restore();
});
it('has loaded body_class helper', function () {
@ -46,7 +46,9 @@ describe('{{body_class}} helper', function () {
});
it('can render class string', function (done) {
helpers.body_class.call({}, {data: {root: {context: ['home']}}}).then(function (rendered) {
options.data.root.context = ['home'];
helpers.body_class.call({}, options).then(function (rendered) {
should.exist(rendered);
rendered.string.should.equal('home-template');
@ -55,111 +57,90 @@ describe('{{body_class}} helper', function () {
}).catch(done);
});
it('can render class string for context', function (done) {
Promise.all([
// Standard home page
helpers.body_class.call(
{relativeUrl: '/'},
{data: {root: {context: ['home', 'index']}}}
),
// A post
helpers.body_class.call(
{relativeUrl: '/a-post-title', post: {}},
{data: {root: {context: ['post']}}}
),
// Paginated index
helpers.body_class.call(
{relativeUrl: '/page/4'},
{data: {root: {context: ['index', 'paged']}}}
),
// Tag page
helpers.body_class.call(
{relativeUrl: '/tag/foo', tag: {slug: 'foo'}},
{data: {root: {context: ['tag']}}}
),
// Paginated tag page
helpers.body_class.call(
{relativeUrl: '/tag/foo/page/2', tag: {slug: 'foo'}},
{data: {root: {context: ['tag', 'paged']}}}
),
// Author page
helpers.body_class.call(
{relativeUrl: '/author/bar', author: {slug: 'bar'}},
{data: {root: {context: ['author']}}}
),
// Paginated author page
helpers.body_class.call(
{relativeUrl: '/author/bar/page/2', author: {slug: 'bar'}},
{data: {root: {context: ['author', 'paged']}}}
),
// Private route for password protection
helpers.body_class.call(
{relativeUrl: '/private/'},
{data: {root: {context: ['private']}}}
),
// Post with tags
helpers.body_class.call(
{relativeUrl: '/my-awesome-post/', post: {tags: [{slug: 'foo'}, {slug: 'bar'}]}},
{data: {root: {context: ['post']}}}
)
]).then(function (rendered) {
rendered.length.should.equal(9);
describe('can render class string for context', function () {
function callBodyClassWithContext(context, self) {
options.data.root.context = context;
return helpers.body_class.call(
self,
options
);
}
should.exist(rendered[0]);
should.exist(rendered[1]);
should.exist(rendered[2]);
should.exist(rendered[3]);
should.exist(rendered[4]);
should.exist(rendered[5]);
should.exist(rendered[6]);
should.exist(rendered[7]);
should.exist(rendered[8]);
it('Standard home page', function (done) {
callBodyClassWithContext(['home', 'index'], {relativeUrl: '/'}).then(function (rendered) {
rendered.string.should.equal('home-template');
done();
}).catch(done);
});
rendered[0].string.should.equal('home-template');
rendered[1].string.should.equal('post-template');
rendered[2].string.should.equal('paged archive-template');
rendered[3].string.should.equal('tag-template tag-foo');
rendered[4].string.should.equal('tag-template tag-foo paged archive-template');
rendered[5].string.should.equal('author-template author-bar');
rendered[6].string.should.equal('author-template author-bar paged archive-template');
rendered[7].string.should.equal('private-template');
rendered[8].string.should.equal('post-template tag-foo tag-bar');
it('a post', function (done) {
callBodyClassWithContext(['post'], {relativeUrl: '/a-post-title', post: {}}).then(function (rendered) {
rendered.string.should.equal('post-template');
done();
}).catch(done);
});
done();
}).catch(done);
});
it('paginated index', function (done) {
callBodyClassWithContext(['index', 'paged'], {relativeUrl: '/page/4'}).then(function (rendered) {
rendered.string.should.equal('paged archive-template');
done();
}).catch(done);
});
it('can render class for static page', function (done) {
helpers.body_class.call(
{
relativeUrl: '/about',
post: {
page: true
}
},
{data: {root: {context: ['page']}}}
).then(function (rendered) {
should.exist(rendered);
rendered.string.should.equal('post-template page-template page');
it('tag page', function (done) {
callBodyClassWithContext(['tag'], {relativeUrl: '/tag/foo', tag: {slug: 'foo'}}).then(function (rendered) {
rendered.string.should.equal('tag-template tag-foo');
done();
}).catch(done);
});
done();
}).catch(done);
});
it('paginated tag page', function (done) {
callBodyClassWithContext(['tag', 'paged'], {relativeUrl: '/tag/foo/page/2', tag: {slug: 'foo'}}).then(function (rendered) {
rendered.string.should.equal('tag-template tag-foo paged archive-template');
done();
}).catch(done);
});
it('can render class for static page with custom template', function (done) {
helpers.body_class.call(
{
relativeUrl: '/about',
post: {
page: true,
slug: 'about'
}
},
{data: {root: {context: ['page']}}}).then(function (rendered) {
should.exist(rendered);
rendered.string.should.equal('post-template page-template page page-about page-template-about');
it('author page', function (done) {
callBodyClassWithContext(['author'], {relativeUrl: '/author/bar', author: {slug: 'bar'}}).then(function (rendered) {
rendered.string.should.equal('author-template author-bar');
done();
}).catch(done);
});
done();
}).catch(done);
it('paginated author page', function (done) {
callBodyClassWithContext(['author', 'paged'], {relativeUrl: '/author/bar/page/2', author: {slug: 'bar'}}).then(function (rendered) {
rendered.string.should.equal('author-template author-bar paged archive-template');
done();
}).catch(done);
});
it('private route for password protection', function (done) {
callBodyClassWithContext(['private'], {relativeUrl: '/private/'}).then(function (rendered) {
rendered.string.should.equal('private-template');
done();
}).catch(done);
});
it('post with tags', function (done) {
callBodyClassWithContext(['post'], {relativeUrl: '/my-awesome-post/', post: {tags: [{slug: 'foo'}, {slug: 'bar'}]}}).then(function (rendered) {
rendered.string.should.equal('post-template tag-foo tag-bar');
done();
}).catch(done);
});
it('a static page', function (done) {
callBodyClassWithContext(['page'], {relativeUrl: '/about', post: {page: true}}).then(function (rendered) {
rendered.string.should.equal('post-template page-template page');
done();
}).catch(done);
});
it('a static page with custom template', function (done) {
callBodyClassWithContext(['page'], {relativeUrl: '/about', post: {page: true, slug: 'about'}}).then(function (rendered) {
rendered.string.should.equal('post-template page-template page page-about page-template-about');
done();
}).catch(done);
});
});
});

View File

@ -15,71 +15,4 @@ describe('Helpers Template', function () {
should.exist(safeString);
safeString.should.have.property('string').and.equal('<h1>Hello world</h1>');
});
describe('getThemeViewForPost', function () {
var themePaths = {
assets: null,
'default.hbs': '/content/themes/casper/default.hbs',
'index.hbs': '/content/themes/casper/index.hbs',
'page.hbs': '/content/themes/casper/page.hbs',
'page-about.hbs': '/content/themes/casper/page-about.hbs',
'post.hbs': '/content/themes/casper/post.hbs'
},
posts = [{
page: 1,
slug: 'about'
}, {
page: 1,
slug: 'contact'
}, {
page: 0,
slug: 'test-post'
}];
it('will return correct view for a post', function () {
var view = template.getThemeViewForPost(themePaths, posts[0]);
view.should.exist;
view.should.eql('page-about');
view = template.getThemeViewForPost(themePaths, posts[1]);
view.should.exist;
view.should.eql('page');
view = template.getThemeViewForPost(themePaths, posts[2]);
view.should.exist;
view.should.eql('post');
});
});
describe('getThemeViewForChannel', function () {
var themePathsWithTagViews = {
assets: null,
'default.hbs': '/content/themes/casper/default.hbs',
'index.hbs': '/content/themes/casper/index.hbs',
'tag.hbs': '/content/themes/casper/tag.hbs',
'tag-design.hbs': '/content/themes/casper/tag-about.hbs'
},
themePaths = {
assets: null,
'default.hbs': '/content/themes/casper/default.hbs',
'index.hbs': '/content/themes/casper/index.hbs'
},
CHANNEL = 'tag',
CUSTOM_EXISTS = 'design',
DEFAULT = 'development';
it('will return correct view for a tag', function () {
var view = template.getThemeViewForChannel(themePathsWithTagViews, CHANNEL, CUSTOM_EXISTS);
view.should.exist;
view.should.eql('tag-design');
view = template.getThemeViewForChannel(themePathsWithTagViews, CHANNEL, DEFAULT);
view.should.exist;
view.should.eql('tag');
view = template.getThemeViewForChannel(themePaths, CHANNEL, DEFAULT);
view.should.exist;
view.should.eql('index');
});
});
});