ractive
Version:
Next-generation DOM manipulation
771 lines (763 loc) • 25.6 kB
JavaScript
var renderTests = [
{
name: "Empty model",
template: "",
result: ""
},
{
name: "Plain text",
template: "a string",
result: "a string"
},
{
name: "Single interpolator",
template: "{{mustache}}",
data: { mustache: "hello world" },
result: "hello world"
},
{
name: "Element containing single interpolator",
template: "<p>{{mustache}}</p>",
data: { mustache: "hello world" },
result: "<p>hello world</p>"
},
{
name: "Element containing interpolator surrounded by text",
template: "<p>Hello {{mustache}}!</p>",
data: { mustache: "world" },
result: "<p>Hello world!</p>"
},
{
name: "Section with index refs",
template: "<ul>{{#items:i}}<li>{{i}}: {{name}}</li>{{/items}}</ul>",
data: {
items: [{name:"zero"},{name:"one"},{name:"two"}]
},
result: "<ul><li>0: zero</li><li>1: one</li><li>2: two</li></ul>"
},
{
name: "Section with index refs in attributes",
template: "<ul>{{#items:i}}<li data-id=\"{{i}}\">{{name}}</li>{{/items}}</ul>",
data: {
items: [{name:"zero"},{name:"one"},{name:"two"}]
},
result: "<ul><li data-id=\"0\">zero</li><li data-id=\"1\">one</li><li data-id=\"2\">two</li></ul>"
},
{
name: "Element with attributes",
template: "<p class='{{class_name}}'>text</p>",
data: {
"class_name": "it_works"
},
result: "<p class=\"it_works\">text</p>"
},
{
name: "Section with descendant attributes",
template: "{{#todos}}<li><label>{{todo}}</label><span class='{{status}}'>{{todo}}</span></li>{{/todos}}",
data: {
todos: [{todo:"debug Ractive",status:"complete"},{todo:"release Ractive",status:"incomplete"}]
},
result: "<li><label>debug Ractive</label><span class=\"complete\">debug Ractive</span></li><li><label>release Ractive</label><span class=\"incomplete\">release Ractive</span></li>"
},
// argh, fails in IE because of how it does innerHTML (i.e. wrongly). Skipping
/*{
name: "Section with descendant value attributes",
template: "{{#todos}}<li><label>{{todo}}</label><input value='{{todo}}'></li>{{/todos}}",
data: {
todos: [{todo:"debug Ractive"},{todo:"release Ractive"}]
},
result: "<li><label>debug Ractive</label><input></li><li><label>release Ractive</label><input></li>"
},*/
{
name: "Partials",
template: "{{#items}}{{>item}}{{/items}}",
data: {
items: [{description:"Item the first"},{description:"Item the second"},{description:"Item the third"}]
},
partials: {
item: "<p>{{description}}</p>"
},
result: "<p>Item the first</p><p>Item the second</p><p>Item the third</p>"
},
{
name: 'Partials that compile as HTML',
template: '<div>{{>partial}}</div>',
data: { content: 'some text' },
partials: { partial: '<p>{{content}}</p>' },
result: '<div><p>some text</p></div>'
},
{
name: 'Partials inherit index references',
template: '<ul>{{#items:i}}{{>item}}{{/items}}</ul>',
data: { items: [ 'zero', 'one', 'two', 'three' ] },
partials: { item: '<li data-index="{{i}}">{{i}}: {{.}}</li>' },
result: '<ul><li data-index="0">0: zero</li><li data-index="1">1: one</li><li data-index="2">2: two</li><li data-index="3">3: three</li></ul>'
},
{
name: "Static string attributes",
template: "<p class=\"myclass\">test</p>",
result: "<p class=\"myclass\">test</p>"
},
{
name: "Empty string attributes",
template: "<p class=\"\">test</p>",
result: "<p class=\"\">test</p>"
},
{
name: 'Attribute with sections',
template: '<ul>{{#todos:i}}<li data-index="{{i}}" class="{{#completed}}completed{{/completed}}{{^completed}}view{{/completed}}">{{desc}}</li>{{/todos}}</ul>',
data: { todos: [{ desc: 'debug Ractive', completed: false }, { desc: 'release Ractive', completed: false }, { desc: 'make cup of tea', completed: true }]},
result: '<ul><li data-index="0" class="view">debug Ractive</li><li data-index="1" class="view">release Ractive</li><li data-index="2" class="completed">make cup of tea</li></ul>'
},
{
name: 'Conditional section with true condition',
template: '{{#condition}}The condition is truthy{{/condition}}',
data: { condition: true },
result: 'The condition is truthy'
},
{
name: 'Conditional section with false condition',
template: '{{#condition}}The condition is truthy{{/condition}}',
data: { condition: false },
result: ''
},
{
name: 'Inverted section with true condition',
template: '{{^condition}}The condition is falsy{{/condition}}',
data: { condition: true },
result: ''
},
{
name: 'Inverted section with false condition',
template: '{{^condition}}The condition is falsy{{/condition}}',
data: { condition: false },
result: 'The condition is falsy'
},
{
name: 'Triple',
template: '<div>before {{{triple}}} after</div>',
data: { triple: '<strong>bold</strong> <em>italic</em>' },
result: '<div>before <strong>bold</strong> <em>italic</em> after</div>',
new_data: { triple: '<em>italic</em> <strong>bold</strong>' },
new_result: '<div>before <em>italic</em> <strong>bold</strong> after</div>'
},
{
name: 'Static',
template: '<div>[[color]]</div>',
data: { color: 'purple' },
result: '<div>purple</div>',
new_data: { color: 'orange' },
new_result: '<div>purple</div>'
},
{
name: 'SVG',
template: '<svg><circle cx="{{x}}" cy="{{y}}" r="{{r}}"/></svg>',
data: { x: 50, y: 50, r: 50 },
result: '<svg><circle cx="50" cy="50" r="50"></circle></svg>',
svg: true
},
{
name: 'SVG with non-mustache text',
template: '<svg><text>some text</text></svg>',
data: {},
result: '<svg><text>some text</text></svg>',
svg: true
},
{
name: 'SVG with interpolator',
template: '<svg><text>{{hello}}</text></svg>',
data: { hello: 'Hello world!' },
result: '<svg><text>Hello world!</text></svg>',
svg: true
},
{
name: 'SVG with interpolator and static text',
template: '<svg><text>Hello {{thing}}!</text></svg>',
data: { thing: 'world' },
result: '<svg><text>Hello world!</text></svg>',
svg: true
},
{
name: 'Basic expression',
template: '{{( "test".toUpperCase() )}}',
result: 'TEST'
},
{
name: 'Expression with a single reference',
template: '{{( ref )}}',
data: { ref: 'success' },
result: 'success'
},
{
name: 'Arithmetic expression',
template: '{{( number * 2 )}}',
data: { number: 10 },
result: '20'
},
{
name: 'Arithmetic expression with update',
template: '{{( number * 2 )}}',
data: { number: 10 },
new_data: { number: 20 },
result: '20',
new_result: '40'
},
{
name: 'Arithmetic expression with missing data',
template: '{{( number * 2 )}}',
result: 'NaN'
},
{
name: 'Arithmetic expression with missing data and update',
template: '{{( number * 2 )}}',
new_data: { number: 20 },
result: 'NaN',
new_result: '40'
},
{
name: 'Arithmetic expression with index reference',
template: '<ul>{{#items:i}}<li>{{( i + 1 )}}: {{.}}</li>{{/items}}</ul>',
data: { items: [ 'a', 'b', 'c' ] },
result: '<ul><li>1: a</li><li>2: b</li><li>3: c</li></ul>'
},
{
name: 'Conditional expression',
template: '<p class="{{( done ? \"complete\" : \"incomplete\" )}}">{{desc}}{{( done ? "" : " (pending)" )}}</p>',
data: { desc: 'Write more tests', done: true },
result: '<p class="complete">Write more tests</p>',
new_data: { done: false },
new_result: '<p class="incomplete">Write more tests (pending)</p>'
},
{
name: 'Invocation expression',
template: '<p>The population of {{country}} is {{( format(population) )}}.</p>',
data: {
country: 'the UK',
population: 62641000,
format: function ( num ) {
if ( num > 1000000000 ) return ( num / 1000000000 ).toFixed( 1 ) + ' billion';
if ( num > 1000000 ) return ( num / 1000000 ).toFixed( 1 ) + ' million';
if ( num > 1000 ) return ( Math.floor( num / 1000 ) ) + ',' + ( num % 1000 );
return num;
}
},
result: '<p>The population of the UK is 62.6 million.</p>'
},
{
name: 'Responding to downstream changes',
template: '<p>Total: {{( total( numbers ) )}}</p>',
data: {
numbers: [ 1, 2, 3, 4 ],
total: function ( numbers ) {
return numbers.reduce( function ( prev, curr ) {
return prev + curr;
}, 0 );
}
},
result: '<p>Total: 10</p>',
new_data: {
'numbers[4]': 5
},
new_result: '<p>Total: 15</p>'
},
{
name: 'Attribute with nested mustaches',
template: '<svg viewBox="{{#viewBox}}{{x}} {{y}} {{width}} {{height}}{{/viewBox}}">{{#rect}}<rect x="{{x}}" y="{{y}}" width="{{width}}" height="{{height}}"/>{{/rect}}</svg>',
data: {
viewBox: { x: 0, y: 0, width: 100, height: 100 },
rect: { x: 10, y: 10, width: 80, height: 80 }
},
result: '<svg viewBox="0 0 100 100"><rect x="10" y="10" width="80" height="80"></rect></svg>',
new_data: {
viewBox: { x: 50, y: 50, width: 350, height: 350 },
rect: { x: 20, y: 20, width: 200, height: 100 }
},
new_result: '<svg viewBox="50 50 350 350"><rect x="20" y="20" width="200" height="100"></rect></svg>',
svg: true
},
{
name: 'List section with non-self-updating attributes',
template: '<ul>{{#items}}<li data-info="{{#info}}{{a}} {{b}} {{c}}{{/info}}"></li>{{/items}}</ul>',
data: {
items: [{ info: { a: 1, b: 2, c: 3 } }]
},
result: '<ul><li data-info="1 2 3"></li></ul>',
new_data: {
items: [{ info: { a: 1, b: 2, c: 3 } }, { info: { a: 4, b: 5, c: 6 } }]
},
new_result: '<ul><li data-info="1 2 3"></li><li data-info="4 5 6"></li></ul>'
},
{
name: 'Section with non-explicitly-closed element',
template: '<ul>{{#items}}<li>{{.}}{{/items}}</ul>',
data: { items: [ 'a', 'b', 'c' ]},
result: '<ul><li>a</li><li>b</li><li>c</li></ul>',
new_data: { items: [ 'd', 'e', 'f' ]},
new_result: '<ul><li>d</li><li>e</li><li>f</li></ul>'
},
{
name: 'Whitespace is stripped from start and end of templates',
template: ' <p>{{content}}</p> ',
data: { content: 'test' },
result: '<p>test</p>'
},
{
name: 'Whitespace is stripped from start and end of templates without mustaches',
template: ' <p>test</p> ',
result: '<p>test</p>'
},
{
name: 'Expression with implicit iterator',
template: '<ul>{{#items}}<li>{{( uppercase( . ) )}}</li>{{/items}}</ul>',
data: { items: [ 'a', 'b', 'c' ], uppercase: function ( str ) { return str.toUpperCase(); } },
result: '<ul><li>A</li><li>B</li><li>C</li></ul>',
new_data: { items: [ 'd', 'e', 'f' ]},
new_result: '<ul><li>D</li><li>E</li><li>F</li></ul>'
},
{
name: 'Input with dynamic (but not two-way) name attribute',
template: '{{#list:i}}<input name="test{{i}}">{{/list}}',
data: { list: [ 'a', 'b', 'c' ] },
result: '<input name="test0"><input name="test1"><input name="test2">'
},
{
name: 'Ancestor references',
template: '{{#foo}}{{#bar}}{{#baz}}<p>{{value}}</p><p>{{../value}}</p><p>{{../../value}}</p>{{/baz}}{{/bar}}{{/foo}}',
data: { foo: { value: 'foo', bar: { value: 'bar', baz: { value: 'baz' } } } },
result: '<p>baz</p><p>bar</p><p>foo</p>'
},
{
name: 'Conditional expression with unresolved condition',
template: '{{ foobar ? "YES" : "NO"}}',
data: {},
result: 'NO'
},
{
name: 'Conditional section with unresolved reference in expression',
template: '{{#( ! foobar )}}NO{{/()}}',
data: {},
result: 'NO'
},
{
name: 'Conditional section with references to undefined',
template: '{{#( foobar === undefined )}}undefined{{/()}}',
data: { foobar: undefined },
result: 'undefined'
},
{
name: 'Dependencies can be declared with this.get() inside expression functions',
template: '{{ area() }}',
data: { width: 50, height: 50, area: function () { return this.get( 'width' ) * this.get( 'height' ) } },
result: '2500',
new_data: { width: 100 },
new_result: '5000'
},
{
name: 'Triples work correctly inside table elements',
template: '<table>{{{row}}}</table>' +
'<table><thead>{{{headerRow}}}</thead></table>' +
'<table><tbody>{{{row}}}</tbody></table>' +
'<table><tr>{{{cell}}}</tr></table>' +
'<table><tr><td>{{{cellContents}}}</td></tr></table>' +
'<table><tr><th>{{{cellContents}}}</th></tr></table>',
data: {
row: '<tr><td>works</td></tr>',
headerRow: '<tr><th>works</th></tr>',
cell: '<td>works</td>',
cellContents: 'works'
},
result: '<table><tr><td>works</td></tr></table>' +
'<table><thead><tr><th>works</th></tr></thead></table>' +
'<table><tbody><tr><td>works</td></tr></tbody></table>' +
'<table><tr><td>works</td></tr></table>' +
'<table><tr><td>works</td></tr></table>' +
'<table><tr><th>works</th></tr></table>',
new_data: {
row: '<tr><td>still works</td></tr>',
headerRow: '<tr><th>still works</th></tr>',
cell: '<td>still works</td>',
cellContents: 'still works'
},
new_result: '<table><tr><td>still works</td></tr></table>' +
'<table><thead><tr><th>still works</th></tr></thead></table>' +
'<table><tbody><tr><td>still works</td></tr></tbody></table>' +
'<table><tr><td>still works</td></tr></table>' +
'<table><tr><td>still works</td></tr></table>' +
'<table><tr><th>still works</th></tr></table>'
},
{
name: 'Triples work correctly inside select elements',
template: '<select>{{{options}}}</select>',
data: { options: '<option value="1">one</option><option value="2">two</option><option value="3">three</option>' },
result: '<select><option value="1">one</option><option value="2">two</option><option value="3">three</option></select>',
new_data: { options: '<option value="4">four</option><option value="5">five</option><option value="6">six</option>' },
new_result: '<select><option value="4">four</option><option value="5">five</option><option value="6">six</option></select>'
},
{
name: 'Class name on an SVG element',
template: '<svg><text class="label">foo</text></svg>',
result: '<svg><text class=label>foo</text></svg>',
svg: true
},
{
name: 'Multiple angle brackets are correctly escaped, both with render() and renderHTML()',
template: '{{foo}}',
data: { foo: '<p>test</p>' },
result: '<p>test</p>'
},
{
name: 'Angle brackets should not be escaped inside script tags',
template: '<script>(function () { var html="<p>{{html}}</p>";var foo = 4 < 3; }());</script>',
data: { html: 'some <strong>html</strong>' },
result: '<script>(function () { var html="<p>some <strong>html</strong></p>";var foo = 4 < 3; }());</script>'
},
{
name: 'Section iterating over a hash',
template: '<ul>{{#items:key}}<li>{{key}}: {{this}}</li>{{/items}}</ul>',
data: { items: { a: 1, b: 2, c: 3 } },
result: '<ul><li>a: 1</li><li>b: 2</li><li>c: 3</li></ul>',
new_data: { items: { c: 3, d: 4, e: 5 } },
new_result: '<ul><li>c: 3</li><li>d: 4</li><li>e: 5</li></ul>'
},
{
name: 'Null values in the viewmodel',
template: '<p>{{foo}}</p>',
data: { foo: null },
result: '<p></p>'
},
{
name: 'Null values in the viewmodel, with a triple',
template: '<p>{{{foo}}}</p>',
data: { foo: null },
result: '<p></p>'
},
{
name: 'Null values in the viewmodel, with an attribute',
template: '<p class="foo-{{bar}}">test</p>',
data: { bar: null },
result: '<p class="foo-">test</p>'
},
{
name: 'Inverted section with restricted reference',
template: '<p>{{^.foo}}this should appear{{/.foo}}</p>',
result: '<p>this should appear</p>'
},
{
name: 'Data is an array',
template: '{{#.}}<p>{{name}}</p>{{/.}}',
data: [{ name: 'Alice' }, { name: 'Bob' }, { name: 'Charles' }],
result: '<p>Alice</p><p>Bob</p><p>Charles</p>'
},
{
name: 'Setting child properties of null values creates object',
template: '{{foo.bar}}',
data: { foo: null },
result: '',
new_data: { 'foo.bar': 'works' },
new_result: 'works'
},
{
name: 'Children of sections with partially resolved evaluator',
template: '{{# foo || {} }}{{bar}}{{/ foo || {} }}',
data: {},
result: '',
new_data: { foo: { bar: 'works' } },
new_result: 'works'
},
{
name: 'Different expressions that share a keypath in unresolved state',
template: '{{identity(foo)}} / {{identity(bar)}}',
data: { identity: function ( val ) { return val; } },
result: ' / ',
new_data: { foo: 'one', bar: 'two', identity: function ( val ) { return val; } },
new_result: 'one / two'
},
{
name: 'Properties of functions render correctly (#451)',
template: '{{foo.prop}}-{{#foo}}{{prop}}{{/foo}}',
data: function () {
var foo = function () {}, columns = [{ bar: foo }];
foo.prop = 'works';
return {
columns: columns,
foo: foo
};
},
result: 'works-works',
new_data: { 'foo.prop': 'still works' },
new_result: 'still works-still works'
},
{
name: 'style tags in svg',
template: '<svg><style>text { font-size: 40px }</style></svg>',
result: '<svg><style>text { font-size: 40px }</style></svg>',
svg: true
},
// Elements with two-way bindings should render correctly with .toHTML() - #446
{
nodeOnly: true,
name: 'Two-way select bindings',
template: '<select value="{{foo}}"><option value="a">a</option><option value="b">b</option><option value="c">c</option></select>',
data: {},
result: '<select><option value="a" selected>a</option><option value="b">b</option><option value="c">c</option></select>',
new_data: { foo: 'c' },
new_result: '<select><option value="a">a</option><option value="b">b</option><option value="c" selected>c</option></select>'
},
{
nodeOnly: true,
name: 'Two-way select bindings inside list',
template: '<select value="{{selected}}">{{#items}}<option value="{{.}}">{{.}}</option>{{/items}}</select>',
data: { selected: 2, items: [1,2,3] },
result: '<select><option value="1">1</option><option value="2" selected>2</option><option value="3">3</option></select>',
new_data: { selected: 3 },
new_result: '<select><option value="1">1</option><option value="2">2</option><option value="3" selected>3</option></select>'
},
{
nodeOnly: true,
name: 'Two-way multiple select bindings',
template: '<select multiple value="{{foo}}"><option value="a">a</option><option value="b">b</option><option value="c">c</option></select>',
data: {},
result: '<select multiple><option value="a">a</option><option value="b">b</option><option value="c">c</option></select>',
new_data: { foo: [ 'b', 'c' ] },
new_result: '<select multiple><option value="a">a</option><option value="b" selected>b</option><option value="c" selected>c</option></select>'
},
{
nodeOnly: true,
name: 'Two-way radio buttons',
template: '<input type="radio" name="{{foo}}" value="one"><input type="radio" name="{{foo}}" value="two">',
data: { foo: 'one' },
result: '<input type="radio" name="{{foo}}" value="one" checked><input type="radio" name="{{foo}}" value="two">',
new_data: { foo: 'two' },
new_result: '<input type="radio" name="{{foo}}" value="one"><input type="radio" name="{{foo}}" value="two" checked>'
},
//unresolved expressions
{
name: 'Keypath expression with unresolved member resolves',
template: '{{foo[bar]}}',
data: { foo: { boo: 'bizz' } },
result: '',
new_data: { bar: 'boo' },
new_result: 'bizz'
},
{
name: 'Keypath expression with top level unresolved',
template: '{{foo[bar]}}',
data: { bar: 'boo' },
result: '',
new_data: { foo: { boo: 'bizz' } },
new_result: 'bizz'
},
{
name: 'Nested keypath expression with top level unresolved',
template: '{{#item}}{{foo[bar]}}{{/}}',
data: { bar: 'boo' },
result: '',
new_data: { item: { foo: { boo: 'bizz' } } },
new_result: 'bizz'
},
{
name: 'Keypath expression with array index member',
template: '{{foo[bar]}}',
data: { foo: ['fizz', 'bizz'], bar: 0 },
result: 'fizz',
new_data: { bar: 1 },
new_result: 'bizz'
},
{
name: 'Keypath expression with unrooted references and array index member',
template: '{{#item}}{{foo[bar]}}{{/}}',
data: { item: { foo: ['fizz', 'bizz'], bar: 0 } },
result: 'fizz',
new_data: { item: { foo: ['fizz', 'bizz'], bar: 1 } },
new_result: 'bizz'
},
{
name: 'Attribute value with characters that need to be escaped',
template: '<div class="{{className}}"></div>',
data: { className: '"find & \'replace\'"' },
result: '<div class=""find & 'replace'""></div>'
},
{
nodeOnly: true, // fixture.innerHTML doesn't work in our favour
name: 'Boolean attributes',
template: '<input type="checkbox" checked="{{isChecked}}">',
data: { isChecked: true },
result: '<input type=checkbox checked>',
new_data: { isChecked: false },
new_result: '<input type=checkbox>'
},
{
name: 'References resolve on the basis of the first key (#522)',
template: '{{#foo}}{{bar.baz}}{{/foo}}',
data: { foo: { bar: {} }, bar: { baz: 'hello' } },
result: '',
new_data: { foo: { bar: { baz: 'goodbye' } }, bar: { baz: 'hello' } },
new_result: 'goodbye'
},
{
name: '{{#each object}}...{{/each}} works',
handlebars: true,
template: '{{#each object}}<p>{{this}}</p>{{/each}}',
data: { object: { foo: 1, bar: 2, baz: 3 } },
result: '<p>1</p><p>2</p><p>3</p>',
new_data: { object: { bar: 2, baz: 4, qux: 5 } },
new_result: '<p>2</p><p>4</p><p>5</p>'
},
{
name: '@index can be used as an index reference',
handlebars: true,
template: '{{#each items}}<p>{{@index}}: {{this}}</p>{{/each}}',
data: { items: [ 'a', 'b', 'c' ] },
result: '<p>0: a</p><p>1: b</p><p>2: c</p>'
},
{
name: '@key can be used as an key reference',
handlebars: true,
template: '{{#each object}}<p>{{@key}}: {{this}}</p>{{/each}}',
data: { object: { foo: 1, bar: 2, baz: 3 } },
result: '<p>foo: 1</p><p>bar: 2</p><p>baz: 3</p>'
},
{
name: '@index can be used in an expression',
handlebars: true,
template: '{{#each items}}<p>{{@index + 1}}: {{this}}</p>{{/each}}',
data: { items: [ 'a', 'b', 'c' ] },
result: '<p>1: a</p><p>2: b</p><p>3: c</p>'
},
{
name: '@index can be used in a reference expression',
handlebars: true,
template: '{{#each items}}<p>{{items[@index]}} - {{items[@index+1]}}</p>{{/each}}',
data: { items: [ 'a', 'b', 'c' ] },
result: '<p>a - b</p><p>b - c</p><p>c - </p>'
},
{
name: '{{#each items}}...{{else}}...{{/each}}',
handlebars: true,
template: '{{#each items}}<p>{{this}}</p>{{else}}<p>no items!</p>{{/each}}',
data: { items: [ 'a', 'b', 'c' ] },
result: '<p>a</p><p>b</p><p>c</p>',
new_data: { items: null },
new_result: '<p>no items!</p>'
},
{
name: '#if/else with true static expression',
handlebars: true,
template: '{{#if true}}yes{{else}}no{{/if}}',
result: 'yes'
},
{
name: '#if/else with false static expression',
handlebars: true,
template: '{{#if false}}yes{{else}}no{{/if}}',
result: 'no'
},
{
name: '#if/else with true keypath expression',
handlebars: true,
template: '{{#if foo[bar]}}yes{{else}}no{{/if}}',
data: { foo: { a: true, b: false }, bar: 'a' },
result: 'yes'
},
{
name: '#if/else with false keypath expression',
handlebars: true,
template: '{{#if foo[bar]}}yes{{else}}no{{/if}}',
data: { foo: { a: true, b: false }, bar: 'b' },
result: 'no'
},
{
name: '#if/else with true reference expression',
handlebars: true,
template: '{{#if (foo+1<12)}}yes{{else}}no{{/if}}',
data: { foo: 6 },
result: 'yes'
},
{
name: '#if/else with false reference expression',
handlebars: true,
template: '{{#if (foo+1<12)}}yes{{else}}no{{/if}}',
data: { foo: 16 },
result: 'no'
},
{
name: 'Restricting references with `this`',
template: '{{#foo}}{{this.bar}}{{/foo}}',
data: { foo: {}, bar: 'fail' },
result: '',
new_data: { foo: { bar: 'success' }, bar: 'fail' },
new_result: 'success'
},
{
name: 'Section in attribute',
template: '<div style="{{#red}}color: red;{{/}}">{{#red}}is red{{/red}}</div>',
data: { red: true },
result: '<div style="color: red;">is red</div>',
new_data: { red: false },
new_result: '<div style=""></div>'
},
{
name: 'Triple inside an unrendering section (#726)',
template: '{{#condition}}{{{getTriple(condition)}}}{{/condition}}',
data: { condition: true, getTriple: ( condition ) => condition ? 'yes' : 'no' },
result: 'yes',
new_data: { condition: false },
new_result: ''
},
{
name: 'Reference expression with sub-expression',
template: '{{ foo[ "ba" + letter ].prop}}',
data: { foo: { bar: { prop: 'one' }, baz: { prop: 'two' } }, letter: 'r' },
result: 'one',
new_data: { foo: { bar: { prop: 'one' }, baz: { prop: 'two' } }, letter: 'z' },
new_result: 'two'
},
{
name: 'Empty non-boolean attributes (#878)',
template: '<div data-attr></div>',
result: '<div data-attr></div>'
},
{
name: 'Falsy boolean attributes',
template: '<video autoplay="{{foo}}"></video>',
result: '<video></video>'
},
{
name: 'Root-level reference',
template: '{{#a}}{{#b}}{{#c}}{{~/foo}}{{/c}}{{/b}}{{/a}}',
data: { foo: 'top', a: { b: { c: { foo: 'c' }, foo: 'b' }, foo: 'a' } },
result: 'top'
},
{
name: 'else in non-Handlebars blocks',
template: '{{#foo}}yes{{else}}no{{/foo}}',
data: { foo: true },
result: 'yes',
new_data: { foo: false },
new_result: 'no'
},
{
name: 'Double-rendering bug (#748) is prevented',
template: '{{#foo}}{{#f(this)}}{{this}}{{/f}}{{/foo}}',
data: {
foo: [
[ 2, 1, 4, 3 ]
],
f: function (x) {
return x.sort(function (a, b) { // ... or this (sort) and it will work
return b - a;
});
}
},
result: '4321'
}
];
// this needs to work with AMD (for qunit) and node (for nodeunit)...
if ( typeof define === 'function' && define.amd ) {
define( function () {
return renderTests;
});
}
else if ( typeof module !== 'undefined' && module.exports ) {
module.exports = renderTests;
}