diff options
Diffstat (limited to 'spec')
-rw-r--r-- | spec/blocks.js | 178 | ||||
-rw-r--r-- | spec/parser.js | 14 | ||||
-rw-r--r-- | spec/partials.js | 39 | ||||
-rw-r--r-- | spec/runtime.js | 6 | ||||
-rw-r--r-- | spec/tokenizer.js | 9 | ||||
-rw-r--r-- | spec/visitor.js | 2 |
6 files changed, 245 insertions, 3 deletions
diff --git a/spec/blocks.js b/spec/blocks.js index 71c9045..2fbaee7 100644 --- a/spec/blocks.js +++ b/spec/blocks.js @@ -166,4 +166,182 @@ describe('blocks', function() { shouldCompileTo(string, [hash, undefined, undefined, true], 'Goodbye cruel '); }); }); + + describe('decorators', function() { + it('should apply mustache decorators', function() { + var helpers = { + helper: function(options) { + return options.fn.run; + } + }; + var decorators = { + decorator: function(fn) { + fn.run = 'success'; + return fn; + } + }; + shouldCompileTo( + '{{#helper}}{{*decorator}}{{/helper}}', + {hash: {}, helpers: helpers, decorators: decorators}, + 'success'); + }); + it('should apply allow undefined return', function() { + var helpers = { + helper: function(options) { + return options.fn() + options.fn.run; + } + }; + var decorators = { + decorator: function(fn) { + fn.run = 'cess'; + } + }; + shouldCompileTo( + '{{#helper}}{{*decorator}}suc{{/helper}}', + {hash: {}, helpers: helpers, decorators: decorators}, + 'success'); + }); + + it('should apply block decorators', function() { + var helpers = { + helper: function(options) { + return options.fn.run; + } + }; + var decorators = { + decorator: function(fn, props, container, options) { + fn.run = options.fn(); + return fn; + } + }; + shouldCompileTo( + '{{#helper}}{{#*decorator}}success{{/decorator}}{{/helper}}', + {hash: {}, helpers: helpers, decorators: decorators}, + 'success'); + }); + it('should support nested decorators', function() { + var helpers = { + helper: function(options) { + return options.fn.run; + } + }; + var decorators = { + decorator: function(fn, props, container, options) { + fn.run = options.fn.nested + options.fn(); + return fn; + }, + nested: function(fn, props, container, options) { + props.nested = options.fn(); + } + }; + shouldCompileTo( + '{{#helper}}{{#*decorator}}{{#*nested}}suc{{/nested}}cess{{/decorator}}{{/helper}}', + {hash: {}, helpers: helpers, decorators: decorators}, + 'success'); + }); + + it('should apply multiple decorators', function() { + var helpers = { + helper: function(options) { + return options.fn.run; + } + }; + var decorators = { + decorator: function(fn, props, container, options) { + fn.run = (fn.run || '') + options.fn(); + return fn; + } + }; + shouldCompileTo( + '{{#helper}}{{#*decorator}}suc{{/decorator}}{{#*decorator}}cess{{/decorator}}{{/helper}}', + {hash: {}, helpers: helpers, decorators: decorators}, + 'success'); + }); + + it('should access parent variables', function() { + var helpers = { + helper: function(options) { + return options.fn.run; + } + }; + var decorators = { + decorator: function(fn, props, container, options) { + fn.run = options.args; + return fn; + } + }; + shouldCompileTo( + '{{#helper}}{{*decorator foo}}{{/helper}}', + {hash: {'foo': 'success'}, helpers: helpers, decorators: decorators}, + 'success'); + }); + it('should work with root program', function() { + var run; + var decorators = { + decorator: function(fn, props, container, options) { + equals(options.args[0], 'success'); + run = true; + return fn; + } + }; + shouldCompileTo( + '{{*decorator "success"}}', + {hash: {'foo': 'success'}, decorators: decorators}, + ''); + equals(run, true); + }); + it('should fail when accessing variables from root', function() { + var run; + var decorators = { + decorator: function(fn, props, container, options) { + equals(options.args[0], undefined); + run = true; + return fn; + } + }; + shouldCompileTo( + '{{*decorator foo}}', + {hash: {'foo': 'fail'}, decorators: decorators}, + ''); + equals(run, true); + }); + + describe('registration', function() { + it('unregisters', function() { + handlebarsEnv.decorators = {}; + + handlebarsEnv.registerDecorator('foo', function() { + return 'fail'; + }); + + equals(!!handlebarsEnv.decorators.foo, true); + handlebarsEnv.unregisterDecorator('foo'); + equals(handlebarsEnv.decorators.foo, undefined); + }); + + it('allows multiple globals', function() { + handlebarsEnv.decorators = {}; + + handlebarsEnv.registerDecorator({ + foo: function() {}, + bar: function() {} + }); + + equals(!!handlebarsEnv.decorators.foo, true); + equals(!!handlebarsEnv.decorators.bar, true); + handlebarsEnv.unregisterDecorator('foo'); + handlebarsEnv.unregisterDecorator('bar'); + equals(handlebarsEnv.decorators.foo, undefined); + equals(handlebarsEnv.decorators.bar, undefined); + }); + it('fails with multiple and args', function() { + shouldThrow(function() { + handlebarsEnv.registerDecorator({ + world: function() { return 'world!'; }, + testHelper: function() { return 'found it!'; } + }, {}); + }, Error, 'Arg not supported with multiple decorators'); + }); + }); + }); }); diff --git a/spec/parser.js b/spec/parser.js index 5b60f93..3b7e3e4 100644 --- a/spec/parser.js +++ b/spec/parser.js @@ -247,6 +247,20 @@ describe('parser', function() { }); }); + describe('directives', function() { + it('should parse block directives', function() { + equals(astFor('{{#* foo}}{{/foo}}'), 'DIRECTIVE BLOCK:\n PATH:foo []\n PROGRAM:\n'); + }); + it('should parse directives', function() { + equals(astFor('{{* foo}}'), '{{ DIRECTIVE PATH:foo [] }}\n'); + }); + it('should fail if directives have inverse', function() { + shouldThrow(function() { + astFor('{{#* foo}}{{^}}{{/foo}}'); + }, Error, /Unexpected inverse/); + }); + }); + it('GH1024 - should track program location properly', function() { var p = Handlebars.parse('\n' + ' {{#if foo}}\n' diff --git a/spec/partials.js b/spec/partials.js index 314cca2..f3283ba 100644 --- a/spec/partials.js +++ b/spec/partials.js @@ -257,6 +257,45 @@ describe('partials', function() { }); }); + 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 pass compiler flags', function() { if (Handlebars.compile) { var env = Handlebars.create(); diff --git a/spec/runtime.js b/spec/runtime.js index 502a843..a4830ad 100644 --- a/spec/runtime.js +++ b/spec/runtime.js @@ -14,19 +14,19 @@ describe('runtime', function() { it('should throw on version mismatch', function() { shouldThrow(function() { Handlebars.template({ - main: true, + main: {}, compiler: [Handlebars.COMPILER_REVISION + 1] }); }, Error, /Template was precompiled with a newer version of Handlebars than the current runtime/); shouldThrow(function() { Handlebars.template({ - main: true, + main: {}, compiler: [Handlebars.COMPILER_REVISION - 1] }); }, Error, /Template was precompiled with an older version of Handlebars than the current runtime/); shouldThrow(function() { Handlebars.template({ - main: true + main: {} }); }, Error, /Template was precompiled with an older version of Handlebars than the current runtime/); }); diff --git a/spec/tokenizer.js b/spec/tokenizer.js index f170704..dc077ce 100644 --- a/spec/tokenizer.js +++ b/spec/tokenizer.js @@ -241,6 +241,15 @@ describe('Tokenizer', function() { shouldMatchTokens(result, ['OPEN_BLOCK', 'ID', 'CLOSE', 'CONTENT', 'OPEN_ENDBLOCK', 'ID', 'CLOSE']); }); + it('tokenizes directives', function() { + shouldMatchTokens( + tokenize('{{#*foo}}content{{/foo}}'), + ['OPEN_BLOCK', 'ID', 'CLOSE', 'CONTENT', 'OPEN_ENDBLOCK', 'ID', 'CLOSE']); + shouldMatchTokens( + tokenize('{{*foo}}'), + ['OPEN', 'ID', 'CLOSE']); + }); + it('tokenizes inverse sections as "INVERSE"', function() { shouldMatchTokens(tokenize('{{^}}'), ['INVERSE']); shouldMatchTokens(tokenize('{{else}}'), ['INVERSE']); diff --git a/spec/visitor.js b/spec/visitor.js index 3e2d523..d3fb795 100644 --- a/spec/visitor.js +++ b/spec/visitor.js @@ -9,6 +9,8 @@ describe('Visitor', function() { var visitor = new Handlebars.Visitor(); visitor.accept(Handlebars.parse('{{foo}}{{#foo (bar 1 "1" true undefined null) foo=@data}}{{!comment}}{{> bar }} {{/foo}}')); visitor.accept(Handlebars.parse('{{#> bar }} {{/bar}}')); + visitor.accept(Handlebars.parse('{{#* bar }} {{/bar}}')); + visitor.accept(Handlebars.parse('{{* bar }}')); }); it('should traverse to stubs', function() { |