Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
global.handlebarsEnv = null;
beforeEach(function () {
global.handlebarsEnv = Handlebars.create();
});
describe('basic context', function () {
it('most basic', function () {
expectTemplate('{{foo}}').withInput({ foo: 'foo' }).toCompileTo('foo');
});
it('escaping', function () {
expectTemplate('\\{{foo}}')
.withInput({ foo: 'food' })
.toCompileTo('{{foo}}');
expectTemplate('content \\{{foo}}')
.withInput({ foo: 'food' })
.toCompileTo('content {{foo}}');
expectTemplate('\\\\{{foo}}')
.withInput({ foo: 'food' })
.toCompileTo('\\food');
expectTemplate('content \\\\{{foo}}')
.withInput({ foo: 'food' })
.toCompileTo('content \\food');
expectTemplate('\\\\ {{foo}}')
.withInput({ foo: 'food' })
.toCompileTo('\\\\ food');
});
it('compiling with a basic context', function () {
expectTemplate('Goodbye\n{{cruel}}\n{{world}}!')
.withInput({
cruel: 'cruel',
world: 'world',
})
.withMessage('It works if all the required keys are provided')
.toCompileTo('Goodbye\ncruel\nworld!');
});
it('compiling with a string context', function () {
expectTemplate('{{.}}{{length}}').withInput('bye').toCompileTo('bye3');
});
it('compiling with an undefined context', function () {
expectTemplate('Goodbye\n{{cruel}}\n{{world.bar}}!')
.withInput(undefined)
.toCompileTo('Goodbye\n\n!');
expectTemplate('{{#unless foo}}Goodbye{{../test}}{{test2}}{{/unless}}')
.withInput(undefined)
.toCompileTo('Goodbye');
});
it('comments', function () {
expectTemplate('{{! Goodbye}}Goodbye\n{{cruel}}\n{{world}}!')
.withInput({
cruel: 'cruel',
world: 'world',
})
.withMessage('comments are ignored')
.toCompileTo('Goodbye\ncruel\nworld!');
expectTemplate(' {{~! comment ~}} blah').toCompileTo('blah');
expectTemplate(' {{~!-- long-comment --~}} blah').toCompileTo(
'blah'
);
expectTemplate(' {{! comment ~}} blah').toCompileTo(' blah');
expectTemplate(' {{!-- long-comment --~}} blah').toCompileTo(
' blah'
);
expectTemplate(' {{~! comment}} blah').toCompileTo(' blah');
expectTemplate(' {{~!-- long-comment --}} blah').toCompileTo(
' blah'
);
});
it('boolean', function () {
var string = '{{#goodbye}}GOODBYE {{/goodbye}}cruel {{world}}!';
expectTemplate(string)
.withInput({
goodbye: true,
world: 'world',
})
.withMessage('booleans show the contents when true')
.toCompileTo('GOODBYE cruel world!');
expectTemplate(string)
.withInput({
goodbye: false,
world: 'world',
})
.withMessage('booleans do not show the contents when false')
.toCompileTo('cruel world!');
});
it('zeros', function () {
expectTemplate('num1: {{num1}}, num2: {{num2}}')
.withInput({
num1: 42,
num2: 0,
})
.toCompileTo('num1: 42, num2: 0');
expectTemplate('num: {{.}}').withInput(0).toCompileTo('num: 0');
expectTemplate('num: {{num1/num2}}')
.withInput({ num1: { num2: 0 } })
.toCompileTo('num: 0');
});
it('false', function () {
/* eslint-disable no-new-wrappers */
expectTemplate('val1: {{val1}}, val2: {{val2}}')
.withInput({
val1: false,
val2: new Boolean(false),
})
.toCompileTo('val1: false, val2: false');
expectTemplate('val: {{.}}').withInput(false).toCompileTo('val: false');
expectTemplate('val: {{val1/val2}}')
.withInput({ val1: { val2: false } })
.toCompileTo('val: false');
expectTemplate('val1: {{{val1}}}, val2: {{{val2}}}')
.withInput({
val1: false,
val2: new Boolean(false),
})
.toCompileTo('val1: false, val2: false');
expectTemplate('val: {{{val1/val2}}}')
.withInput({ val1: { val2: false } })
.toCompileTo('val: false');
/* eslint-enable */
});
it('should handle undefined and null', function () {
expectTemplate('{{awesome undefined null}}')
.withInput({
awesome: function (_undefined, _null, options) {
return (
(_undefined === undefined) +
' ' +
(_null === null) +
' ' +
typeof options
);
},
})
.toCompileTo('true true object');
expectTemplate('{{undefined}}')
.withInput({
undefined: function () {
return 'undefined!';
},
})
.toCompileTo('undefined!');
expectTemplate('{{null}}')
.withInput({
null: function () {
return 'null!';
},
})
.toCompileTo('null!');
});
it('newlines', function () {
expectTemplate("Alan's\nTest").toCompileTo("Alan's\nTest");
expectTemplate("Alan's\rTest").toCompileTo("Alan's\rTest");
});
it('escaping text', function () {
expectTemplate("Awesome's")
.withMessage(
"text is escaped so that it doesn't get caught on single quotes"
)
.toCompileTo("Awesome's");
expectTemplate('Awesome\\')
.withMessage("text is escaped so that the closing quote can't be ignored")
.toCompileTo('Awesome\\');
expectTemplate('Awesome\\\\ foo')
.withMessage("text is escaped so that it doesn't mess up backslashes")
.toCompileTo('Awesome\\\\ foo');
expectTemplate('Awesome {{foo}}')
.withInput({ foo: '\\' })
.withMessage("text is escaped so that it doesn't mess up backslashes")
.toCompileTo('Awesome \\');
expectTemplate(" ' ' ")
.withMessage('double quotes never produce invalid javascript')
.toCompileTo(" ' ' ");
});
it('escaping expressions', function () {
expectTemplate('{{{awesome}}}')
.withInput({ awesome: "&'\\<>" })
.withMessage("expressions with 3 handlebars aren't escaped")
.toCompileTo("&'\\<>");
expectTemplate('{{&awesome}}')
.withInput({ awesome: "&'\\<>" })
.withMessage("expressions with {{& handlebars aren't escaped")
.toCompileTo("&'\\<>");
expectTemplate('{{awesome}}')
.withInput({ awesome: '&"\'`\\<>' })
.withMessage('by default expressions should be escaped')
.toCompileTo('&amp;&quot;&#x27;&#x60;\\&lt;&gt;');
expectTemplate('{{awesome}}')
.withInput({ awesome: 'Escaped, <b> looks like: &lt;b&gt;' })
.withMessage('escaping should properly handle amperstands')
.toCompileTo('Escaped, &lt;b&gt; looks like: &amp;lt;b&amp;gt;');
});
it("functions returning safestrings shouldn't be escaped", function () {
expectTemplate('{{awesome}}')
.withInput({
awesome: function () {
return new Handlebars.SafeString("&'\\<>");
},
})
.withMessage("functions returning safestrings aren't escaped")
.toCompileTo("&'\\<>");
});
it('functions', function () {
expectTemplate('{{awesome}}')
.withInput({
awesome: function () {
return 'Awesome';
},
})
.withMessage('functions are called and render their output')
.toCompileTo('Awesome');
expectTemplate('{{awesome}}')
.withInput({
awesome: function () {
return this.more;
},
more: 'More awesome',
})
.withMessage('functions are bound to the context')
.toCompileTo('More awesome');
});
it('functions with context argument', function () {
expectTemplate('{{awesome frank}}')
.withInput({
awesome: function (context) {
return context;
},
frank: 'Frank',
})
.withMessage('functions are called with context arguments')
.toCompileTo('Frank');
});
it('pathed functions with context argument', function () {
expectTemplate('{{bar.awesome frank}}')
.withInput({
bar: {
awesome: function (context) {
return context;
},
},
frank: 'Frank',
})
.withMessage('functions are called with context arguments')
.toCompileTo('Frank');
});
it('depthed functions with context argument', function () {
expectTemplate('{{#with frank}}{{../awesome .}}{{/with}}')
.withInput({
awesome: function (context) {
return context;
},
frank: 'Frank',
})
.withMessage('functions are called with context arguments')
.toCompileTo('Frank');
});
it('block functions with context argument', function () {
expectTemplate('{{#awesome 1}}inner {{.}}{{/awesome}}')
.withInput({
awesome: function (context, options) {
return options.fn(context);
},
})
.withMessage('block functions are called with context and options')
.toCompileTo('inner 1');
});
it('depthed block functions with context argument', function () {
expectTemplate(
'{{#with value}}{{#../awesome 1}}inner {{.}}{{/../awesome}}{{/with}}'
)
.withInput({
value: true,
awesome: function (context, options) {
return options.fn(context);
},
})
.withMessage('block functions are called with context and options')
.toCompileTo('inner 1');
});
it('block functions without context argument', function () {
expectTemplate('{{#awesome}}inner{{/awesome}}')
.withInput({
awesome: function (options) {
return options.fn(this);
},
})
.withMessage('block functions are called with options')
.toCompileTo('inner');
});
it('pathed block functions without context argument', function () {
expectTemplate('{{#foo.awesome}}inner{{/foo.awesome}}')
.withInput({
foo: {
awesome: function () {
return this;
},
},
})
.withMessage('block functions are called with options')
.toCompileTo('inner');
});
it('depthed block functions without context argument', function () {
expectTemplate(
'{{#with value}}{{#../awesome}}inner{{/../awesome}}{{/with}}'
)
.withInput({
value: true,
awesome: function () {
return this;
},
})
.withMessage('block functions are called with options')
.toCompileTo('inner');
});
it('paths with hyphens', function () {
expectTemplate('{{foo-bar}}')
.withInput({ 'foo-bar': 'baz' })
.withMessage('Paths can contain hyphens (-)')
.toCompileTo('baz');
expectTemplate('{{foo.foo-bar}}')
.withInput({ foo: { 'foo-bar': 'baz' } })
.withMessage('Paths can contain hyphens (-)')
.toCompileTo('baz');
expectTemplate('{{foo/foo-bar}}')
.withInput({ foo: { 'foo-bar': 'baz' } })
.withMessage('Paths can contain hyphens (-)')
.toCompileTo('baz');
});
it('nested paths', function () {
expectTemplate('Goodbye {{alan/expression}} world!')
.withInput({ alan: { expression: 'beautiful' } })
.withMessage('Nested paths access nested objects')
.toCompileTo('Goodbye beautiful world!');
});
it('nested paths with empty string value', function () {
expectTemplate('Goodbye {{alan/expression}} world!')
.withInput({ alan: { expression: '' } })
.withMessage('Nested paths access nested objects with empty string')
.toCompileTo('Goodbye world!');
});
it('literal paths', function () {
expectTemplate('Goodbye {{[@alan]/expression}} world!')
.withInput({ '@alan': { expression: 'beautiful' } })
.withMessage('Literal paths can be used')
.toCompileTo('Goodbye beautiful world!');
expectTemplate('Goodbye {{[foo bar]/expression}} world!')
.withInput({ 'foo bar': { expression: 'beautiful' } })
.withMessage('Literal paths can be used')
.toCompileTo('Goodbye beautiful world!');
});
it('literal references', function () {
expectTemplate('Goodbye {{[foo bar]}} world!')
.withInput({ 'foo bar': 'beautiful' })
.toCompileTo('Goodbye beautiful world!');
expectTemplate('Goodbye {{"foo bar"}} world!')
.withInput({ 'foo bar': 'beautiful' })
.toCompileTo('Goodbye beautiful world!');
expectTemplate("Goodbye {{'foo bar'}} world!")
.withInput({ 'foo bar': 'beautiful' })
.toCompileTo('Goodbye beautiful world!');
expectTemplate('Goodbye {{"foo[bar"}} world!')
.withInput({ 'foo[bar': 'beautiful' })
.toCompileTo('Goodbye beautiful world!');
expectTemplate('Goodbye {{"foo\'bar"}} world!')
.withInput({ "foo'bar": 'beautiful' })
.toCompileTo('Goodbye beautiful world!');
expectTemplate("Goodbye {{'foo\"bar'}} world!")
.withInput({ 'foo"bar': 'beautiful' })
.toCompileTo('Goodbye beautiful world!');
});
it("that current context path ({{.}}) doesn't hit helpers", function () {
expectTemplate('test: {{.}}')
.withInput(null)
.withHelpers({ helper: 'awesome' })
.toCompileTo('test: ');
});
it('complex but empty paths', function () {
expectTemplate('{{person/name}}')
.withInput({ person: { name: null } })
.toCompileTo('');
expectTemplate('{{person/name}}').withInput({ person: {} }).toCompileTo('');
});
it('this keyword in paths', function () {
expectTemplate('{{#goodbyes}}{{this}}{{/goodbyes}}')
.withInput({ goodbyes: ['goodbye', 'Goodbye', 'GOODBYE'] })
.withMessage('This keyword in paths evaluates to current context')
.toCompileTo('goodbyeGoodbyeGOODBYE');
expectTemplate('{{#hellos}}{{this/text}}{{/hellos}}')
.withInput({
hellos: [{ text: 'hello' }, { text: 'Hello' }, { text: 'HELLO' }],
})
.withMessage('This keyword evaluates in more complex paths')
.toCompileTo('helloHelloHELLO');
});
it('this keyword nested inside path', function () {
expectTemplate('{{#hellos}}{{text/this/foo}}{{/hellos}}').toThrow(
Error,
'Invalid path: text/this - 1:13'
);
expectTemplate('{{[this]}}').withInput({ this: 'bar' }).toCompileTo('bar');
expectTemplate('{{text/[this]}}')
.withInput({ text: { this: 'bar' } })
.toCompileTo('bar');
});
it('this keyword in helpers', function () {
var helpers = {
foo: function (value) {
return 'bar ' + value;
},
};
expectTemplate('{{#goodbyes}}{{foo this}}{{/goodbyes}}')
.withInput({ goodbyes: ['goodbye', 'Goodbye', 'GOODBYE'] })
.withHelpers(helpers)
.withMessage('This keyword in paths evaluates to current context')
.toCompileTo('bar goodbyebar Goodbyebar GOODBYE');
expectTemplate('{{#hellos}}{{foo this/text}}{{/hellos}}')
.withInput({
hellos: [{ text: 'hello' }, { text: 'Hello' }, { text: 'HELLO' }],
})
.withHelpers(helpers)
.withMessage('This keyword evaluates in more complex paths')
.toCompileTo('bar hellobar Hellobar HELLO');
});
it('this keyword nested inside helpers param', function () {
expectTemplate('{{#hellos}}{{foo text/this/foo}}{{/hellos}}').toThrow(
Error,
'Invalid path: text/this - 1:17'
);
expectTemplate('{{foo [this]}}')
.withInput({
foo: function (value) {
return value;
},
this: 'bar',
})
.toCompileTo('bar');
expectTemplate('{{foo text/[this]}}')
.withInput({
foo: function (value) {
return value;
},
text: { this: 'bar' },
})
.toCompileTo('bar');
});
it('pass string literals', function () {
expectTemplate('{{"foo"}}').toCompileTo('');
expectTemplate('{{"foo"}}').withInput({ foo: 'bar' }).toCompileTo('bar');
expectTemplate('{{#"foo"}}{{.}}{{/"foo"}}')
.withInput({
foo: ['bar', 'baz'],
})
.toCompileTo('barbaz');
});
it('pass number literals', function () {
expectTemplate('{{12}}').toCompileTo('');
expectTemplate('{{12}}').withInput({ 12: 'bar' }).toCompileTo('bar');
expectTemplate('{{12.34}}').toCompileTo('');
expectTemplate('{{12.34}}').withInput({ 12.34: 'bar' }).toCompileTo('bar');
expectTemplate('{{12.34 1}}')
.withInput({
12.34: function (arg) {
return 'bar' + arg;
},
})
.toCompileTo('bar1');
});
it('pass boolean literals', function () {
expectTemplate('{{true}}').toCompileTo('');
expectTemplate('{{true}}').withInput({ '': 'foo' }).toCompileTo('');
expectTemplate('{{false}}').withInput({ false: 'foo' }).toCompileTo('foo');
});
it('should handle literals in subexpression', function () {
expectTemplate('{{foo (false)}}')
.withInput({
false: function () {
return 'bar';
},
})
.withHelper('foo', function (arg) {
return arg;
})
.toCompileTo('bar');
});
});