Files
handlebars.js/spec/partials.js
T
2019-12-03 22:39:17 +01:00

845 lines
25 KiB
JavaScript

describe('partials', function() {
it('basic partials', function() {
var string = 'Dudes: {{#dudes}}{{> dude}}{{/dudes}}';
var partial = '{{name}} ({{url}}) ';
var hash = {
dudes: [
{ name: 'Yehuda', url: 'http://yehuda' },
{ name: 'Alan', url: 'http://alan' }
]
};
shouldCompileToWithPartials(
string,
[hash, {}, { dude: partial }],
true,
'Dudes: Yehuda (http://yehuda) Alan (http://alan) '
);
shouldCompileToWithPartials(
string,
[hash, {}, { dude: partial }, , false],
true,
'Dudes: Yehuda (http://yehuda) Alan (http://alan) '
);
});
it('dynamic partials', function() {
var string = 'Dudes: {{#dudes}}{{> (partial)}}{{/dudes}}';
var partial = '{{name}} ({{url}}) ';
var hash = {
dudes: [
{ name: 'Yehuda', url: 'http://yehuda' },
{ name: 'Alan', url: 'http://alan' }
]
};
var helpers = {
partial: function() {
return 'dude';
}
};
shouldCompileToWithPartials(
string,
[hash, helpers, { dude: partial }],
true,
'Dudes: Yehuda (http://yehuda) Alan (http://alan) '
);
shouldCompileToWithPartials(
string,
[hash, helpers, { dude: partial }, , false],
true,
'Dudes: Yehuda (http://yehuda) Alan (http://alan) '
);
});
it('failing dynamic partials', function() {
var string = 'Dudes: {{#dudes}}{{> (partial)}}{{/dudes}}';
var partial = '{{name}} ({{url}}) ';
var hash = {
dudes: [
{ name: 'Yehuda', url: 'http://yehuda' },
{ name: 'Alan', url: 'http://alan' }
]
};
var helpers = {
partial: function() {
return 'missing';
}
};
shouldThrow(
function() {
shouldCompileToWithPartials(
string,
[hash, helpers, { dude: partial }],
true,
'Dudes: Yehuda (http://yehuda) Alan (http://alan) '
);
},
Handlebars.Exception,
'The partial missing could not be found'
);
});
it('partials with context', function() {
var string = 'Dudes: {{>dude dudes}}';
var partial = '{{#this}}{{name}} ({{url}}) {{/this}}';
var hash = {
dudes: [
{ name: 'Yehuda', url: 'http://yehuda' },
{ name: 'Alan', url: 'http://alan' }
]
};
shouldCompileToWithPartials(
string,
[hash, {}, { dude: partial }],
true,
'Dudes: Yehuda (http://yehuda) Alan (http://alan) ',
'Partials can be passed a context'
);
});
it('partials with no context', function() {
var partial = '{{name}} ({{url}}) ';
var hash = {
dudes: [
{ name: 'Yehuda', url: 'http://yehuda' },
{ name: 'Alan', url: 'http://alan' }
]
};
shouldCompileToWithPartials(
'Dudes: {{#dudes}}{{>dude}}{{/dudes}}',
[hash, {}, { dude: partial }, { explicitPartialContext: true }],
true,
'Dudes: () () '
);
shouldCompileToWithPartials(
'Dudes: {{#dudes}}{{>dude name="foo"}}{{/dudes}}',
[hash, {}, { dude: partial }, { explicitPartialContext: true }],
true,
'Dudes: foo () foo () '
);
});
it('partials with string context', function() {
var string = 'Dudes: {{>dude "dudes"}}';
var partial = '{{.}}';
var hash = {};
shouldCompileToWithPartials(
string,
[hash, {}, { dude: partial }],
true,
'Dudes: dudes'
);
});
it('partials with undefined context', function() {
var string = 'Dudes: {{>dude dudes}}';
var partial = '{{foo}} Empty';
var hash = {};
shouldCompileToWithPartials(
string,
[hash, {}, { dude: partial }],
true,
'Dudes: Empty'
);
});
it('partials with duplicate parameters', function() {
shouldThrow(
function() {
CompilerContext.compile('Dudes: {{>dude dudes foo bar=baz}}');
},
Error,
'Unsupported number of partial arguments: 2 - 1:7'
);
});
it('partials with parameters', function() {
var string = 'Dudes: {{#dudes}}{{> dude others=..}}{{/dudes}}';
var partial = '{{others.foo}}{{name}} ({{url}}) ';
var hash = {
foo: 'bar',
dudes: [
{ name: 'Yehuda', url: 'http://yehuda' },
{ name: 'Alan', url: 'http://alan' }
]
};
shouldCompileToWithPartials(
string,
[hash, {}, { dude: partial }],
true,
'Dudes: barYehuda (http://yehuda) barAlan (http://alan) ',
'Basic partials output based on current context.'
);
});
it('partial in a partial', function() {
var string = 'Dudes: {{#dudes}}{{>dude}}{{/dudes}}';
var dude = '{{name}} {{> url}} ';
var url = '<a href="{{url}}">{{url}}</a>';
var hash = {
dudes: [
{ name: 'Yehuda', url: 'http://yehuda' },
{ name: 'Alan', url: 'http://alan' }
]
};
shouldCompileToWithPartials(
string,
[hash, {}, { dude: dude, url: url }],
true,
'Dudes: Yehuda <a href="http://yehuda">http://yehuda</a> Alan <a href="http://alan">http://alan</a> ',
'Partials are rendered inside of other partials'
);
});
it('rendering undefined partial throws an exception', function() {
shouldThrow(
function() {
var template = CompilerContext.compile('{{> whatever}}');
template();
},
Handlebars.Exception,
'The partial whatever could not be found'
);
});
it('registering undefined partial throws an exception', function() {
shouldThrow(
function() {
var undef;
handlebarsEnv.registerPartial('undefined_test', undef);
},
Handlebars.Exception,
'Attempting to register a partial called "undefined_test" as undefined'
);
});
it('rendering template partial in vm mode throws an exception', function() {
shouldThrow(
function() {
var template = CompilerContext.compile('{{> whatever}}');
template();
},
Handlebars.Exception,
'The partial whatever could not be found'
);
});
it('rendering function partial in vm mode', function() {
var string = 'Dudes: {{#dudes}}{{> dude}}{{/dudes}}';
function partial(context) {
return context.name + ' (' + context.url + ') ';
}
var hash = {
dudes: [
{ name: 'Yehuda', url: 'http://yehuda' },
{ name: 'Alan', url: 'http://alan' }
]
};
shouldCompileTo(
string,
[hash, {}, { dude: partial }],
'Dudes: Yehuda (http://yehuda) Alan (http://alan) ',
'Function partials output based in VM.'
);
});
it('GH-14: a partial preceding a selector', function() {
var string = 'Dudes: {{>dude}} {{anotherDude}}';
var dude = '{{name}}';
var hash = { name: 'Jeepers', anotherDude: 'Creepers' };
shouldCompileToWithPartials(
string,
[hash, {}, { dude: dude }],
true,
'Dudes: Jeepers Creepers',
'Regular selectors can follow a partial'
);
});
it('Partials with slash paths', function() {
var string = 'Dudes: {{> shared/dude}}';
var dude = '{{name}}';
var hash = { name: 'Jeepers', anotherDude: 'Creepers' };
shouldCompileToWithPartials(
string,
[hash, {}, { 'shared/dude': dude }],
true,
'Dudes: Jeepers',
'Partials can use literal paths'
);
});
it('Partials with slash and point paths', function() {
var string = 'Dudes: {{> shared/dude.thing}}';
var dude = '{{name}}';
var hash = { name: 'Jeepers', anotherDude: 'Creepers' };
shouldCompileToWithPartials(
string,
[hash, {}, { 'shared/dude.thing': dude }],
true,
'Dudes: Jeepers',
'Partials can use literal with points in paths'
);
});
it('Global Partials', function() {
handlebarsEnv.registerPartial('globalTest', '{{anotherDude}}');
var string = 'Dudes: {{> shared/dude}} {{> globalTest}}';
var dude = '{{name}}';
var hash = { name: 'Jeepers', anotherDude: 'Creepers' };
shouldCompileToWithPartials(
string,
[hash, {}, { 'shared/dude': dude }],
true,
'Dudes: Jeepers Creepers',
'Partials can use globals or passed'
);
handlebarsEnv.unregisterPartial('globalTest');
equals(handlebarsEnv.partials.globalTest, undefined);
});
it('Multiple partial registration', function() {
handlebarsEnv.registerPartial({
'shared/dude': '{{name}}',
globalTest: '{{anotherDude}}'
});
var string = 'Dudes: {{> shared/dude}} {{> globalTest}}';
var hash = { name: 'Jeepers', anotherDude: 'Creepers' };
shouldCompileToWithPartials(
string,
[hash],
true,
'Dudes: Jeepers Creepers',
'Partials can use globals or passed'
);
});
it('Partials with integer path', function() {
var string = 'Dudes: {{> 404}}';
var dude = '{{name}}';
var hash = { name: 'Jeepers', anotherDude: 'Creepers' };
shouldCompileToWithPartials(
string,
[hash, {}, { 404: dude }],
true,
'Dudes: Jeepers',
'Partials can use literal paths'
);
});
it('Partials with complex path', function() {
var string = 'Dudes: {{> 404/asdf?.bar}}';
var dude = '{{name}}';
var hash = { name: 'Jeepers', anotherDude: 'Creepers' };
shouldCompileToWithPartials(
string,
[hash, {}, { '404/asdf?.bar': dude }],
true,
'Dudes: Jeepers',
'Partials can use literal paths'
);
});
it('Partials with escaped', function() {
var string = 'Dudes: {{> [+404/asdf?.bar]}}';
var dude = '{{name}}';
var hash = { name: 'Jeepers', anotherDude: 'Creepers' };
shouldCompileToWithPartials(
string,
[hash, {}, { '+404/asdf?.bar': dude }],
true,
'Dudes: Jeepers',
'Partials can use literal paths'
);
});
it('Partials with string', function() {
var string = "Dudes: {{> '+404/asdf?.bar'}}";
var dude = '{{name}}';
var hash = { name: 'Jeepers', anotherDude: 'Creepers' };
shouldCompileToWithPartials(
string,
[hash, {}, { '+404/asdf?.bar': dude }],
true,
'Dudes: Jeepers',
'Partials can use literal paths'
);
});
it('should handle empty partial', function() {
var string = 'Dudes: {{#dudes}}{{> dude}}{{/dudes}}';
var partial = '';
var hash = {
dudes: [
{ name: 'Yehuda', url: 'http://yehuda' },
{ name: 'Alan', url: 'http://alan' }
]
};
shouldCompileToWithPartials(
string,
[hash, {}, { dude: partial }],
true,
'Dudes: '
);
});
it('throw on missing partial', function() {
var compile = handlebarsEnv.compile;
handlebarsEnv.compile = undefined;
shouldThrow(
function() {
shouldCompileTo('{{> dude}}', [{}, {}, { dude: 'fail' }], '');
},
Error,
/The partial dude could not be compiled/
);
handlebarsEnv.compile = compile;
});
describe('partial blocks', function() {
it('should render partial block as default', function() {
shouldCompileToWithPartials(
'{{#> dude}}success{{/dude}}',
[{}, {}, {}],
true,
'success'
);
});
it('should execute default block with proper context', function() {
shouldCompileToWithPartials(
'{{#> dude context}}{{value}}{{/dude}}',
[{ context: { value: 'success' } }, {}, {}],
true,
'success'
);
});
it('should propagate block parameters to default block', function() {
shouldCompileToWithPartials(
'{{#with context as |me|}}{{#> dude}}{{me.value}}{{/dude}}{{/with}}',
[{ context: { value: 'success' } }, {}, {}],
true,
'success'
);
});
it('should not use partial block if partial exists', function() {
shouldCompileToWithPartials(
'{{#> dude}}fail{{/dude}}',
[{}, {}, { dude: 'success' }],
true,
'success'
);
});
it('should render block from partial', function() {
shouldCompileToWithPartials(
'{{#> dude}}success{{/dude}}',
[{}, {}, { dude: '{{> @partial-block }}' }],
true,
'success'
);
});
it('should be able to render the partial-block twice', function() {
shouldCompileToWithPartials(
'{{#> dude}}success{{/dude}}',
[{}, {}, { dude: '{{> @partial-block }} {{> @partial-block }}' }],
true,
'success success'
);
});
it('should render block from partial with context', function() {
shouldCompileToWithPartials(
'{{#> dude}}{{value}}{{/dude}}',
[
{ context: { value: 'success' } },
{},
{ dude: '{{#with context}}{{> @partial-block }}{{/with}}' }
],
true,
'success'
);
});
it('should be able to access the @data frame from a partial-block', function() {
shouldCompileToWithPartials(
'{{#> dude}}in-block: {{@root/value}}{{/dude}}',
[
{ value: 'success' },
{},
{
dude:
'<code>before-block: {{@root/value}} {{> @partial-block }}</code>'
}
],
true,
'<code>before-block: success in-block: success</code>'
);
});
it('should allow the #each-helper to be used along with partial-blocks', function() {
shouldCompileToWithPartials(
'<template>{{#> list value}}value = {{.}}{{/list}}</template>',
[
{ value: ['a', 'b', 'c'] },
{},
{
list:
'<list>{{#each .}}<item>{{> @partial-block}}</item>{{/each}}</list>'
}
],
true,
'<template><list><item>value = a</item><item>value = b</item><item>value = c</item></list></template>'
);
});
it('should render block from partial with context (twice)', function() {
shouldCompileToWithPartials(
'{{#> dude}}{{value}}{{/dude}}',
[
{ context: { value: 'success' } },
{},
{
dude:
'{{#with context}}{{> @partial-block }} {{> @partial-block }}{{/with}}'
}
],
true,
'success success'
);
});
it('should render block from partial with context', function() {
shouldCompileToWithPartials(
'{{#> dude}}{{../context/value}}{{/dude}}',
[
{ context: { value: 'success' } },
{},
{ dude: '{{#with context}}{{> @partial-block }}{{/with}}' }
],
true,
'success'
);
});
it('should render block from partial with block params', function() {
shouldCompileToWithPartials(
'{{#with context as |me|}}{{#> dude}}{{me.value}}{{/dude}}{{/with}}',
[
{ context: { value: 'success' } },
{},
{ dude: '{{> @partial-block }}' }
],
true,
'success'
);
});
it('should render nested partial blocks', function() {
shouldCompileToWithPartials(
'<template>{{#> outer}}{{value}}{{/outer}}</template>',
[
{ value: 'success' },
{},
{
outer:
'<outer>{{#> nested}}<outer-block>{{> @partial-block}}</outer-block>{{/nested}}</outer>',
nested: '<nested>{{> @partial-block}}</nested>'
}
],
true,
'<template><outer><nested><outer-block>success</outer-block></nested></outer></template>'
);
});
it('should render nested partial blocks at different nesting levels', function() {
shouldCompileToWithPartials(
'<template>{{#> outer}}{{value}}{{/outer}}</template>',
[
{ value: 'success' },
{},
{
outer:
'<outer>{{#> nested}}<outer-block>{{> @partial-block}}</outer-block>{{/nested}}{{> @partial-block}}</outer>',
nested: '<nested>{{> @partial-block}}</nested>'
}
],
true,
'<template><outer><nested><outer-block>success</outer-block></nested>success</outer></template>'
);
});
it('should render nested partial blocks at different nesting levels (twice)', function() {
shouldCompileToWithPartials(
'<template>{{#> outer}}{{value}}{{/outer}}</template>',
[
{ value: 'success' },
{},
{
outer:
'<outer>{{#> nested}}<outer-block>{{> @partial-block}} {{> @partial-block}}</outer-block>{{/nested}}{{> @partial-block}}+{{> @partial-block}}</outer>',
nested: '<nested>{{> @partial-block}}</nested>'
}
],
true,
'<template><outer><nested><outer-block>success success</outer-block></nested>success+success</outer></template>'
);
});
it('should render nested partial blocks (twice at each level)', function() {
shouldCompileToWithPartials(
'<template>{{#> outer}}{{value}}{{/outer}}</template>',
[
{ value: 'success' },
{},
{
outer:
'<outer>{{#> nested}}<outer-block>{{> @partial-block}} {{> @partial-block}}</outer-block>{{/nested}}</outer>',
nested: '<nested>{{> @partial-block}}{{> @partial-block}}</nested>'
}
],
true,
'<template><outer>' +
'<nested><outer-block>success success</outer-block><outer-block>success success</outer-block></nested>' +
'</outer></template>'
);
});
});
describe('inline partials', function() {
it('should define inline partials for template', function() {
shouldCompileTo(
'{{#*inline "myPartial"}}success{{/inline}}{{> myPartial}}',
{},
'success'
);
});
it('should overwrite multiple partials in the same template', function() {
shouldCompileTo(
'{{#*inline "myPartial"}}fail{{/inline}}{{#*inline "myPartial"}}success{{/inline}}{{> myPartial}}',
{},
'success'
);
});
it('should define inline partials for block', function() {
shouldCompileTo(
'{{#with .}}{{#*inline "myPartial"}}success{{/inline}}{{> myPartial}}{{/with}}',
{},
'success'
);
shouldThrow(
function() {
shouldCompileTo(
'{{#with .}}{{#*inline "myPartial"}}success{{/inline}}{{/with}}{{> myPartial}}',
{},
'success'
);
},
Error,
/myPartial could not/
);
});
it('should override global partials', function() {
shouldCompileTo(
'{{#*inline "myPartial"}}success{{/inline}}{{> myPartial}}',
{
hash: {},
partials: {
myPartial: function() {
return 'fail';
}
}
},
'success'
);
});
it('should override template partials', function() {
shouldCompileTo(
'{{#*inline "myPartial"}}fail{{/inline}}{{#with .}}{{#*inline "myPartial"}}success{{/inline}}{{> myPartial}}{{/with}}',
{},
'success'
);
});
it('should override partials down the entire stack', function() {
shouldCompileTo(
'{{#with .}}{{#*inline "myPartial"}}success{{/inline}}{{#with .}}{{#with .}}{{> myPartial}}{{/with}}{{/with}}{{/with}}',
{},
'success'
);
});
it('should define inline partials for partial call', function() {
shouldCompileToWithPartials(
'{{#*inline "myPartial"}}success{{/inline}}{{> dude}}',
[{}, {}, { dude: '{{> myPartial }}' }],
true,
'success'
);
});
it('should define inline partials in partial block call', function() {
shouldCompileToWithPartials(
'{{#> dude}}{{#*inline "myPartial"}}success{{/inline}}{{/dude}}',
[{}, {}, { dude: '{{> myPartial }}' }],
true,
'success'
);
});
it('should render nested inline partials', function() {
shouldCompileToWithPartials(
'{{#*inline "outer"}}{{#>inner}}<outer-block>{{>@partial-block}}</outer-block>{{/inner}}{{/inline}}' +
'{{#*inline "inner"}}<inner>{{>@partial-block}}</inner>{{/inline}}' +
'{{#>outer}}{{value}}{{/outer}}',
[{ value: 'success' }, {}, {}],
true,
'<inner><outer-block>success</outer-block></inner>'
);
});
it('should render nested inline partials with partial-blocks on different nesting levels', function() {
shouldCompileToWithPartials(
'{{#*inline "outer"}}{{#>inner}}<outer-block>{{>@partial-block}}</outer-block>{{/inner}}{{>@partial-block}}{{/inline}}' +
'{{#*inline "inner"}}<inner>{{>@partial-block}}</inner>{{/inline}}' +
'{{#>outer}}{{value}}{{/outer}}',
[{ value: 'success' }, {}, {}],
true,
'<inner><outer-block>success</outer-block></inner>success'
);
});
it('should render nested inline partials (twice at each level)', function() {
shouldCompileToWithPartials(
'{{#*inline "outer"}}{{#>inner}}<outer-block>{{>@partial-block}} {{>@partial-block}}</outer-block>{{/inner}}{{/inline}}' +
'{{#*inline "inner"}}<inner>{{>@partial-block}}{{>@partial-block}}</inner>{{/inline}}' +
'{{#>outer}}{{value}}{{/outer}}',
[{ value: 'success' }, {}, {}],
true,
'<inner><outer-block>success success</outer-block><outer-block>success success</outer-block></inner>'
);
});
});
it('should pass compiler flags', function() {
if (Handlebars.compile) {
var env = Handlebars.create();
env.registerPartial('partial', '{{foo}}');
var template = env.compile('{{foo}} {{> partial}}', { noEscape: true });
equal(template({ foo: '<' }), '< <');
}
});
describe('standalone partials', function() {
it('indented partials', function() {
var string = 'Dudes:\n{{#dudes}}\n {{>dude}}\n{{/dudes}}';
var dude = '{{name}}\n';
var hash = {
dudes: [
{ name: 'Yehuda', url: 'http://yehuda' },
{ name: 'Alan', url: 'http://alan' }
]
};
shouldCompileToWithPartials(
string,
[hash, {}, { dude: dude }],
true,
'Dudes:\n Yehuda\n Alan\n'
);
});
it('nested indented partials', function() {
var string = 'Dudes:\n{{#dudes}}\n {{>dude}}\n{{/dudes}}';
var dude = '{{name}}\n {{> url}}';
var url = '{{url}}!\n';
var hash = {
dudes: [
{ name: 'Yehuda', url: 'http://yehuda' },
{ name: 'Alan', url: 'http://alan' }
]
};
shouldCompileToWithPartials(
string,
[hash, {}, { dude: dude, url: url }],
true,
'Dudes:\n Yehuda\n http://yehuda!\n Alan\n http://alan!\n'
);
});
it('prevent nested indented partials', function() {
var string = 'Dudes:\n{{#dudes}}\n {{>dude}}\n{{/dudes}}';
var dude = '{{name}}\n {{> url}}';
var url = '{{url}}!\n';
var hash = {
dudes: [
{ name: 'Yehuda', url: 'http://yehuda' },
{ name: 'Alan', url: 'http://alan' }
]
};
shouldCompileToWithPartials(
string,
[hash, {}, { dude: dude, url: url }, { preventIndent: true }],
true,
'Dudes:\n Yehuda\n http://yehuda!\n Alan\n http://alan!\n'
);
});
});
describe('compat mode', function() {
it('partials can access parents', function() {
var string = 'Dudes: {{#dudes}}{{> dude}}{{/dudes}}';
var partial = '{{name}} ({{url}}) {{root}} ';
var hash = {
root: 'yes',
dudes: [
{ name: 'Yehuda', url: 'http://yehuda' },
{ name: 'Alan', url: 'http://alan' }
]
};
shouldCompileToWithPartials(
string,
[hash, {}, { dude: partial }, true],
true,
'Dudes: Yehuda (http://yehuda) yes Alan (http://alan) yes '
);
});
it('partials can access parents with custom context', function() {
var string = 'Dudes: {{#dudes}}{{> dude "test"}}{{/dudes}}';
var partial = '{{name}} ({{url}}) {{root}} ';
var hash = {
root: 'yes',
dudes: [
{ name: 'Yehuda', url: 'http://yehuda' },
{ name: 'Alan', url: 'http://alan' }
]
};
shouldCompileToWithPartials(
string,
[hash, {}, { dude: partial }, true],
true,
'Dudes: Yehuda (http://yehuda) yes Alan (http://alan) yes '
);
});
it('partials can access parents without data', function() {
var string = 'Dudes: {{#dudes}}{{> dude}}{{/dudes}}';
var partial = '{{name}} ({{url}}) {{root}} ';
var hash = {
root: 'yes',
dudes: [
{ name: 'Yehuda', url: 'http://yehuda' },
{ name: 'Alan', url: 'http://alan' }
]
};
shouldCompileToWithPartials(
string,
[hash, {}, { dude: partial }, true, false],
true,
'Dudes: Yehuda (http://yehuda) yes Alan (http://alan) yes '
);
});
it('partials inherit compat', function() {
var string = 'Dudes: {{> dude}}';
var partial = '{{#dudes}}{{name}} ({{url}}) {{root}} {{/dudes}}';
var hash = {
root: 'yes',
dudes: [
{ name: 'Yehuda', url: 'http://yehuda' },
{ name: 'Alan', url: 'http://alan' }
]
};
shouldCompileToWithPartials(
string,
[hash, {}, { dude: partial }, true],
true,
'Dudes: Yehuda (http://yehuda) yes Alan (http://alan) yes '
);
});
});
});