summaryrefslogtreecommitdiffstats
path: root/spec/qunit_spec.js
diff options
context:
space:
mode:
Diffstat (limited to 'spec/qunit_spec.js')
-rw-r--r--spec/qunit_spec.js262
1 files changed, 201 insertions, 61 deletions
diff --git a/spec/qunit_spec.js b/spec/qunit_spec.js
index e144ba2..56cb687 100644
--- a/spec/qunit_spec.js
+++ b/spec/qunit_spec.js
@@ -6,19 +6,25 @@ Handlebars.registerHelper('helperMissing', function(helper, context) {
}
});
-var shouldCompileTo = function(string, hash, expected, message) {
- var template = Handlebars.compile(string);
- if(Object.prototype.toString.call(hash) === "[object Array]") {
- if(hash[1]) {
+var shouldCompileTo = function(string, hashOrArray, expected, message) {
+ var template = Handlebars.compile(string), ary;
+ if(Object.prototype.toString.call(hashOrArray) === "[object Array]") {
+ helpers = hashOrArray[1];
+
+ if(helpers) {
for(var prop in Handlebars.helpers) {
- hash[1][prop] = Handlebars.helpers[prop];
+ helpers[prop] = Handlebars.helpers[prop];
}
}
+
+ ary = [];
+ ary.push(hashOrArray[0]);
+ ary.push({ helpers: hashOrArray[1], partials: hashOrArray[2] });
} else {
- hash = [hash];
+ ary = [hashOrArray];
}
- result = template.apply(this, hash)
+ result = template.apply(this, ary);
equal(result, expected, "'" + expected + "' should === '" + result + "': " + message);
};
@@ -72,7 +78,8 @@ test("newlines", function() {
test("escaping text", function() {
shouldCompileTo("Awesome's", {}, "Awesome's", "text is escaped so that it doesn't get caught on single quotes");
shouldCompileTo("Awesome\\", {}, "Awesome\\", "text is escaped so that the closing quote can't be ignored");
- shouldCompileTo("Awesome\\ foo", {}, "Awesome\\ foo", "text is escaped so that it doesn't mess up backslashes");
+ shouldCompileTo("Awesome\\\\ foo", {}, "Awesome\\\\ foo", "text is escaped so that it doesn't mess up backslashes");
+ shouldCompileTo("Awesome {{foo}}", {foo: '\\'}, "Awesome \\", "text is escaped so that it doesn't mess up backslashes");
shouldCompileTo(' " " ', {}, ' " " ', "double quotes never produce invalid javascript");
});
@@ -80,12 +87,12 @@ test("escaping expressions", function() {
shouldCompileTo("{{{awesome}}}", {awesome: "&\"\\<>"}, '&\"\\<>',
"expressions with 3 handlebars aren't escaped");
- shouldCompileTo("{{awesome}}", {awesome: "&\"\\<>"}, '&amp;\"\\&lt;&gt;',
- "by default expressions should be escaped");
-
shouldCompileTo("{{&awesome}}", {awesome: "&\"\\<>"}, '&\"\\<>',
"expressions with {{& handlebars aren't escaped");
+ shouldCompileTo("{{awesome}}", {awesome: "&\"'`\\<>"}, '&amp;&quot;&#x27;&#x60;\\&lt;&gt;',
+ "by default expressions should be escaped");
+
});
test("functions returning safestrings shouldn't be escaped", function() {
@@ -106,6 +113,10 @@ test("functions with context argument", function() {
"Frank", "functions are called with context arguments");
});
+test("paths with hyphens", function() {
+ shouldCompileTo("{{foo-bar}}", {"foo-bar": "baz"}, "baz", "Paths can contain hyphens (-)");
+});
+
test("nested paths", function() {
shouldCompileTo("Goodbye {{alan/expression}} world!", {alan: {expression: "beautiful"}},
"Goodbye beautiful world!", "Nested paths access nested objects");
@@ -128,7 +139,7 @@ test("--- TODO --- bad idea nested paths", function() {
shouldCompileTo(string, hash, "world world world ", "Same context (.) is ignored in paths");
});
-test("that current context path ({{.}}) doesn't hit fallback", function() {
+test("that current context path ({{.}}) doesn't hit helpers", function() {
shouldCompileTo("test: {{.}}", [null, {helper: "awesome"}], "test: ");
});
@@ -220,16 +231,16 @@ test("block with complex lookup", function() {
test("helper with complex lookup", function() {
var string = "{{#goodbyes}}{{{link ../prefix}}}{{/goodbyes}}"
var hash = {prefix: "/root", goodbyes: [{text: "Goodbye", url: "goodbye"}]};
- var fallback = {link: function(prefix) {
+ var helpers = {link: function(prefix) {
return "<a href='" + prefix + "/" + this.url + "'>" + this.text + "</a>"
}};
- shouldCompileTo(string, [hash, fallback], "<a href='/root/goodbye'>Goodbye</a>")
+ shouldCompileTo(string, [hash, helpers], "<a href='/root/goodbye'>Goodbye</a>")
});
test("helper block with complex lookup expression", function() {
var string = "{{#goodbyes}}{{../name}}{{/goodbyes}}"
var hash = {name: "Alan"};
- var fallback = {goodbyes: function(fn) {
+ var helpers = {goodbyes: function(fn) {
var out = "";
var byes = ["Goodbye", "goodbye", "GOODBYE"];
for (var i = 0,j = byes.length; i < j; i++) {
@@ -237,16 +248,16 @@ test("helper block with complex lookup expression", function() {
}
return out;
}};
- shouldCompileTo(string, [hash, fallback], "Goodbye Alan! goodbye Alan! GOODBYE Alan! ");
+ shouldCompileTo(string, [hash, helpers], "Goodbye Alan! goodbye Alan! GOODBYE Alan! ");
});
test("helper with complex lookup and nested template", function() {
var string = "{{#goodbyes}}{{#link ../prefix}}{{text}}{{/link}}{{/goodbyes}}";
var hash = {prefix: '/root', goodbyes: [{text: "Goodbye", url: "goodbye"}]};
- var fallback = {link: function (prefix, fn) {
+ var helpers = {link: function (prefix, fn) {
return "<a href='" + prefix + "/" + this.url + "'>" + fn(this) + "</a>";
}};
- shouldCompileTo(string, [hash, fallback], "<a href='/root/goodbye'>Goodbye</a>")
+ shouldCompileTo(string, [hash, helpers], "<a href='/root/goodbye'>Goodbye</a>")
});
test("block with deep nested complex lookup", function() {
@@ -359,24 +370,24 @@ test("block helper inverted sections", function() {
// so we should see the output of both
shouldCompileTo(string, hash, "<ul><li>Alan</li><li>Yehuda</li></ul>", "an inverse wrapper is passed in as a new context");
shouldCompileTo(string, empty, "<p><em>Nobody's here</em></p>", "an inverse wrapper can be optionally called");
- shouldCompileTo(messageString, rootMessage, "<p>Nobody's here</p>", "the context of an inverse is the parent of the block");
+ shouldCompileTo(messageString, rootMessage, "<p>Nobody&#x27;s here</p>", "the context of an inverse is the parent of the block");
});
-module("fallback hash");
+module("helpers hash");
-test("providing a fallback hash", function() {
+test("providing a helpers hash", function() {
shouldCompileTo("Goodbye {{cruel}} {{world}}!", [{cruel: "cruel"}, {world: "world"}], "Goodbye cruel world!",
- "Fallback hash is available");
+ "helpers hash is available");
shouldCompileTo("Goodbye {{#iter}}{{cruel}} {{world}}{{/iter}}!", [{iter: [{cruel: "cruel"}]}, {world: "world"}],
- "Goodbye cruel world!", "Fallback hash is available inside other blocks");
+ "Goodbye cruel world!", "helpers hash is available inside other blocks");
});
test("in cases of conflict, the explicit hash wins", function() {
});
-test("the fallback hash is available is nested contexts", function() {
+test("the helpers hash is available is nested contexts", function() {
});
@@ -423,10 +434,15 @@ test("GH-14: a partial preceding a selector", function() {
module("String literal parameters");
test("simple literals work", function() {
- var string = 'Message: {{hello "world"}}';
+ var string = 'Message: {{hello "world" 12 true false}}';
var hash = {};
- var fallback = {hello: function(param) { return "Hello " + param; }}
- shouldCompileTo(string, [hash, fallback], "Message: Hello world", "template with a simple String literal");
+ var helpers = {hello: function(param, times, bool1, bool2) {
+ if(typeof times !== 'number') { times = "NaN"; }
+ if(typeof bool1 !== 'boolean') { bool1 = "NaB"; }
+ if(typeof bool2 !== 'boolean') { bool2 = "NaB"; }
+ return "Hello " + param + " " + times + " times: " + bool1 + " " + bool2;
+ }}
+ shouldCompileTo(string, [hash, helpers], "Message: Hello world 12 times: true false", "template with a simple String literal");
});
test("using a quote in the middle of a parameter raises an error", function() {
@@ -437,17 +453,17 @@ test("using a quote in the middle of a parameter raises an error", function() {
});
test("escaping a String is possible", function(){
- var string = 'Message: {{hello "\\"world\\""}}';
+ var string = 'Message: {{{hello "\\"world\\""}}}';
var hash = {}
- var fallback = {hello: function(param) { return "Hello " + param; }}
- shouldCompileTo(string, [hash, fallback], "Message: Hello \"world\"", "template with an escaped String literal");
+ var helpers = {hello: function(param) { return "Hello " + param; }}
+ shouldCompileTo(string, [hash, helpers], "Message: Hello \"world\"", "template with an escaped String literal");
});
test("it works with ' marks", function() {
- var string = 'Message: {{hello "Alan\'s world"}}';
+ var string = 'Message: {{{hello "Alan\'s world"}}}';
var hash = {}
- var fallback = {hello: function(param) { return "Hello " + param; }}
- shouldCompileTo(string, [hash, fallback], "Message: Hello Alan's world", "template with a ' mark");
+ var helpers = {hello: function(param) { return "Hello " + param; }}
+ shouldCompileTo(string, [hash, helpers], "Message: Hello Alan's world", "template with a ' mark");
});
module("multiple parameters");
@@ -455,17 +471,17 @@ module("multiple parameters");
test("simple multi-params work", function() {
var string = 'Message: {{goodbye cruel world}}';
var hash = {cruel: "cruel", world: "world"}
- var fallback = {goodbye: function(cruel, world) { return "Goodbye " + cruel + " " + world; }}
- shouldCompileTo(string, [hash, fallback], "Message: Goodbye cruel world", "regular helpers with multiple params");
+ var helpers = {goodbye: function(cruel, world) { return "Goodbye " + cruel + " " + world; }}
+ shouldCompileTo(string, [hash, helpers], "Message: Goodbye cruel world", "regular helpers with multiple params");
});
test("block multi-params work", function() {
var string = 'Message: {{#goodbye cruel world}}{{greeting}} {{adj}} {{noun}}{{/goodbye}}';
var hash = {cruel: "cruel", world: "world"}
- var fallback = {goodbye: function(cruel, world, fn) {
+ var helpers = {goodbye: function(cruel, world, fn) {
return fn({greeting: "Goodbye", adj: cruel, noun: world});
}}
- shouldCompileTo(string, [hash, fallback], "Message: Goodbye cruel world", "block helpers with multiple params");
+ shouldCompileTo(string, [hash, helpers], "Message: Goodbye cruel world", "block helpers with multiple params");
})
module("safestring");
@@ -523,7 +539,7 @@ test("overriding property lookup", function() {
test("passing in data to a compiled function that expects data - works with helpers", function() {
- var template = Handlebars.compile("{{hello}}", true);
+ var template = Handlebars.compile("{{hello}}", {data: true});
var helpers = {
hello: function(options) {
@@ -531,12 +547,12 @@ test("passing in data to a compiled function that expects data - works with help
}
};
- var result = template({noun: "cat"}, helpers, null, {adjective: "happy"});
+ var result = template({noun: "cat"}, {helpers: helpers, data: {adjective: "happy"}});
equals("happy cat", result);
});
test("passing in data to a compiled function that expects data - works with helpers and parameters", function() {
- var template = Handlebars.compile("{{hello world}}", true);
+ var template = Handlebars.compile("{{hello world}}", {data: true});
var helpers = {
hello: function(noun, options) {
@@ -544,12 +560,12 @@ test("passing in data to a compiled function that expects data - works with help
}
};
- var result = template({exclaim: true, world: "world"}, helpers, null, {adjective: "happy"});
+ var result = template({exclaim: true, world: "world"}, {helpers: helpers, data: {adjective: "happy"}});
equals("happy world!", result);
});
test("passing in data to a compiled function that expects data - works with block helpers", function() {
- var template = Handlebars.compile("{{#hello}}{{world}}{{/hello}}", true);
+ var template = Handlebars.compile("{{#hello}}{{world}}{{/hello}}", {data: true});
var helpers = {
hello: function(fn) {
@@ -560,12 +576,12 @@ test("passing in data to a compiled function that expects data - works with bloc
}
};
- var result = template({exclaim: true}, helpers, null, {adjective: "happy"});
+ var result = template({exclaim: true}, {helpers: helpers, data: {adjective: "happy"}});
equals("happy world!", result);
});
test("passing in data to a compiled function that expects data - works with block helpers that use ..", function() {
- var template = Handlebars.compile("{{#hello}}{{world ../zomg}}{{/hello}}", true);
+ var template = Handlebars.compile("{{#hello}}{{world ../zomg}}{{/hello}}", {data: true});
var helpers = {
hello: function(fn) {
@@ -576,12 +592,12 @@ test("passing in data to a compiled function that expects data - works with bloc
}
};
- var result = template({exclaim: true, zomg: "world"}, helpers, null, {adjective: "happy"});
+ var result = template({exclaim: true, zomg: "world"}, {helpers: helpers, data: {adjective: "happy"}});
equals("happy world?", result);
});
test("passing in data to a compiled function that expects data - data is passed to with block helpers where children use ..", function() {
- var template = Handlebars.compile("{{#hello}}{{world ../zomg}}{{/hello}}", true);
+ var template = Handlebars.compile("{{#hello}}{{world ../zomg}}{{/hello}}", {data: true});
var helpers = {
hello: function(fn, inverse) {
@@ -592,40 +608,40 @@ test("passing in data to a compiled function that expects data - data is passed
}
};
- var result = template({exclaim: true, zomg: "world"}, helpers, null, {adjective: "happy", accessData: "#win"});
+ var result = template({exclaim: true, zomg: "world"}, {helpers: helpers, data: {adjective: "happy", accessData: "#win"}});
equals("#win happy world?", result);
});
test("you can override inherited data when invoking a helper", function() {
- var template = Handlebars.compile("{{#hello}}{{world zomg}}{{/hello}}", true);
+ var template = Handlebars.compile("{{#hello}}{{world zomg}}{{/hello}}", {data: true});
var helpers = {
hello: function(fn) {
- return fn({exclaim: "?", zomg: "world"}, null, null, {adjective: "sad"});
+ return fn({exclaim: "?", zomg: "world"}, { data: {adjective: "sad"} });
},
world: function(thing, options) {
return options.data.adjective + " " + thing + (this.exclaim || "");
}
};
- var result = template({exclaim: true, zomg: "planet"}, helpers, null, {adjective: "happy"});
+ var result = template({exclaim: true, zomg: "planet"}, {helpers: helpers, data: {adjective: "happy"}});
equals("sad world?", result);
});
test("you can override inherited data when invoking a helper with depth", function() {
- var template = Handlebars.compile("{{#hello}}{{world ../zomg}}{{/hello}}", true);
+ var template = Handlebars.compile("{{#hello}}{{world ../zomg}}{{/hello}}", {data: true});
var helpers = {
hello: function(fn) {
- return fn({exclaim: "?"}, null, null, {adjective: "sad"});
+ return fn({exclaim: "?"}, { data: {adjective: "sad"} });
},
world: function(thing, options) {
return options.data.adjective + " " + thing + (this.exclaim || "");
}
};
- var result = template({exclaim: true, zomg: "world"}, helpers, null, {adjective: "happy"});
+ var result = template({exclaim: true, zomg: "world"}, {helpers: helpers, data: {adjective: "happy"}});
equals("sad world?", result);
});
@@ -647,7 +663,7 @@ test("helpers take precedence over same-named context properties", function() {
world: "world"
};
- var result = template(context, helpers);
+ var result = template(context, {helpers: helpers});
equals(result, "GOODBYE cruel WORLD");
});
@@ -669,34 +685,158 @@ test("helpers take precedence over same-named context properties", function() {
world: "world"
};
- var result = template(context, helpers);
+ var result = template(context, {helpers: helpers});
equals(result, "GOODBYE cruel WORLD");
});
test("helpers can take an optional hash", function() {
- var template = Handlebars.compile('{{goodbye cruel="CRUEL" world="WORLD"}}');
+ var template = Handlebars.compile('{{goodbye cruel="CRUEL" world="WORLD" times=12}}');
var helpers = {
goodbye: function(options) {
- return "GOODBYE " + options.hash.cruel + " " + options.hash.world;
+ return "GOODBYE " + options.hash.cruel + " " + options.hash.world + " " + options.hash.times + " TIMES";
}
};
var context = {};
- var result = template(context, helpers);
+ var result = template(context, {helpers: helpers});
+ equals(result, "GOODBYE CRUEL WORLD 12 TIMES");
+});
+
+test("helpers can take an optional hash with booleans", function() {
+ var helpers = {
+ goodbye: function(options) {
+ if (options.hash.print === true) {
+ return "GOODBYE " + options.hash.cruel + " " + options.hash.world;
+ } else if (options.hash.print === false) {
+ return "NOT PRINTING";
+ } else {
+ return "THIS SHOULD NOT HAPPEN";
+ }
+ }
+ };
+
+ var context = {};
+
+ var template = Handlebars.compile('{{goodbye cruel="CRUEL" world="WORLD" print=true}}');
+ var result = template(context, {helpers: helpers});
equals(result, "GOODBYE CRUEL WORLD");
+
+ var template = Handlebars.compile('{{goodbye cruel="CRUEL" world="WORLD" print=false}}');
+ var result = template(context, {helpers: helpers});
+ equals(result, "NOT PRINTING");
});
test("block helpers can take an optional hash", function() {
- var template = Handlebars.compile('{{#goodbye cruel="CRUEL"}}world{{/goodbye}}');
+ var template = Handlebars.compile('{{#goodbye cruel="CRUEL" times=12}}world{{/goodbye}}');
var helpers = {
goodbye: function(options) {
- return "GOODBYE " + options.hash.cruel + " " + options.fn(this);
+ return "GOODBYE " + options.hash.cruel + " " + options.fn(this) + " " + options.hash.times + " TIMES";
}
};
- var result = template({}, helpers);
+ var result = template({}, {helpers: helpers});
+ equals(result, "GOODBYE CRUEL world 12 TIMES");
+});
+
+test("block helpers can take an optional hash with booleans", function() {
+ var helpers = {
+ goodbye: function(options) {
+ if (options.hash.print === true) {
+ return "GOODBYE " + options.hash.cruel + " " + options.fn(this);
+ } else if (options.hash.print === false) {
+ return "NOT PRINTING";
+ } else {
+ return "THIS SHOULD NOT HAPPEN";
+ }
+ }
+ };
+
+ var template = Handlebars.compile('{{#goodbye cruel="CRUEL" print=true}}world{{/goodbye}}');
+ var result = template({}, {helpers: helpers});
equals(result, "GOODBYE CRUEL world");
+
+ var template = Handlebars.compile('{{#goodbye cruel="CRUEL" print=false}}world{{/goodbye}}');
+ var result = template({}, {helpers: helpers});
+ equals(result, "NOT PRINTING");
+});
+
+
+test("arguments to helpers can be retrieved from options hash in string form", function() {
+ var template = Handlebars.compile('{{wycats is.a slave.driver}}', {stringParams: true});
+
+ var helpers = {
+ wycats: function(passiveVoice, noun, options) {
+ return "HELP ME MY BOSS " + passiveVoice + ' ' + noun;
+ }
+ };
+
+ var result = template({}, {helpers: helpers});
+
+ equals(result, "HELP ME MY BOSS is.a slave.driver");
+});
+
+test("when using block form, arguments to helpers can be retrieved from options hash in string form", function() {
+ var template = Handlebars.compile('{{#wycats is.a slave.driver}}help :({{/wycats}}', {stringParams: true});
+
+ var helpers = {
+ wycats: function(passiveVoice, noun, options) {
+ return "HELP ME MY BOSS " + passiveVoice + ' ' +
+ noun + ': ' + options.fn(this);
+ }
+ };
+
+ var result = template({}, {helpers: helpers});
+
+ equals(result, "HELP ME MY BOSS is.a slave.driver: help :(");
});
+
+test("when inside a block in String mode, .. passes the appropriate context in the options hash", function() {
+ var template = Handlebars.compile('{{#with dale}}{{tomdale ../need dad.joke}}{{/with}}', {stringParams: true});
+
+ var helpers = {
+ tomdale: function(desire, noun, options) {
+ return "STOP ME FROM READING HACKER NEWS I " +
+ options.contexts[0][desire] + " " + noun;
+ },
+
+ "with": function(context, options) {
+ return options.fn(options.contexts[0][context]);
+ }
+ };
+
+ var result = template({
+ dale: {},
+
+ need: 'need-a'
+ }, {helpers: helpers});
+
+ equals(result, "STOP ME FROM READING HACKER NEWS I need-a dad.joke");
+});
+
+test("when inside a block in String mode, .. passes the appropriate context in the options hash to a block helper", function() {
+ var template = Handlebars.compile('{{#with dale}}{{#tomdale ../need dad.joke}}wot{{/tomdale}}{{/with}}', {stringParams: true});
+
+ var helpers = {
+ tomdale: function(desire, noun, options) {
+ return "STOP ME FROM READING HACKER NEWS I " +
+ options.contexts[0][desire] + " " + noun + " " +
+ options.fn(this);
+ },
+
+ "with": function(context, options) {
+ return options.fn(options.contexts[0][context]);
+ }
+ };
+
+ var result = template({
+ dale: {},
+
+ need: 'need-a'
+ }, {helpers: helpers});
+
+ equals(result, "STOP ME FROM READING HACKER NEWS I need-a dad.joke wot");
+});
+