From 081772c3f4850847e69ed84cd7bdd6e0c4e1936f Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 16 Jul 2010 18:36:24 -0400 Subject: [PATCH] replicate interpreter tests into compiler tests. --- test/{unit.js => unit.compiler.js} | 29 +- test/unit.html | 3 +- test/unit.interpreter.js | 581 +++++++++++++++++++++++++++++ 3 files changed, 599 insertions(+), 14 deletions(-) rename test/{unit.js => unit.compiler.js} (94%) create mode 100644 test/unit.interpreter.js diff --git a/test/unit.js b/test/unit.compiler.js similarity index 94% rename from test/unit.js rename to test/unit.compiler.js index 3e93a1d..631651e 100644 --- a/test/unit.js +++ b/test/unit.compiler.js @@ -1,3 +1,19 @@ +// the compiler tests are the exact same as the interpreter tests +// so instead of writing all the tests twice, override the to_html +// method +module('Compiler', { + setup: function() { + this._oldToHtml = Mustache.to_html; + Mustache.to_html = function(template, view, partials) { + var compiler = Mustache.compile(template, partials); + return compiler(view); + } + }, + teardown: function() { + Mustache.to_html = this._oldToHtml; + } +}); + test("Parser", function() { expect(3); @@ -53,19 +69,6 @@ test("Parser", function() { }); -test("Compiler", function() { - expect(3); - - var template = Mustache.compile('the grand poobah says: {{variable}}.', {}); - equals(template({variable: 'hello'}), 'the grand poobah says: hello.'); - - template = Mustache.compile('the grand poobah says: {{>partial}}.', {partial: 'i love {{sugar}}'}); - equals(template({sugar: 'chocolate'}), 'the grand poobah says: i love chocolate.'); - - template = Mustache.compile('the grand poobah says: {{#hos}}i love chocolate{{/hos}}.', {}); - equals(template({hos:function() { return function(text, renderer) { return '' + text + ''; } }}), 'the grand poobah says: i love chocolate.'); -}); - test("Basic Variables", function() { expect(3); diff --git a/test/unit.html b/test/unit.html index 5f373f2..64cbc28 100644 --- a/test/unit.html +++ b/test/unit.html @@ -5,7 +5,8 @@ - + +

mustache.js unit tests

diff --git a/test/unit.interpreter.js b/test/unit.interpreter.js new file mode 100644 index 0000000..9cf8015 --- /dev/null +++ b/test/unit.interpreter.js @@ -0,0 +1,581 @@ +module('Interpreter'); + +test("Parser", function() { + expect(3); + + // matches whitespace_partial.html + equals( + Mustache.to_html( + '

{{ greeting }}

\n{{> partial }}\n

{{ farewell }}

', + { + greeting: function() { + return "Welcome"; + }, + + farewell: function() { + return "Fair enough, right?"; + }, + + partial: { + name: "Chris", + value: 10000, + taxed_value: function() { + return this.value - (this.value * 0.4); + }, + in_ca: true + } + }, + {partial:'Hello {{ name}}\nYou have just won ${{value }}!\n{{# in_ca }}\nWell, ${{ taxed_value }}, after taxes.\n{{/ in_ca }}\n'} + ), + '

Welcome

\nHello Chris\nYou have just won $10000!\n\nWell, $6000, after taxes.\n\n\n

Fair enough, right?

', + 'Whitespace in Tag names' + ); + + equals( + Mustache.to_html( + '{{tag1}}\n\n\n{{tag2}}\n', + { tag1: 'Hello', tag2: 'World' }, + {} + ), + 'Hello\n\n\nWorld\n', + 'Preservation of white space' + ); + + try { + Mustache.to_html( + '{{=tag1}}', + { tag1: 'Hello' }, + {} + ); + + ok(false); + } catch (e) { + equals(e.message, 'Unexpected end of document.'); + } + +}); + +test("Basic Variables", function() { + expect(3); + + // matches escaped.html + equals( + Mustache.to_html( + '

{{title}}

\nBut not {{entities}}.\n', + { + title: function() { + return "Bear > Shark"; + }, + entities: """ + }, + {} + ), + '

Bear > Shark

\nBut not ".\n', + 'HTML Escaping' + ); + + // matches null_string.html + equals( + Mustache.to_html( + 'Hello {{name}}\nglytch {{glytch}}\nbinary {{binary}}\nvalue {{value}}\nnumeric {{numeric}}', + { + name: "Elise", + glytch: true, + binary: false, + value: null, + numeric: function() { + return NaN; + } + }, + {} + ), + 'Hello Elise\nglytch true\nbinary false\nvalue \nnumeric NaN', + 'Different variable types' + ); + + // matches two_in_a_row.html + equals( + Mustache.to_html( + '{{greeting}}, {{name}}!', + { + name: "Joe", + greeting: "Welcome" + }, + {} + ), + 'Welcome, Joe!' + ); + +}); + +test("'{' or '&' (Unescaped Variable)", function() { + expect(2); + + // matches unescaped.html + equals( + Mustache.to_html( + '

{{{title}}}

', + { + title: function() { + return "Bear > Shark"; + } + }, + {} + ), + '

Bear > Shark

', + '{ character' + ); + + equals( + Mustache.to_html( + '

{{&title}}

', + { + title: function() { + return "Bear > Shark"; + } + }, + {} + ), + '

Bear > Shark

', + '& character' + ); +}); + +test("'#' (Sections)", function() { + expect(7); + + // matches array_of_partials_implicit_partial.html + equals( + Mustache.to_html( + 'Here is some stuff!\n{{#numbers}}\n{{>partial}}\n{{/numbers}}', + { numbers: ['1', '2', '3', '4'] }, + { partial: '{{.}}' } + ), + 'Here is some stuff!\n\n1\n\n2\n\n3\n\n4\n', + 'Array of Partials (Implicit)' + ); + + // matches array_of_partials_partial.html + equals( + Mustache.to_html( + 'Here is some stuff!\n{{#numbers}}\n{{>partial}}\n{{/numbers}}', + { numbers: [{i: '1'}, {i: '2'}, {i: '3'}, {i: '4'}] }, + { partial: '{{i}}' } + ), + 'Here is some stuff!\n\n1\n\n2\n\n3\n\n4\n', + 'Array of Partials (Explicit)' + ); + + // matches array_of_strings.html + equals( + Mustache.to_html( + '{{#array_of_strings}}{{.}} {{/array_of_strings}}', + {array_of_strings: ['hello', 'world']}, + {} + ), + 'hello world ', + 'Array of Strings' + ); + + // mathces higher_order_sections.html + equals( + Mustache.to_html( + '{{#bolder}}Hi {{name}}.{{/bolder}}\n', + { + "name": "Tater", + "helper": "To tinker?", + "bolder": function() { + return function(text, render) { + return "" + render(text) + ' ' + this.helper; + } + } + }, + {} + ), + 'Hi Tater. To tinker?\n' + ); + + // matches recursion_with_same_names.html + equals( + Mustache.to_html( + '{{ name }}\n{{ description }}\n\n{{#terms}}\n {{name}}\n {{index}}\n{{/terms}}\n', + { + name: 'name', + description: 'desc', + terms: [ + {name: 't1', index: 0}, + {name: 't2', index: 1}, + ] + }, + {} + ), + 'name\ndesc\n\n\n t1\n 0\n\n t2\n 1\n\n' + ); + + // matches reuse_of_enumerables.html + equals( + Mustache.to_html( + '{{#terms}}\n {{name}}\n {{index}}\n{{/terms}}\n{{#terms}}\n {{name}}\n {{index}}\n{{/terms}}\n', + { + terms: [ + {name: 't1', index: 0}, + {name: 't2', index: 1}, + ] + }, + {} + ), + '\n t1\n 0\n t2\n 1\n\n t1\n 0\n t2\n 1\n\n', + 'Lazy match of Section and Inverted Section' + ); + + // matches section_as_context.html + equals( + Mustache.to_html( + '{{#a_object}}\n

{{title}}

\n

{{description}}

\n \n{{/a_object}}\n', + { + a_object: { + title: 'this is an object', + description: 'one of its attributes is a list', + a_list: [{label: 'listitem1'}, {label: 'listitem2'}] + } + }, + {} + ), + '\n

this is an object

\n

one of its attributes is a list

\n \n', + 'Lazy match of Section and Inverted Section' + ); +}); + +test("'^' (Inverted Section)", function() { + expect(1); + + // matches inverted_section.html + equals( + Mustache.to_html( + '{{#repo}}{{name}}{{/repo}}\n{{^repo}}No repos :({{/repo}}\n', + { + "repo": [] + }, + {} + ), + '\nNo repos :(\n' + ); +}); + +test("'>' (Partials)", function() { + expect(5); + + // matches view_partial.html + equals( + Mustache.to_html( + '

{{greeting}}

\n{{>partial}}\n

{{farewell}}

', + { + greeting: function() { + return "Welcome"; + }, + + farewell: function() { + return "Fair enough, right?"; + }, + + partial: { + name: "Chris", + value: 10000, + taxed_value: function() { + return this.value - (this.value * 0.4); + }, + in_ca: true + } + }, + {partial: 'Hello {{name}}\nYou have just won ${{value}}!\n{{#in_ca}}\nWell, ${{ taxed_value }}, after taxes.\n{{/in_ca}}\n'} + ), + '

Welcome

\nHello Chris\nYou have just won $10000!\n\nWell, $6000, after taxes.\n\n\n

Fair enough, right?

' + ); + + // matches array_partial.html + equals( + Mustache.to_html( + '{{>partial}}', + { + partial: { + array: ['1', '2', '3', '4'] + } + }, + { partial: 'Here\'s a non-sense array of values\n{{#array}}\n {{.}}\n{{/array}}' } + ), + 'Here\'s a non-sense array of values\n\n 1\n\n 2\n\n 3\n\n 4\n' + ); + + // matches template_partial.html + equals( + Mustache.to_html( + '

{{title}}

\n{{>partial}}', + { + title: function() { + return "Welcome"; + }, + partial: { + again: "Goodbye" + } + }, + {partial:'Again, {{again}}!'} + ), + '

Welcome

\nAgain, Goodbye!' + ); + + // matches partial_recursion.html + equals( + Mustache.to_html( + '{{name}}\n{{#kids}}\n{{>partial}}\n{{/kids}}', + { + name: '1', + kids: [ + { + name: '1.1', + children: [ + {name: '1.1.1'} + ] + } + ] + }, + {partial:'{{name}}\n{{#children}}\n{{>partial}}\n{{/children}}'} + ), + '1\n\n1.1\n\n1.1.1\n\n\n' + ); + + try { + Mustache.to_html( + '{{>partial}}', + {}, + {partal: ''} + ); + ok(false); + } catch(e) { + equals(e.message, "Unknown partial 'partial'"); + } +}); + +test("'=' (Set Delimiter)", function() { + expect(1); + + // matches delimiter.html + equals( + Mustache.to_html( + '{{=<% %>=}}*\n<% first %>\n* <% second %>\n<%=| |=%>\n* | third |\n|={{ }}=|\n* {{ fourth }}', + { + first: "It worked the first time.", + second: "And it worked the second time.", + third: "Then, surprisingly, it worked the third time.", + fourth: "Fourth time also fine!." + }, + {} + ), + '*\nIt worked the first time.\n* And it worked the second time.\n\n* Then, surprisingly, it worked the third time.\n\n* Fourth time also fine!.', + 'Simple Set Delimiter' + ); +}); + +test("'!' (Comments)", function() { + expect(1); + + // matches comments.html + equals( + Mustache.to_html( + '

{{title}}{{! just something interesting... or not... }}

\n', + { + title: function() { + return "A Comedy of Errors"; + } + }, + {} + ), + '

A Comedy of Errors

\n' + ); +}); + +test("'%' (Pragmas)", function() { + expect(3); + + // matches array_of_strings_options.html + equals( + Mustache.to_html( + '{{%IMPLICIT-ITERATOR iterator=rob}}\n{{#array_of_strings_options}}{{rob}} {{/array_of_strings_options}}', + {array_of_strings_options: ['hello', 'world']}, + {} + ), + '\nhello world ', + 'IMPLICIT-ITERATOR pragma' + ); + + // matches unknown_pragma.txt + try { + equals( + Mustache.to_html( + '{{%I-HAVE-THE-GREATEST-MUSTACHE}}\n', + {}, + {} + ), + 'hello world ', + 'IMPLICIT-ITERATOR pragma' + ); + ok(false); + } catch (e) { + equals(e.message, 'This implementation of mustache doesn\'t understand the \'I-HAVE-THE-GREATEST-MUSTACHE\' pragma'); + } + + equals( + Mustache.to_html( + '{{%IMPLICIT-ITERATOR}}{{#dataSet}}{{.}}:{{/dataSet}}', + { dataSet: [ 'Object 1', 'Object 2', 'Object 3' ] }, + {} + ), + "Object 1:Object 2:Object 3:" + ); +}); + +test("Empty", function() { + expect(2); + + // matches empty_template.html + equals( + Mustache.to_html( + '

Test

', + {}, + {} + ), + '

Test

', + 'Empty Template' + ); + + // matches empty_partial.html + equals( + Mustache.to_html( + 'hey {{foo}}\n{{>partial}}\n', + { + foo: 1 + }, + {partial: 'yo'} + ), + 'hey 1\nyo\n', + 'Empty Partial' + ); +}); + +test("Demo", function() { + expect(2); + + // matches simple.html + equals( + Mustache.to_html( + 'Hello {{name}}\nYou have just won ${{value}}!\n{{#in_ca}}\nWell, ${{ taxed_value }}, after taxes.\n{{/in_ca}}', + { + name: "Chris", + value: 10000, + taxed_value: function() { + return this.value - (this.value * 0.4); + }, + in_ca: true + }, + {} + ), + 'Hello Chris\nYou have just won $10000!\n\nWell, $6000, after taxes.\n', + 'A simple template' + ); + + // matches complex.html + var template = [ + '

{{header}}

', + '{{#list}}', + ' ', + '{{/list}}', + '{{#empty}}', + '

The list is empty.

', + '{{/empty}}', + ].join('\n'); + + var view = { + header: function() { + return "Colors"; + }, + item: [ + {name: "red", current: true, url: "#Red"}, + {name: "green", current: false, url: "#Green"}, + {name: "blue", current: false, url: "#Blue"} + ], + link: function() { + return this["current"] !== true; + }, + list: function() { + return this.item.length !== 0; + }, + empty: function() { + return this.item.length === 0; + } + }; + + var expected_result = [ + '

Colors

', + ' ', + '' + ].join('\n'); + + equals( + Mustache.to_html( + template, + view, + {} + ), + expected_result, + 'A complex template' + ); +}); + +test("Regression Suite", function() { + expect(3); + + // matches bug_11_eating_whitespace.html + equals( + Mustache.to_html( + '{{tag}} foo', + { tag: "yo" }, + {} + ), + 'yo foo', + 'Issue 11' + ); + + // matches delimiters_partial.html + equals( + Mustache.to_html( + '{{#enumerate}}\n{{>partial}}\n{{/enumerate}}', + { enumerate: [ { text: 'A' }, { text: 'B' } ] }, + { partial: '{{=[[ ]]=}}\n{{text}}\n[[={{ }}=]]' } + ), + '\n\n{{text}}\n\n\n\n{{text}}\n\n', + 'Issue 44' + ); + + // matches bug_46_set_delimiter.html + equals( + Mustache.to_html( + '{{=[[ ]]=}}[[#IsMustacheAwesome]]mustache is awesome![[/IsMustacheAwesome]]', + {IsMustacheAwesome: true}, + {} + ), + 'mustache is awesome!', + 'Issue 46' + ); +});