templz
Version:
Mustache-inspired template engine working with strings and elements
1,094 lines (969 loc) • 44.7 kB
JavaScript
/*!
* Templz test units
*
* Open index.html in a browser to test Templz in a user agent environment
*
* To test Templz in node.js, just type
*
* mocha
*/
(function(root, tests) {
if (typeof define === "function" && define.amd)
define(["expect", "templz"], tests);
else if (typeof exports === "object")
tests(require("../util/expect.js"), require("../templz.js"));
else tests(root.expect, root.Templz);
})(this, function(expect, Templz) {
// Strict mode interferes with some tests
// "use strict";
describe("String templates - interpolation", function() {
it("No Interpolation - Tag-free templates should render as-is.", function() {
var data = {},
template = Templz.compile("Hello from {Templz}!\n");
expect(template.render(data)).to.be("Hello from {Templz}!\n");
});
it("Basic Interpolation - Unadorned tags should interpolate content into the template.", function() {
var data = {
subject: "world"
},
template = Templz.compile("Hello, {{subject}}!\n");
expect(template.render(data)).to.be("Hello, world!\n");
});
it("HTML Escaping - Basic interpolation should be HTML escaped.", function() {
var data = {
forbidden: "& \" < >"
},
template = Templz.compile("These characters should be HTML escaped: {{forbidden}}\n");
expect(template.render(data)).to.be("These characters should be HTML escaped: & " < >\n");
});
it("Triple curly braces - Triple curly braces should interpolate without HTML escaping.", function() {
var data = {
forbidden: "& \" < >"
},
template = Templz.compile("These characters should not be HTML escaped: {{{forbidden}}}\n");
expect(template.render(data)).to.be("These characters should not be HTML escaped: & \" < >\n");
});
it("Ampersand - Ampersand should interpolate without HTML escaping.", function() {
var data = {
forbidden: "& \" < >"
},
template = Templz.compile("These characters should not be HTML escaped: {{&forbidden}}\n");
expect(template.render(data)).to.be("These characters should not be HTML escaped: & \" < >\n");
});
it("Basic Integer Interpolation - Integers should interpolate seamlessly.", function() {
var data = {
mph: 85
},
template = Templz.compile("\"{{mph}} miles an hour!\"");
expect(template.render(data)).to.be("\"85 miles an hour!\"");
});
it("Triple curly braces Integer Interpolation - Integers should interpolate seamlessly.", function() {
var data = {
mph: 85
},
template = Templz.compile("\"{{{mph}}} miles an hour!\"");
expect(template.render(data)).to.be("\"85 miles an hour!\"");
});
it("Ampersand Integer Interpolation - Integers should interpolate seamlessly.", function() {
var data = {
mph: 85
},
template = Templz.compile("\"{{&mph}} miles an hour!\"");
expect(template.render(data)).to.be("\"85 miles an hour!\"");
});
it("Basic Decimal Interpolation - Decimals should interpolate seamlessly with proper significance.", function() {
var data = {
power: 1.21
},
template = Templz.compile("\"{{power}} jiggawatts!\"");
expect(template.render(data)).to.be("\"1.21 jiggawatts!\"");
});
it("Triple curly braces Decimal Interpolation - Decimals should interpolate seamlessly with proper significance.", function() {
var data = {
power: 1.21
},
template = Templz.compile("\"{{{power}}} jiggawatts!\"");
expect(template.render(data)).to.be("\"1.21 jiggawatts!\"");
});
it("Ampersand Decimal Interpolation - Decimals should interpolate seamlessly with proper significance.", function() {
var data = {
power: 1.21
},
template = Templz.compile("\"{{&power}} jiggawatts!\"");
expect(template.render(data)).to.be("\"1.21 jiggawatts!\"");
});
it("Basic Context Miss Interpolation - Failed context lookups should default to empty strings.", function() {
var data = {},
template = Templz.compile("I ({{cannot}}) be seen!");
expect(template.render(data)).to.be("I () be seen!");
});
it("Triple curly braces Context Miss Interpolation - Failed context lookups should default to empty strings.", function() {
var data = {},
template = Templz.compile("I ({{{cannot}}}) be seen!");
expect(template.render(data)).to.be("I () be seen!");
});
it("Ampersand Context Miss Interpolation - Failed context lookups should default to empty strings.", function() {
var data = {},
template = Templz.compile("I ({{&cannot}}) be seen!");
expect(template.render(data)).to.be("I () be seen!");
});
it("Dotted Names - Basic Interpolation - Dotted names should be considered a form of shorthand for sections.", function() {
var data = {
person: {
name: "Joe"
}
},
template = Templz.compile("\"{{person.name}}\" == \"{{#person}}{{name}}{{/person}}\"");
expect(template.render(data)).to.be("\"Joe\" == \"Joe\"");
});
it("Dotted Names - Triple curly braces Interpolation - Dotted names should be considered a form of shorthand for sections.", function() {
var data = {
person: {
name: "Joe"
}
},
template = Templz.compile("\"{{{person.name}}}\" == \"{{#person}}{{{name}}}{{/person}}\"");
expect(template.render(data)).to.be("\"Joe\" == \"Joe\"");
});
it("Dotted Names - Ampersand Interpolation - Dotted names should be considered a form of shorthand for sections.", function() {
var data = {
person: {
name: "Joe"
}
},
template = Templz.compile("\"{{&person.name}}\" == \"{{#person}}{{&name}}{{/person}}\"");
expect(template.render(data)).to.be("\"Joe\" == \"Joe\"");
});
it("Dotted Names - Arbitrary Depth - Dotted names should be functional to any level of nesting.", function() {
var data = {
a: {
b: {
c: {
d: {
e: {
name: "Phil"
}
}
}
}
}
},
template = Templz.compile("\"{{a.b.c.d.e.name}}\" == \"Phil\"");
expect(template.render(data)).to.be("\"Phil\" == \"Phil\"");
});
it("Dotted Names - Broken Chains - Any falsey value prior to the last part of the name should yield ''.", function() {
var data = {
a: {}
},
template = Templz.compile("\"{{a.b.c}}\" == \"\"");
expect(template.render(data)).to.be("\"\" == \"\"");
});
it("Dotted Names - Broken Chain Resolution - Each part of a dotted name should resolve only against its parent.", function() {
var data = {
a: {
b: {}
},
c: {
name: "Jim"
}
},
template = Templz.compile("\"{{a.b.c.name}}\" == \"\"");
expect(template.render(data)).to.be("\"\" == \"\"");
});
it("Dotted Names - Initial Resolution - The first part of a dotted name should resolve as any other name.", function() {
var data = {
a: {
b: {
c: {
d: {
e: {
name: "Phil"
}
}
}
}
},
b: {
c: {
d: {
e: {
name: "Wrong"
}
}
}
}
},
template = Templz.compile("\"{{#a}}{{b.c.d.e.name}}{{/a}}\" == \"Phil\"");
expect(template.render(data)).to.be("\"Phil\" == \"Phil\"");
});
it("Interpolation - Surrounding Whitespace - Interpolation should not alter surrounding whitespace.", function() {
var data = {
string: "---"
},
template = Templz.compile("| {{string}} |");
expect(template.render(data)).to.be("| --- |");
});
it("Triple curly braces - Surrounding Whitespace - Interpolation should not alter surrounding whitespace.", function() {
var data = {
string: "---"
},
template = Templz.compile("| {{{string}}} |");
expect(template.render(data)).to.be("| --- |");
});
it("Ampersand - Surrounding Whitespace - Interpolation should not alter surrounding whitespace.", function() {
var data = {
string: "---"
},
template = Templz.compile("| {{&string}} |");
expect(template.render(data)).to.be("| --- |");
});
it("Interpolation - Standalone - Standalone interpolation should not alter surrounding whitespace.", function() {
var data = {
string: "---"
},
template = Templz.compile(" {{string}}\n");
expect(template.render(data)).to.be(" ---\n");
});
it("Triple curly braces - Standalone - Standalone interpolation should not alter surrounding whitespace.", function() {
var data = {
string: "---"
},
template = Templz.compile(" {{{string}}}\n");
expect(template.render(data)).to.be(" ---\n");
});
it("Ampersand - Standalone - Standalone interpolation should not alter surrounding whitespace.", function() {
var data = {
string: "---"
},
template = Templz.compile(" {{&string}}\n");
expect(template.render(data)).to.be(" ---\n");
});
it("Interpolation With Padding - Superfluous in-tag whitespace should be ignored.", function() {
var data = {
string: "---"
},
template = Templz.compile("|{{ string }}|");
expect(template.render(data)).to.be("|---|");
});
it("Triple curly braces With Padding - Superfluous in-tag whitespace should be ignored.", function() {
var data = {
string: "---"
},
template = Templz.compile("|{{{ string }}}|");
expect(template.render(data)).to.be("|---|");
});
it("Ampersand With Padding - Superfluous in-tag whitespace should be ignored.", function() {
var data = {
string: "---"
},
template = Templz.compile("|{{& string }}|");
expect(template.render(data)).to.be("|---|");
});
});
describe("String templates - comments", function() {
it("Inline - Comment blocks should be removed from the template.", function() {
var data = {},
template = Templz.compile("12345{{! Comment Block! }}67890");
expect(template.render(data)).to.be("1234567890");
});
it("Multiline - Multiline comments should be permitted.", function() {
var data = {},
template = Templz.compile("12345{{!\n This is a\n multi-line comment...\n}}67890\n");
expect(template.render(data)).to.be("1234567890\n");
});
it("Standalone - All standalone comment lines should be removed.", function() {
var data = {},
template = Templz.compile("Begin.\n{{! Comment Block! }}\nEnd.\n");
expect(template.render(data)).to.be("Begin.\nEnd.\n");
});
it("Indented Standalone - All standalone comment lines should be removed.", function() {
var data = {},
template = Templz.compile("Begin.\n {{! Indented Comment Block! }}\nEnd.\n");
expect(template.render(data)).to.be("Begin.\nEnd.\n");
});
it("Standalone Line Endings - \"\\r\\n\" should be considered a newline for standalone tags.", function() {
var data = {},
template = Templz.compile("|\r\n{{! Standalone Comment }}\r\n|");
expect(template.render(data)).to.be("|\r\n|");
});
it("Standalone Without Previous Line - Standalone tags should not require a newline to precede them.", function() {
var data = {},
template = Templz.compile(" {{! I'm Still Standalone }}\n!");
expect(template.render(data)).to.be("!");
});
it("Standalone Without Newline - Standalone tags should not require a newline to follow them.", function() {
var data = {},
template = Templz.compile("!\n {{! I'm Still Standalone }}");
expect(template.render(data)).to.be("!\n");
});
it("Multiline Standalone - All standalone comment lines should be removed.", function() {
var data = {},
template = Templz.compile("Begin.\n{{!\nSomething's going on here...\n}}\nEnd.\n");
expect(template.render(data)).to.be("Begin.\nEnd.\n");
});
it("Indented Multiline Standalone - All standalone comment lines should be removed.", function() {
var data = {},
template = Templz.compile("Begin.\n {{!\n Something's going on here...\n }}\nEnd.\n");
expect(template.render(data)).to.be("Begin.\nEnd.\n");
});
it("Indented Inline - Inline comments should not strip whitespace", function() {
var data = {},
template = Templz.compile(" 12 {{! 34 }}\n");
expect(template.render(data)).to.be(" 12 \n");
});
it("Surrounding Whitespace - Comment removal should preserve surrounding whitespace.", function() {
var data = {},
template = Templz.compile("12345 {{! Comment Block! }} 67890");
expect(template.render(data)).to.be("12345 67890");
});
});
describe("String templates - sections", function() {
it("Truthy - Truthy sections should have their contents rendered.", function() {
var data = {
"boolean": true
},
template = Templz.compile("\"{{#boolean}}This should be rendered.{{/boolean}}\"");
expect(template.render(data)).to.be("\"This should be rendered.\"");
});
it("Falsey - Falsey sections should have their contents omitted.", function() {
var data = {
"boolean": false
},
template = Templz.compile("\"{{#boolean}}This should not be rendered.{{/boolean}}\"");
expect(template.render(data)).to.be("\"\"");
});
it("Context - Objects and hashes should be pushed onto the context stack.", function() {
var data = {
context: {
name: "Joe"
}
},
template = Templz.compile("\"{{#context}}Hi {{name}}.{{/context}}\"");
expect(template.render(data)).to.be("\"Hi Joe.\"");
});
it("Deeply Nested Contexts - All elements on the context stack should be accessible.", function() {
var data = {
a: {
one: 1
},
b: {
two: 2
},
c: {
three: 3
},
d: {
four: 4
},
e: {
five: 5
}
},
template = Templz.compile("{{#a}}\n{{one}}\n{{#b}}\n{{one}}{{two}}{{one}}\n{{#c}}\n{{one}}{{two}}{{three}}{{two}}{{one}}\n{{#d}}\n{{one}}{{two}}{{three}}{{four}}{{three}}{{two}}{{one}}\n{{#e}}\n{{one}}{{two}}{{three}}{{four}}{{five}}{{four}}{{three}}{{two}}{{one}}\n{{/e}}\n{{one}}{{two}}{{three}}{{four}}{{three}}{{two}}{{one}}\n{{/d}}\n{{one}}{{two}}{{three}}{{two}}{{one}}\n{{/c}}\n{{one}}{{two}}{{one}}\n{{/b}}\n{{one}}\n{{/a}}\n");
expect(template.render(data)).to.be("1\n121\n12321\n1234321\n123454321\n1234321\n12321\n121\n1\n");
});
it("List - Lists should be iterated; list items should visit the context stack.", function() {
var data = {
list: [{
item: 1
},
{
item: 2
},
{
item: 3
}
]
},
template = Templz.compile("\"{{#list}}{{item}}{{/list}}\"");
expect(template.render(data)).to.be("\"123\"");
});
it("Empty List - Empty lists should behave like falsey values.", function() {
var data = {
list: []
},
template = Templz.compile("\"{{#list}}Yay lists!{{/list}}\"");
expect(template.render(data)).to.be("\"\"");
});
it("Doubled - Multiple sections per template should be permitted.", function() {
var data = {
two: "second",
bool: true
},
template = Templz.compile("{{#bool}}\n* first\n{{/bool}}\n* {{two}}\n{{#bool}}\n* third\n{{/bool}}\n");
expect(template.render(data)).to.be("* first\n* second\n* third\n");
});
it("Nested (Truthy) - Nested truthy sections should have their contents rendered.", function() {
var data = {
bool: true
},
template = Templz.compile("| A {{#bool}}B {{#bool}}C{{/bool}} D{{/bool}} E |");
expect(template.render(data)).to.be("| A B C D E |");
});
it("Nested (Falsey) - Nested falsey sections should be omitted.", function() {
var data = {
bool: false
},
template = Templz.compile("| A {{#bool}}B {{#bool}}C{{/bool}} D{{/bool}} E |");
expect(template.render(data)).to.be("| A E |");
});
it("Context Misses - Failed context lookups should be considered falsey.", function() {
var data = {},
template = Templz.compile("[{{#missing}}Found key 'missing'!{{/missing}}]");
expect(template.render(data)).to.be("[]");
});
it("Implicit Iterator - String - Implicit iterators should directly interpolate strings.", function() {
var data = {
list: ["a", "b", "c", "d", "e"]
},
template = Templz.compile("\"{{#list}}({{.}}){{/list}}\"");
expect(template.render(data)).to.be("\"(a)(b)(c)(d)(e)\"");
});
it("Implicit Iterator - Integer - Implicit iterators should cast integers to strings and interpolate.", function() {
var data = {
list: [1, 2, 3, 4, 5]
},
template = Templz.compile("\"{{#list}}({{.}}){{/list}}\"");
expect(template.render(data)).to.be("\"(1)(2)(3)(4)(5)\"");
});
it("Implicit Iterator - Decimal - Implicit iterators should cast decimals to strings and interpolate.", function() {
var data = {
list: [1.1, 2.2, 3.3, 4.4, 5.5]
},
template = Templz.compile("\"{{#list}}({{.}}){{/list}}\"");
expect(template.render(data)).to.be("\"(1.1)(2.2)(3.3)(4.4)(5.5)\"");
});
it("Dotted Names - Truthy - Dotted names should be valid for Section tags.", function() {
var data = {
a: {
b: {
c: true
}
}
},
template = Templz.compile("\"{{#a.b.c}}Here{{/a.b.c}}\" == \"Here\"");
expect(template.render(data)).to.be("\"Here\" == \"Here\"");
});
it("Dotted Names - Falsey - Dotted names should be valid for Section tags.", function() {
var data = {
a: {
b: {
c: false
}
}
},
template = Templz.compile("\"{{#a.b.c}}Here{{/a.b.c}}\" == \"\"");
expect(template.render(data)).to.be("\"\" == \"\"");
});
it("Dotted Names - Broken Chains - Dotted names that cannot be resolved should be considered falsey.", function() {
var data = {
a: {}
},
template = Templz.compile("\"{{#a.b.c}}Here{{/a.b.c}}\" == \"\"");
expect(template.render(data)).to.be("\"\" == \"\"");
});
it("Surrounding Whitespace - Sections should not alter surrounding whitespace.", function() {
var data = {
"boolean": true
},
template = Templz.compile(" | {{#boolean}}\t|\t{{/boolean}} | \n");
expect(template.render(data)).to.be(" | \t|\t | \n");
});
it("Internal Whitespace - Sections should not alter internal whitespace.", function() {
var data = {
"boolean": true
},
template = Templz.compile(" | {{#boolean}} {{! Important Whitespace }}\n {{/boolean}} | \n");
expect(template.render(data)).to.be(" | \n | \n");
});
it("Indented Inline Sections - Single-line sections should not alter surrounding whitespace.", function() {
var data = {
"boolean": true
},
template = Templz.compile(" {{#boolean}}YES{{/boolean}}\n {{#boolean}}GOOD{{/boolean}}\n");
expect(template.render(data)).to.be(" YES\n GOOD\n");
});
it("Standalone Lines - Standalone lines should be removed from the template.", function() {
var data = {
"boolean": true
},
template = Templz.compile("| This Is\n{{#boolean}}\n|\n{{/boolean}}\n| A Line\n");
expect(template.render(data)).to.be("| This Is\n|\n| A Line\n");
});
it("Indented Standalone Lines - Indented standalone lines should be removed from the template.", function() {
var data = {
"boolean": true
},
template = Templz.compile("| This Is\n {{#boolean}}\n|\n {{/boolean}}\n| A Line\n");
expect(template.render(data)).to.be("| This Is\n|\n| A Line\n");
});
it("Standalone Line Endings - \"\\r\\n\" should be considered a newline for standalone tags.", function() {
var data = {
"boolean": true
},
template = Templz.compile("|\r\n{{#boolean}}\r\n{{/boolean}}\r\n|");
expect(template.render(data)).to.be("|\r\n|");
});
it("Standalone Without Previous Line - Standalone tags should not require a newline to precede them.", function() {
var data = {
"boolean": true
},
template = Templz.compile(" {{#boolean}}\n#{{/boolean}}\n/");
expect(template.render(data)).to.be("#\n/");
});
it("Standalone Without Newline - Standalone tags should not require a newline to follow them.", function() {
var data = {
"boolean": true
},
template = Templz.compile("#{{#boolean}}\n/\n {{/boolean}}");
expect(template.render(data)).to.be("#\n/\n");
});
it("Padding - Superfluous in-tag whitespace should be ignored.", function() {
var data = {
"boolean": true
},
template = Templz.compile("|{{# boolean }}={{/ boolean }}|");
expect(template.render(data)).to.be("|=|");
});
});
describe("String templates - inverted sections", function() {
it("Falsey - Falsey sections should have their contents rendered.", function() {
var data = {
"boolean": false
},
template = Templz.compile("\"{{^boolean}}This should be rendered.{{/boolean}}\"");
expect(template.render(data)).to.be("\"This should be rendered.\"");
});
it("Truthy - Truthy sections should have their contents omitted.", function() {
var data = {
"boolean": true
},
template = Templz.compile("\"{{^boolean}}This should not be rendered.{{/boolean}}\"");
expect(template.render(data)).to.be("\"\"");
});
it("Context - Objects and hashes should behave like truthy values.", function() {
var data = {
context: {
name: "Joe"
}
},
template = Templz.compile("\"{{^context}}Hi {{name}}.{{/context}}\"");
expect(template.render(data)).to.be("\"\"");
});
it("List - Lists should behave like truthy values.", function() {
var data = {
list: [{
n: 1
},
{
n: 2
},
{
n: 3
}
]
},
template = Templz.compile("\"{{^list}}{{n}}{{/list}}\"");
expect(template.render(data)).to.be("\"\"");
});
it("Empty List - Empty lists should behave like falsey values.", function() {
var data = {
list: []
},
template = Templz.compile("\"{{^list}}Yay lists!{{/list}}\"");
expect(template.render(data)).to.be("\"Yay lists!\"");
});
it("Doubled - Multiple inverted sections per template should be permitted.", function() {
var data = {
two: "second",
bool: false
},
template = Templz.compile("{{^bool}}\n* first\n{{/bool}}\n* {{two}}\n{{^bool}}\n* third\n{{/bool}}\n");
expect(template.render(data)).to.be("* first\n* second\n* third\n");
});
it("Nested (Falsey) - Nested falsey sections should have their contents rendered.", function() {
var data = {
bool: false
},
template = Templz.compile("| A {{^bool}}B {{^bool}}C{{/bool}} D{{/bool}} E |");
expect(template.render(data)).to.be("| A B C D E |");
});
it("Nested (Truthy) - Nested truthy sections should be omitted.", function() {
var data = {
bool: true
},
template = Templz.compile("| A {{^bool}}B {{^bool}}C{{/bool}} D{{/bool}} E |");
expect(template.render(data)).to.be("| A E |");
});
it("Context Misses - Failed context lookups should be considered falsey.", function() {
var data = {},
template = Templz.compile("[{{^missing}}Cannot find key 'missing'!{{/missing}}]");
expect(template.render(data)).to.be("[Cannot find key 'missing'!]");
});
it("Dotted Names - Truthy - Dotted names should be valid for Inverted Section tags.", function() {
var data = {
a: {
b: {
c: true
}
}
},
template = Templz.compile("\"{{^a.b.c}}Not Here{{/a.b.c}}\" == \"\"");
expect(template.render(data)).to.be("\"\" == \"\"");
});
it("Dotted Names - Falsey - Dotted names should be valid for Inverted Section tags.", function() {
var data = {
a: {
b: {
c: false
}
}
},
template = Templz.compile("\"{{^a.b.c}}Not Here{{/a.b.c}}\" == \"Not Here\"");
expect(template.render(data)).to.be("\"Not Here\" == \"Not Here\"");
});
it("Dotted Names - Broken Chains - Dotted names that cannot be resolved should be considered falsey.", function() {
var data = {
a: {}
},
template = Templz.compile("\"{{^a.b.c}}Not Here{{/a.b.c}}\" == \"Not Here\"");
expect(template.render(data)).to.be("\"Not Here\" == \"Not Here\"");
});
it("Surrounding Whitespace - Inverted sections should not alter surrounding whitespace.", function() {
var data = {
"boolean": false
},
template = Templz.compile(" | {{^boolean}}\t|\t{{/boolean}} | \n");
expect(template.render(data)).to.be(" | \t|\t | \n");
});
it("Internal Whitespace - Inverted should not alter internal whitespace.", function() {
var data = {
"boolean": false
},
template = Templz.compile(" | {{^boolean}} {{! Important Whitespace }}\n {{/boolean}} | \n");
expect(template.render(data)).to.be(" | \n | \n");
});
it("Indented Inline Sections - Single-line sections should not alter surrounding whitespace.", function() {
var data = {
"boolean": false
},
template = Templz.compile(" {{^boolean}}NO{{/boolean}}\n {{^boolean}}WAY{{/boolean}}\n");
expect(template.render(data)).to.be(" NO\n WAY\n");
});
it("Standalone Lines - Standalone lines should be removed from the template.", function() {
var data = {
"boolean": false
},
template = Templz.compile("| This Is\n{{^boolean}}\n|\n{{/boolean}}\n| A Line\n");
expect(template.render(data)).to.be("| This Is\n|\n| A Line\n");
});
it("Standalone Indented Lines - Standalone indented lines should be removed from the template.", function() {
var data = {
"boolean": false
},
template = Templz.compile("| This Is\n {{^boolean}}\n|\n {{/boolean}}\n| A Line\n");
expect(template.render(data)).to.be("| This Is\n|\n| A Line\n");
});
it("Standalone Line Endings - \"\\r\\n\" should be considered a newline for standalone tags.", function() {
var data = {
"boolean": false
},
template = Templz.compile("|\r\n{{^boolean}}\r\n{{/boolean}}\r\n|");
expect(template.render(data)).to.be("|\r\n|");
});
it("Standalone Without Previous Line - Standalone tags should not require a newline to precede them.", function() {
var data = {
"boolean": false
},
template = Templz.compile(" {{^boolean}}\n^{{/boolean}}\n/");
expect(template.render(data)).to.be("^\n/");
});
it("Standalone Without Newline - Standalone tags should not require a newline to follow them.", function() {
var data = {
"boolean": false
},
template = Templz.compile("^{{^boolean}}\n/\n {{/boolean}}");
expect(template.render(data)).to.be("^\n/\n");
});
it("Padding - Superfluous in-tag whitespace should be ignored.", function() {
var data = {
"boolean": false
},
template = Templz.compile("|{{^ boolean }}={{/ boolean }}|");
expect(template.render(data)).to.be("|=|");
});
});
describe("String templates - partials", function() {
it("Basic Behavior - The greater-than operator should expand to the named partial.", function() {
var data = {},
template = Templz.compile("\"{{>text}}\""),
partials = {
text: "from partial"
};
expect(template.render(data, partials)).to.be("\"from partial\"");
});
it("Failed Lookup - The empty string should be used when the named partial is not found.", function() {
var data = {},
template = Templz.compile("\"{{>text}}\""),
partials = {};
expect(template.render(data, partials)).to.be("\"\"");
});
it("Context - The greater-than operator should operate within the current context.", function() {
var data = {
text: "content"
},
template = Templz.compile("\"{{>partial}}\""),
partials = {
partial: "*{{text}}*"
};
expect(template.render(data, partials)).to.be("\"*content*\"");
});
it("Recursion - The greater-than operator should properly recurse.", function() {
var data = {
content: "X",
nodes: [{
content: "Y",
nodes: []
}
]
},
template = Templz.compile("{{>node}}"),
partials = {
node: "{{content}}<{{#nodes}}{{>node}}{{/nodes}}>"
};
expect(template.render(data, partials)).to.be("X<Y<>>");
});
it("Surrounding Whitespace - The greater-than operator should not alter surrounding whitespace.", function() {
var data = {},
template = Templz.compile("| {{>partial}} |"),
partials = {
partial: "\t|\t"
};
expect(template.render(data, partials)).to.be("| \t|\t |");
});
it("Inline Indentation - Whitespace should be left untouched.", function() {
var data = {
data: "|"
},
template = Templz.compile(" {{data}} {{> partial}}\n"),
partials = {
partial: ">\n>"
};
expect(template.render(data, partials)).to.be(" | >\n>\n");
});
it("Standalone Line Endings - \"\\r\\n\" should be considered a newline for standalone tags.", function() {
var data = {},
template = Templz.compile("|\r\n{{>partial}}\r\n|"),
partials = {
partial: ">"
};
expect(template.render(data, partials)).to.be("|\r\n>|");
});
it("Standalone Without Previous Line - Standalone tags should not require a newline to precede them.", function() {
var data = {},
template = Templz.compile(" {{>partial}}\n>"),
partials = {
partial: ">\n>"
};
expect(template.render(data, partials)).to.be(" >\n >>");
});
it("Standalone Without Newline - Standalone tags should not require a newline to follow them.", function() {
var data = {},
template = Templz.compile(">\n {{>partial}}"),
partials = {
partial: ">\n>"
};
expect(template.render(data, partials)).to.be(">\n >\n >");
});
it("Standalone Indentation - Each line of the partial should be indented before rendering.", function() {
var data = {
content: "<\n->"
},
template = Templz.compile("\\\n {{>partial}}\n/\n"),
partials = {
partial: "|\n{{{content}}}\n|\n"
};
expect(template.render(data, partials)).to.be("\\\n |\n <\n->\n |\n/\n");
});
it("Padding Whitespace - Superfluous in-tag whitespace should be ignored.", function() {
var data = {
"boolean": true
},
template = Templz.compile("|{{> partial }}|"),
partials = {
partial: "[]"
};
expect(template.render(data, partials)).to.be("|[]|");
});
});
describe("String templates - changing delimiters", function() {
it("Pair Behavior - The equals sign (used on both sides) should permit delimiter changes.", function() {
var data = {
text: "Hey!"
},
template = Templz.compile("{{=<% %>=}}(<%text%>)");
expect(template.render(data)).to.be("(Hey!)");
});
it("Special Characters - Characters with special meaning regexen should be valid delimiters.", function() {
var data = {
text: "It worked!"
},
template = Templz.compile("({{=[ ]=}}[text])");
expect(template.render(data)).to.be("(It worked!)");
});
it("Sections - Delimiters set outside sections should persist.", function() {
var data = {
section: true,
data: "I got interpolated."
},
template = Templz.compile("[\n{{#section}}\n {{data}}\n |data|\n{{/section}}\n\n{{= | | =}}\n|#section|\n {{data}}\n |data|\n|/section|\n]\n");
expect(template.render(data)).to.be("[\n I got interpolated.\n |data|\n\n {{data}}\n I got interpolated.\n]\n");
});
it("Inverted Sections - Delimiters set outside inverted sections should persist.", function() {
var data = {
section: false,
data: "I got interpolated."
},
template = Templz.compile("[\n{{^section}}\n {{data}}\n |data|\n{{/section}}\n\n{{= | | =}}\n|^section|\n {{data}}\n |data|\n|/section|\n]\n");
expect(template.render(data)).to.be("[\n I got interpolated.\n |data|\n\n {{data}}\n I got interpolated.\n]\n");
});
it("Partial Inheritence - Delimiters set in a parent template should not affect a partial.", function() {
var data = {
value: "yes"
},
template = Templz.compile("[ {{>include}} ]\n{{= | | =}}\n[ |>include| ]\n"),
partials = {
include: ".{{value}}."
};
expect(template.render(data, partials)).to.be("[ .yes. ]\n[ .yes. ]\n");
});
it("Post-Partial Behavior - Delimiters set in a partial should not affect the parent template.", function() {
var data = {
value: "yes"
},
template = Templz.compile("[ {{>include}} ]\n[ .{{value}}. .|value|. ]\n"),
partials = {
include: ".{{value}}. {{= | | =}} .|value|."
};
expect(template.render(data, partials)).to.be("[ .yes. .yes. ]\n[ .yes. .|value|. ]\n");
});
it("Surrounding Whitespace - Surrounding whitespace should be left untouched.", function() {
var data = {},
template = Templz.compile("| {{=@ @=}} |");
expect(template.render(data)).to.be("| |");
});
it("Outlying Whitespace (Inline) - Whitespace should be left untouched.", function() {
var data = {},
template = Templz.compile(" | {{=@ @=}}\n");
expect(template.render(data)).to.be(" | \n");
});
it("Standalone Tag - Standalone lines should be removed from the template.", function() {
var data = {},
template = Templz.compile("Begin.\n{{=@ @=}}\nEnd.\n");
expect(template.render(data)).to.be("Begin.\nEnd.\n");
});
it("Indented Standalone Tag - Indented standalone lines should be removed from the template.", function() {
var data = {},
template = Templz.compile("Begin.\n {{=@ @=}}\nEnd.\n");
expect(template.render(data)).to.be("Begin.\nEnd.\n");
});
it("Standalone Line Endings - \"\\r\\n\" should be considered a newline for standalone tags.", function() {
var data = {},
template = Templz.compile("|\r\n{{= @ @ =}}\r\n|");
expect(template.render(data)).to.be("|\r\n|");
});
it("Standalone Without Previous Line - Standalone tags should not require a newline to precede them.", function() {
var data = {},
template = Templz.compile(" {{=@ @=}}\n=");
expect(template.render(data)).to.be("=");
});
it("Standalone Without Newline - Standalone tags should not require a newline to follow them.", function() {
var data = {},
template = Templz.compile("=\n {{=@ @=}}");
expect(template.render(data)).to.be("=\n");
});
it("Pair with Padding - Superfluous in-tag whitespace should be ignored.", function() {
var data = {},
template = Templz.compile("|{{= @ @ =}}|");
expect(template.render(data)).to.be("||");
});
});
describe("String templates - lambda functions", function() {
it("Interpolation - A lambda's return value should be interpolated.", function() {
var data = {
lambda: function() { return "world" }
},
template = Templz.compile("Hello, {{lambda}}!");
expect(template.render(data)).to.be("Hello, world!");
});
it("Interpolation - Expansion - A lambda's return value should be parsed.", function() {
var data = {
planet: "world",
lambda: function() { return "{{planet}}" }
},
template = Templz.compile("Hello, {{lambda}}!");
expect(template.render(data)).to.be("Hello, world!");
});
it("Interpolation - Alternate Delimiters - A lambda's return value should parse with the default delimiters.", function() {
var data = {
planet: "world",
lambda: function() { return "|planet| => {{planet}}" }
},
template = Templz.compile("{{= | | =}}\nHello, (|&lambda|)!");
expect(template.render(data)).to.be("Hello, (|planet| => world)!");
});
it("Interpolation - Multiple Calls - Interpolated lambdas should not be cached.", function() {
var data = {
lambda: function() { return (g=(function(){return this})()).calls=(g.calls||0)+1 }
},
template = Templz.compile("{{lambda}} == {{{lambda}}} == {{lambda}}");
expect(template.render(data)).to.be("1 == 2 == 3");
});
it("Escaping - Lambda results should be appropriately escaped.", function() {
var data = {
lambda: function() { return ">" }
},
template = Templz.compile("<{{lambda}}{{{lambda}}}");
expect(template.render(data)).to.be("<>>");
});
it("Section - Lambdas used for sections should receive the raw section string.", function() {
var data = {
x: "Error!",
lambda: function(txt) { return (txt == "{{x}}" ? "yes" : "no") }
},
template = Templz.compile("<{{#lambda}}{{x}}{{/lambda}}>");
expect(template.render(data)).to.be("<yes>");
});
it("Section - Expansion - Lambdas used for sections should have their results parsed.", function() {
var data = {
planet: "Earth",
lambda: function(txt) { return txt + "{{planet}}" + txt }
},
template = Templz.compile("<{{#lambda}}-{{/lambda}}>");
expect(template.render(data)).to.be("<-Earth->");
});
it("Section - Alternate Delimiters - Lambdas used for sections should parse with the current delimiters.", function() {
var data = {
planet: "Earth",
lambda: function(txt) { return txt + "{{planet}} => |planet|" + txt }
},
template = Templz.compile("{{= | | =}}<|#lambda|-|/lambda|>");
expect(template.render(data)).to.be("<-{{planet}} => Earth->");
});
it("Section - Multiple Calls - Lambdas used for sections should not be cached.", function() {
var data = {
lambda: function(txt) { return "__" + txt + "__" }
},
template = Templz.compile("{{#lambda}}FILE{{/lambda}} != {{#lambda}}LINE{{/lambda}}");
expect(template.render(data)).to.be("__FILE__ != __LINE__");
});
it("Inverted Section - Lambdas used for inverted sections should be considered truthy.", function() {
var data = {
"static": "static",
lambda: function(txt) { return false }
},
template = Templz.compile("<{{^lambda}}{{static}}{{/lambda}}>");
expect(template.render(data)).to.be("<>");
});
});
});