Add tests for handlebars core helper functions

Closes #1842
-add unit tests for core helper functions
-fix up coreHelpers.e
-clean up coreHelpers.pagination
This commit is contained in:
Jason Williams 2014-05-21 21:43:54 +00:00
parent c7bbb9e789
commit 9d16e72bb0
2 changed files with 358 additions and 13 deletions

View File

@ -531,17 +531,18 @@ coreHelpers.meta_description = function (options) {
*/
coreHelpers.e = function (key, defaultString, options) {
var output;
when.all([
return when.all([
api.settings.read('defaultLang'),
api.settings.read('forceI18n')
]).then(function (values) {
if (values[0].settings.value === 'en' &&
if (values[0].settings[0] === 'en_US' &&
_.isEmpty(options.hash) &&
_.isEmpty(values[1].settings.value)) {
values[1].settings[0] !== 'true') {
output = defaultString;
} else {
output = polyglot().t(key, options.hash);
output = polyglot.t(key, options.hash);
}
return output;
});
};
@ -613,6 +614,7 @@ coreHelpers.foreach = function (context, options) {
if (i === 0) {
ret = inverse(this);
}
return ret;
};
@ -653,24 +655,24 @@ coreHelpers.has = function (options) {
coreHelpers.pagination = function (options) {
/*jshint unused:false*/
if (!_.isObject(this.pagination) || _.isFunction(this.pagination)) {
errors.logAndThrowError('pagination data is not an object or is a function');
return;
return errors.logAndThrowError('pagination data is not an object or is a function');
}
if (_.isUndefined(this.pagination.page) || _.isUndefined(this.pagination.pages) ||
_.isUndefined(this.pagination.total) || _.isUndefined(this.pagination.limit)) {
errors.logAndThrowError('All values must be defined for page, pages, limit and total');
return;
return errors.logAndThrowError('All values must be defined for page, pages, limit and total');
}
if ((!_.isNull(this.pagination.next) && !_.isNumber(this.pagination.next)) ||
(!_.isNull(this.pagination.prev) && !_.isNumber(this.pagination.prev))) {
errors.logAndThrowError('Invalid value, Next/Prev must be a number');
return;
return errors.logAndThrowError('Invalid value, Next/Prev must be a number');
}
if (!_.isNumber(this.pagination.page) || !_.isNumber(this.pagination.pages) ||
!_.isNumber(this.pagination.total) || !_.isNumber(this.pagination.limit)) {
errors.logAndThrowError('Invalid value, check page, pages, limit and total are numbers');
return;
return errors.logAndThrowError('Invalid value, check page, pages, limit and total are numbers');
}
var context = _.merge({}, this.pagination);
if (this.tag !== undefined) {

View File

@ -6,6 +6,8 @@ var testUtils = require('../utils'),
_ = require('lodash'),
path = require('path'),
rewire = require('rewire'),
moment = require('moment'),
Polyglot = require('node-polyglot'),
api = require('../../server/api'),
hbs = require('express-hbs'),
packageInfo = require('../../../package'),
@ -683,8 +685,19 @@ describe('Core Helpers', function () {
should.exist(handlebars.helpers.pagination);
});
it('should throw if pagination data is incorrect', function () {
var runHelper = function (data) {
return function () {
helpers.pagination.call(data);
}
};
runHelper('not an object').should.throwError('pagination data is not an object or is a function');
runHelper(function () {}).should.throwError('pagination data is not an object or is a function');
});
it('can render single page with no pagination necessary', function () {
var rendered = helpers.pagination.call({pagination: {page: 1, prev: null, next: null, limit: 15, total: 8, pages: 1}});
var rendered = helpers.pagination.call({pagination: {page: 1, prev: null, next: null, limit: 15, total: 8, pages: 1}, tag: {slug: 'slug'}});
should.exist(rendered);
// strip out carriage returns and compare.
rendered.string.should.match(paginationRegex);
@ -1030,6 +1043,270 @@ describe('Core Helpers', function () {
});
describe('date helper', function () {
it('is loaded', function () {
should.exist(handlebars.helpers.date);
});
// TODO: When timezone support is added these tests should be updated
// to test the output of the helper against static strings instead
// of calling moment(). Without timezone support the output of this
// helper may differ depending on what timezone the tests are run in.
it('creates properly formatted date strings', function () {
var testDates = [
'2013-12-31T11:28:58.593Z',
'2014-01-01T01:28:58.593Z',
'2014-02-20T01:28:58.593Z',
'2014-03-01T01:28:58.593Z'
],
format = 'MMM Do, YYYY',
context = {
hash: {
format: format
}
};
testDates.forEach(function (d) {
var rendered = helpers.date.call({ published_at: d }, context);
should.exist(rendered);
rendered.should.equal(moment(d).format(format));
});
});
it('creates properly formatted time ago date strings', function () {
var testDates = [
'2013-12-31T23:58:58.593Z',
'2014-01-01T00:28:58.593Z',
'2014-11-20T01:28:58.593Z',
'2014-03-01T01:28:58.593Z'
],
context = {
hash: {
timeago: true
}
};
testDates.forEach(function (d) {
var rendered = helpers.date.call({ published_at: d }, context);
should.exist(rendered);
rendered.should.equal(moment(d).fromNow());
});
});
});
describe('e helper', function () {
it('is loaded', function () {
should.exist(handlebars.helpers.e);
});
it('should return the correct default string', function (done) {
apiStub.restore();
apiStub = sandbox.stub(api.settings, 'read', function () {
return when({ settings: ['en_US'] });
});
helpers.e('testKey', 'default', { hash: {} }).then(function (result) {
result.should.equal('default');
done();
}).catch(done);
});
it('should return the correct string', function (done) {
apiStub.restore();
apiStub = sandbox.stub(api.settings, 'read', function () {
return when({ settings: ['fr'] });
});
var polyglot = new Polyglot();
polyglot.extend({ testKey: 'test value' });
helpers.__set__('polyglot', polyglot);
helpers.e('testKey', 'default', { hash: {} }).then(function (result) {
result.should.equal('test value');
done();
}).catch(done);
});
});
describe('foreach helper', function () {
// passed into the foreach helper. takes the input string along with the metadata about
// the current row and builds a csv output string that can be used to check the results.
function fn(input, data) {
data = data.data;
// if there was no private data passed into the helper, no metadata
// was created, so just return the input
if (!data) {
return input + '\n';
}
return input + ',' + data.first + ',' + data.rowEnd + ',' + data.rowStart + ',' +
data.last + ',' + data.even + ',' + data.odd + '\n';
}
function inverse(input) {
return input;
}
it('is loaded', function () {
should.exist(handlebars.helpers.foreach);
});
it('should return the correct result when no private data is supplied', function () {
var options = {},
context = [],
_this = {},
rendered;
options.fn = fn;
options.inverse = inverse;
options.hash = {
columns: 0
};
// test with context as an array
context = 'hello world this is ghost'.split(' ');
rendered = helpers.foreach.call(_this, context, options);
rendered.should.equal('hello\n\world\nthis\nis\nghost\n');
// test with context as an object
context = {
one: 'hello',
two: 'world',
three: 'this',
four: 'is',
five: 'ghost'
};
rendered = helpers.foreach.call(_this, context, options);
rendered.should.equal('hello\n\world\nthis\nis\nghost\n');
});
it('should return the correct result when private data is supplied', function () {
var options = {},
context = [],
_this = {},
rendered,
result;
options.fn = fn;
options.inverse = inverse;
options.hash = {
columns: 0
};
options.data = {};
context = 'hello world this is ghost'.split(' ');
rendered = helpers.foreach.call(_this, context, options);
result = rendered.split('\n');
result[0].should.equal('hello,true,false,false,false,false,true');
result[1].should.equal('world,false,false,false,false,true,false');
result[2].should.equal('this,false,false,false,false,false,true');
result[3].should.equal('is,false,false,false,false,true,false');
result[4].should.equal('ghost,false,false,false,true,false,true');
});
it('should return the correct result when private data is supplied and there are multiple columns', function () {
var options = {},
context = [],
_this = {},
rendered,
result;
options.fn = fn;
options.inverse = inverse;
options.hash = {
columns: 2
};
options.data = {};
// test with context as an array
context = 'hello world this is ghost'.split(' ');
rendered = helpers.foreach.call(_this, context, options);
result = rendered.split('\n');
result[0].should.equal('hello,true,false,true,false,false,true');
result[1].should.equal('world,false,true,false,false,true,false');
result[2].should.equal('this,false,false,true,false,false,true');
result[3].should.equal('is,false,true,false,false,true,false');
result[4].should.equal('ghost,false,false,true,true,false,true');
// test with context as an object
context = {
one: 'hello',
two: 'world',
three: 'this',
four: 'is',
five: 'ghost'
};
rendered = helpers.foreach.call(_this, context, options);
result = rendered.split('\n');
result[0].should.equal('hello,true,false,true,false,false,true');
result[1].should.equal('world,false,true,false,false,true,false');
result[2].should.equal('this,false,false,true,false,false,true');
result[3].should.equal('is,false,true,false,false,true,false');
result[4].should.equal('ghost,false,false,true,true,false,true');
});
it('should return the correct inverse result if no context is provided', function () {
var options = {},
context = [],
_this = 'the inverse data',
rendered;
options.fn = function () {};
options.inverse = inverse;
options.hash = {
columns: 0
};
options.data = {};
rendered = helpers.foreach.call(_this, context, options);
rendered.should.equal(_this);
});
});
describe('helperMissing', function () {
it('should not throw an error', function () {
var helperMissing = helpers.__get__('coreHelpers.helperMissing');
should.exist(helperMissing);
function runHelper() {
var args = arguments;
return function () {
helperMissing.apply(null, args);
}
}
runHelper('test helper').should.not.throwError();
runHelper('test helper', 'second argument').should.not.throwError();
});
});
// ## Admin only helpers
describe("ghostScriptTags helper", function () {
var rendered,
@ -1252,4 +1529,70 @@ describe('Core Helpers', function () {
}).catch(done);
});
});
describe('file storage helper', function () {
it('is loaded', function () {
should.exist(helpers.file_storage);
});
it('should return the string true when config() has no fileStorage property', function () {
var fileStorage = helpers.file_storage();
should.exist(fileStorage);
fileStorage.should.equal('true');
});
it('should return the config().fileStorage value when it exists', function () {
var setting = 'file storage value',
cfg = helpers.__get__('config'),
fileStorage;
configStub = sandbox.stub().returns({
fileStorage: setting
});
_.extend(cfg, configStub);
helpers.__set__('config', cfg);
fileStorage = helpers.file_storage();
should.exist(fileStorage);
fileStorage.should.equal(setting);
});
});
describe('apps helper', function () {
it('is loaded', function () {
should.exist(helpers.apps);
});
it('should return the string false when config() has no apps property', function () {
var apps = helpers.apps();
should.exist(apps);
apps.should.equal('false');
});
it('should return the config().apps value when it exists', function () {
var setting = 'app value',
cfg = helpers.__get__('config'),
apps;
configStub = sandbox.stub().returns({
apps: setting
});
_.extend(cfg, configStub);
helpers.__set__('config', cfg);
apps = helpers.apps();
should.exist(apps);
apps.should.equal(setting);
});
});
});