var Exception = Handlebars.Exception; describe('strict', function() { describe('strict mode', function() { it('should error on missing property lookup', function() { shouldThrow( function() { var template = CompilerContext.compile('{{hello}}', { strict: true }); template({}); }, Exception, /"hello" not defined in/ ); }); it('should error on missing child', function() { var template = CompilerContext.compile('{{hello.bar}}', { strict: true }); equals(template({ hello: { bar: 'foo' } }), 'foo'); shouldThrow( function() { template({ hello: {} }); }, Exception, /"bar" not defined in/ ); }); it('should handle explicit undefined', function() { var template = CompilerContext.compile('{{hello.bar}}', { strict: true }); equals(template({ hello: { bar: undefined } }), ''); }); it('should error on missing property lookup in known helpers mode', function() { shouldThrow( function() { var template = CompilerContext.compile('{{hello}}', { strict: true, knownHelpersOnly: true }); template({}); }, Exception, /"hello" not defined in/ ); }); it('should error on missing context', function() { shouldThrow(function() { var template = CompilerContext.compile('{{hello}}', { strict: true }); template(); }, Error); }); it('should error on missing data lookup', function() { var template = CompilerContext.compile('{{@hello}}', { strict: true }); equals(template(undefined, { data: { hello: 'foo' } }), 'foo'); shouldThrow(function() { template(); }, Error); }); it('should not run helperMissing for helper calls', function() { shouldThrow( function() { var template = CompilerContext.compile('{{hello foo}}', { strict: true }); template({ foo: true }); }, Exception, /"hello" not defined in/ ); shouldThrow( function() { var template = CompilerContext.compile('{{#hello foo}}{{/hello}}', { strict: true }); template({ foo: true }); }, Exception, /"hello" not defined in/ ); }); it('should throw on ambiguous blocks', function() { shouldThrow( function() { var template = CompilerContext.compile('{{#hello}}{{/hello}}', { strict: true }); template({}); }, Exception, /"hello" not defined in/ ); shouldThrow( function() { var template = CompilerContext.compile('{{^hello}}{{/hello}}', { strict: true }); template({}); }, Exception, /"hello" not defined in/ ); shouldThrow( function() { var template = CompilerContext.compile( '{{#hello.bar}}{{/hello.bar}}', { strict: true } ); template({ hello: {} }); }, Exception, /"bar" not defined in/ ); }); it('should allow undefined parameters when passed to helpers', function() { var template = CompilerContext.compile( '{{#unless foo}}success{{/unless}}', { strict: true } ); equals(template({}), 'success'); }); it('should allow undefined hash when passed to helpers', function() { var template = CompilerContext.compile('{{helper value=@foo}}', { strict: true }); var helpers = { helper: function(options) { equals('value' in options.hash, true); equals(options.hash.value, undefined); return 'success'; } }; equals(template({}, { helpers: helpers }), 'success'); }); it('should show error location on missing property lookup', function() { shouldThrow( function() { var template = CompilerContext.compile('\n\n\n {{hello}}', { strict: true }); template({}); }, Exception, '"hello" not defined in [object Object] - 4:5' ); }); it('should error contains correct location properties on missing property lookup', function() { try { var template = CompilerContext.compile('\n\n\n {{hello}}', { strict: true }); template({}); } catch (error) { equals(error.lineNumber, 4); equals(error.endLineNumber, 4); equals(error.column, 5); equals(error.endColumn, 10); } }); }); describe('assume objects', function() { it('should ignore missing property', function() { var template = CompilerContext.compile('{{hello}}', { assumeObjects: true }); equal(template({}), ''); }); it('should ignore missing child', function() { var template = CompilerContext.compile('{{hello.bar}}', { assumeObjects: true }); equal(template({ hello: {} }), ''); }); it('should error on missing object', function() { shouldThrow(function() { var template = CompilerContext.compile('{{hello.bar}}', { assumeObjects: true }); template({}); }, Error); }); it('should error on missing context', function() { shouldThrow(function() { var template = CompilerContext.compile('{{hello}}', { assumeObjects: true }); template(); }, Error); }); it('should error on missing data lookup', function() { shouldThrow(function() { var template = CompilerContext.compile('{{@hello.bar}}', { assumeObjects: true }); template(); }, Error); }); it('should execute blockHelperMissing', function() { var template = CompilerContext.compile('{{^hello}}foo{{/hello}}', { assumeObjects: true }); equals(template({}), 'foo'); }); }); });