describe('Visitor', function() { if (!Handlebars.Visitor || !Handlebars.print) { return; } it('should provide coverage', function() { // Simply run the thing and make sure it does not fail and that all of the // stub methods are executed 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}}')); }); it('should traverse to stubs', function() { var visitor = new Handlebars.Visitor(); visitor.StringLiteral = function(string) { equal(string.value, '2'); }; visitor.NumberLiteral = function(number) { equal(number.value, 1); }; visitor.BooleanLiteral = function(bool) { equal(bool.value, true); equal(this.parents.length, 3); equal(this.parents[0].type, 'SubExpression'); equal(this.parents[1].type, 'BlockStatement'); equal(this.parents[2].type, 'Program'); }; visitor.PathExpression = function(id) { equal(/(foo\.)?bar$/.test(id.original), true); }; visitor.ContentStatement = function(content) { equal(content.value, ' '); }; visitor.CommentStatement = function(comment) { equal(comment.value, 'comment'); }; visitor.accept(Handlebars.parse('{{#foo.bar (foo.bar 1 "2" true) foo=@foo.bar}}{{!comment}}{{> bar }} {{/foo.bar}}')); }); describe('mutating', function() { describe('fields', function() { it('should replace value', function() { var visitor = new Handlebars.Visitor(); visitor.mutating = true; visitor.StringLiteral = function(string) { return {type: 'NumberLiteral', value: 42, loc: string.loc}; }; var ast = Handlebars.parse('{{foo foo="foo"}}'); visitor.accept(ast); equals(Handlebars.print(ast), '{{ PATH:foo [] HASH{foo=NUMBER{42}} }}\n'); }); it('should treat undefined resonse as identity', function() { var visitor = new Handlebars.Visitor(); visitor.mutating = true; var ast = Handlebars.parse('{{foo foo=42}}'); visitor.accept(ast); equals(Handlebars.print(ast), '{{ PATH:foo [] HASH{foo=NUMBER{42}} }}\n'); }); it('should remove false responses', function() { var visitor = new Handlebars.Visitor(); visitor.mutating = true; visitor.Hash = function() { return false; }; var ast = Handlebars.parse('{{foo foo=42}}'); visitor.accept(ast); equals(Handlebars.print(ast), '{{ PATH:foo [] }}\n'); }); it('should throw when removing required values', function() { shouldThrow(function() { var visitor = new Handlebars.Visitor(); visitor.mutating = true; visitor.PathExpression = function() { return false; }; var ast = Handlebars.parse('{{foo 42}}'); visitor.accept(ast); }, Handlebars.Exception, 'MustacheStatement requires path'); }); it('should throw when returning non-node responses', function() { shouldThrow(function() { var visitor = new Handlebars.Visitor(); visitor.mutating = true; visitor.PathExpression = function() { return {}; }; var ast = Handlebars.parse('{{foo 42}}'); visitor.accept(ast); }, Handlebars.Exception, 'Unexpected node type "undefined" found when accepting path on MustacheStatement'); }); }); describe('arrays', function() { it('should replace value', function() { var visitor = new Handlebars.Visitor(); visitor.mutating = true; visitor.StringLiteral = function(string) { return {type: 'NumberLiteral', value: 42, loc: string.locInfo}; }; var ast = Handlebars.parse('{{foo "foo"}}'); visitor.accept(ast); equals(Handlebars.print(ast), '{{ PATH:foo [NUMBER{42}] }}\n'); }); it('should treat undefined resonse as identity', function() { var visitor = new Handlebars.Visitor(); visitor.mutating = true; var ast = Handlebars.parse('{{foo 42}}'); visitor.accept(ast); equals(Handlebars.print(ast), '{{ PATH:foo [NUMBER{42}] }}\n'); }); it('should remove false responses', function() { var visitor = new Handlebars.Visitor(); visitor.mutating = true; visitor.NumberLiteral = function() { return false; }; var ast = Handlebars.parse('{{foo 42}}'); visitor.accept(ast); equals(Handlebars.print(ast), '{{ PATH:foo [] }}\n'); }); }); }); });