Code coverage report for spec/builtins.js

Statements: 20% (27 / 135)      Branches: 0% (0 / 4)      Functions: 13.89% (5 / 36)      Lines: 20.93% (27 / 129)      Ignored: none     

All files » spec/ » builtins.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233  3 3 3                                         3                         3 3       3       3           3 3           3                 3                               3                   3                   3                     3                   3                   3                   3                   3                   3                 3                         3               3                               3 3                 3                      
/*global CompilerContext, shouldCompileTo, shouldThrow, compileWithPartials, handlebarsEnv */
describe('builtin helpers', function() {
  describe('#if', function() {
    it("if", function() {
      var string   = "{{#if goodbye}}GOODBYE {{/if}}cruel {{world}}!";
      shouldCompileTo(string, {goodbye: true, world: "world"}, "GOODBYE cruel world!",
                      "if with boolean argument shows the contents when true");
      shouldCompileTo(string, {goodbye: "dummy", world: "world"}, "GOODBYE cruel world!",
                      "if with string argument shows the contents");
      shouldCompileTo(string, {goodbye: false, world: "world"}, "cruel world!",
                      "if with boolean argument does not show the contents when false");
      shouldCompileTo(string, {world: "world"}, "cruel world!",
                      "if with undefined does not show the contents");
      shouldCompileTo(string, {goodbye: ['foo'], world: "world"}, "GOODBYE cruel world!",
                      "if with non-empty array shows the contents");
      shouldCompileTo(string, {goodbye: [], world: "world"}, "cruel world!",
                      "if with empty array does not show the contents");
      shouldCompileTo(string, {goodbye: 0, world: "world"}, "cruel world!",
                      "if with zero does not show the contents");
      shouldCompileTo("{{#if goodbye includeZero=true}}GOODBYE {{/if}}cruel {{world}}!",
                      {goodbye: 0, world: "world"}, "GOODBYE cruel world!",
                      "if with zero does not show the contents");
    });
 
    it("if with function argument", function() {
      var string   = "{{#if goodbye}}GOODBYE {{/if}}cruel {{world}}!";
      shouldCompileTo(string, {goodbye: function() {return true;}, world: "world"}, "GOODBYE cruel world!",
                      "if with function shows the contents when function returns true");
      shouldCompileTo(string, {goodbye: function() {return this.world;}, world: "world"}, "GOODBYE cruel world!",
                      "if with function shows the contents when function returns string");
      shouldCompileTo(string, {goodbye: function() {return false;}, world: "world"}, "cruel world!",
                      "if with function does not show the contents when returns false");
      shouldCompileTo(string, {goodbye: function() {return this.foo;}, world: "world"}, "cruel world!",
                      "if with function does not show the contents when returns undefined");
    });
  });
 
  describe('#with', function() {
    it("with", function() {
      var string = "{{#with person}}{{first}} {{last}}{{/with}}";
      shouldCompileTo(string, {person: {first: "Alan", last: "Johnson"}}, "Alan Johnson");
    });
    it("with with function argument", function() {
      var string = "{{#with person}}{{first}} {{last}}{{/with}}";
      shouldCompileTo(string, {person: function() { return {first: "Alan", last: "Johnson"};}}, "Alan Johnson");
    });
    it("with with else", function() {
      var string = "{{#with person}}Person is present{{else}}Person is not present{{/with}}";
      shouldCompileTo(string, {}, "Person is not present");
    });
  });
 
  describe('#each', function() {
    beforeEach(function() {
      handlebarsEnv.registerHelper('detectDataInsideEach', function(options) {
        return options.data && options.data.exclaim;
      });
    });
 
    it("each", function() {
      var string   = "{{#each goodbyes}}{{text}}! {{/each}}cruel {{world}}!";
      var hash     = {goodbyes: [{text: "goodbye"}, {text: "Goodbye"}, {text: "GOODBYE"}], world: "world"};
      shouldCompileTo(string, hash, "goodbye! Goodbye! GOODBYE! cruel world!",
                      "each with array argument iterates over the contents when not empty");
      shouldCompileTo(string, {goodbyes: [], world: "world"}, "cruel world!",
                      "each with array argument ignores the contents when empty");
    });
 
    it("each with an object and @key", function() {
      var string   = "{{#each goodbyes}}{{@key}}. {{text}}! {{/each}}cruel {{world}}!";
      var hash     = {goodbyes: {"<b>#1</b>": {text: "goodbye"}, 2: {text: "GOODBYE"}}, world: "world"};
 
      // Object property iteration order is undefined according to ECMA spec,
      // so we need to check both possible orders
      // @see http://stackoverflow.com/questions/280713/elements-order-in-a-for-in-loop
      var actual = compileWithPartials(string, hash);
      var expected1 = "&lt;b&gt;#1&lt;/b&gt;. goodbye! 2. GOODBYE! cruel world!";
      var expected2 = "2. GOODBYE! &lt;b&gt;#1&lt;/b&gt;. goodbye! cruel world!";
 
      equals(actual === expected1 || actual === expected2, true, "each with object argument iterates over the contents when not empty");
      shouldCompileTo(string, {goodbyes: [], world: "world"}, "cruel world!",
                      "each with object argument ignores the contents when empty");
    });
 
    it("each with @index", function() {
      var string = "{{#each goodbyes}}{{@index}}. {{text}}! {{/each}}cruel {{world}}!";
      var hash   = {goodbyes: [{text: "goodbye"}, {text: "Goodbye"}, {text: "GOODBYE"}], world: "world"};
 
      var template = CompilerContext.compile(string);
      var result = template(hash);
 
      equal(result, "0. goodbye! 1. Goodbye! 2. GOODBYE! cruel world!", "The @index variable is used");
    });
 
    it("each with nested @index", function() {
      var string = "{{#each goodbyes}}{{@index}}. {{text}}! {{#each ../goodbyes}}{{@index}} {{/each}}After {{@index}} {{/each}}{{@index}}cruel {{world}}!";
      var hash   = {goodbyes: [{text: "goodbye"}, {text: "Goodbye"}, {text: "GOODBYE"}], world: "world"};
 
      var template = CompilerContext.compile(string);
      var result = template(hash);
 
      equal(result, "0. goodbye! 0 1 2 After 0 1. Goodbye! 0 1 2 After 1 2. GOODBYE! 0 1 2 After 2 cruel world!", "The @index variable is used");
    });
 
    it("each object with @index", function() {
      var string = "{{#each goodbyes}}{{@index}}. {{text}}! {{/each}}cruel {{world}}!";
      var hash   = {goodbyes: {'a': {text: "goodbye"}, b: {text: "Goodbye"}, c: {text: "GOODBYE"}}, world: "world"};
 
      var template = CompilerContext.compile(string);
      var result = template(hash);
 
      equal(result, "0. goodbye! 1. Goodbye! 2. GOODBYE! cruel world!", "The @index variable is used");
    });
 
 
    it("each with @first", function() {
      var string = "{{#each goodbyes}}{{#if @first}}{{text}}! {{/if}}{{/each}}cruel {{world}}!";
      var hash   = {goodbyes: [{text: "goodbye"}, {text: "Goodbye"}, {text: "GOODBYE"}], world: "world"};
 
      var template = CompilerContext.compile(string);
      var result = template(hash);
 
      equal(result, "goodbye! cruel world!", "The @first variable is used");
    });
 
    it("each with nested @first", function() {
      var string = "{{#each goodbyes}}({{#if @first}}{{text}}! {{/if}}{{#each ../goodbyes}}{{#if @first}}{{text}}!{{/if}}{{/each}}{{#if @first}} {{text}}!{{/if}}) {{/each}}cruel {{world}}!";
      var hash   = {goodbyes: [{text: "goodbye"}, {text: "Goodbye"}, {text: "GOODBYE"}], world: "world"};
 
      var template = CompilerContext.compile(string);
      var result = template(hash);
 
      equal(result, "(goodbye! goodbye! goodbye!) (goodbye!) (goodbye!) cruel world!", "The @first variable is used");
    });
 
    it("each object with @first", function() {
      var string = "{{#each goodbyes}}{{#if @first}}{{text}}! {{/if}}{{/each}}cruel {{world}}!";
      var hash   = {goodbyes: {'foo': {text: "goodbye"}, bar: {text: "Goodbye"}}, world: "world"};
 
      var template = CompilerContext.compile(string);
      var result = template(hash);
 
      equal(result, "goodbye! cruel world!", "The @first variable is used");
    });
 
    it("each with @last", function() {
      var string = "{{#each goodbyes}}{{#if @last}}{{text}}! {{/if}}{{/each}}cruel {{world}}!";
      var hash   = {goodbyes: [{text: "goodbye"}, {text: "Goodbye"}, {text: "GOODBYE"}], world: "world"};
 
      var template = CompilerContext.compile(string);
      var result = template(hash);
 
      equal(result, "GOODBYE! cruel world!", "The @last variable is used");
    });
 
    it("each with nested @last", function() {
      var string = "{{#each goodbyes}}({{#if @last}}{{text}}! {{/if}}{{#each ../goodbyes}}{{#if @last}}{{text}}!{{/if}}{{/each}}{{#if @last}} {{text}}!{{/if}}) {{/each}}cruel {{world}}!";
      var hash   = {goodbyes: [{text: "goodbye"}, {text: "Goodbye"}, {text: "GOODBYE"}], world: "world"};
 
      var template = CompilerContext.compile(string);
      var result = template(hash);
 
      equal(result, "(GOODBYE!) (GOODBYE!) (GOODBYE! GOODBYE! GOODBYE!) cruel world!", "The @last variable is used");
    });
 
    it("each with function argument", function() {
      var string = "{{#each goodbyes}}{{text}}! {{/each}}cruel {{world}}!";
      var hash   = {goodbyes: function () { return [{text: "goodbye"}, {text: "Goodbye"}, {text: "GOODBYE"}];}, world: "world"};
      shouldCompileTo(string, hash, "goodbye! Goodbye! GOODBYE! cruel world!",
                "each with array function argument iterates over the contents when not empty");
      shouldCompileTo(string, {goodbyes: [], world: "world"}, "cruel world!",
                "each with array function argument ignores the contents when empty");
    });
 
    it("data passed to helpers", function() {
      var string = "{{#each letters}}{{this}}{{detectDataInsideEach}}{{/each}}";
      var hash = {letters: ['a', 'b', 'c']};
 
      var template = CompilerContext.compile(string);
      var result = template(hash, {
        data: {
          exclaim: '!'
        }
      });
      equal(result, 'a!b!c!', 'should output data');
    });
 
    it("each on implicit context", function() {
      shouldThrow(function() {
        var template = CompilerContext.compile("{{#each}}{{text}}! {{/each}}cruel world!");
        template({});
      }, handlebarsEnv.Exception, 'Must pass iterator to #each');
    });
  });
 
  it("#log", function() {
    var string = "{{log blah}}";
    var hash   = { blah: "whee" };
 
    var levelArg, logArg;
    handlebarsEnv.log = function(level, arg){
      levelArg = level;
      logArg = arg;
    };
 
    shouldCompileTo(string, hash, "", "log should not display");
    equals(1, levelArg, "should call log with 1");
    equals("whee", logArg, "should call log with 'whee'");
  });
 
 
  describe('#lookup', function() {
    it('should lookup arbitrary content', function() {
      var string = '{{#each goodbyes}}{{lookup ../data .}}{{/each}}',
          hash   = {goodbyes: [0, 1], data: ['foo', 'bar']};
 
      var template = CompilerContext.compile(string);
      var result = template(hash);
 
      equal(result, 'foobar');
    });
    it('should not fail on undefined value', function() {
      var string = '{{#each goodbyes}}{{lookup ../bar .}}{{/each}}',
          hash   = {goodbyes: [0, 1], data: ['foo', 'bar']};
 
      var template = CompilerContext.compile(string);
      var result = template(hash);
 
      equal(result, '');
    });
  });
});