| Index: pkg/mustache/test/mustache_test.dart
|
| diff --git a/pkg/mustache/test/mustache_test.dart b/pkg/mustache/test/mustache_test.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..bb020ebdd06c5a08fabb19eed5350bb5275e7bb3
|
| --- /dev/null
|
| +++ b/pkg/mustache/test/mustache_test.dart
|
| @@ -0,0 +1,293 @@
|
| +library mustache_test;
|
| +
|
| +import 'package:unittest/unittest.dart';
|
| +import 'package:mustache/mustache.dart';
|
| +
|
| +const MISMATCHED_TAG = 'Mismatched tag';
|
| +const UNEXPECTED_EOF = 'Unexpected end of input';
|
| +const BAD_VALUE_SECTION = 'Invalid value type for section';
|
| +const BAD_VALUE_INV_SECTION = 'Invalid value type for inverse section';
|
| +const BAD_TAG_NAME = 'Tag contained invalid characters in name';
|
| +const VALUE_NULL = 'Value was null or missing';
|
| +
|
| +main() {
|
| + group('Basic', () {
|
| + test('Variable', () {
|
| + var output = parse('_{{var}}_')
|
| + .renderString({"var": "bob"});
|
| + expect(output, equals('_bob_'));
|
| + });
|
| + test('Comment', () {
|
| + var output = parse('_{{! i am a comment ! }}_').renderString({});
|
| + expect(output, equals('__'));
|
| + });
|
| + });
|
| + group('Section', () {
|
| + test('Map', () {
|
| + var output = parse('{{#section}}_{{var}}_{{/section}}')
|
| + .renderString({"section": {"var": "bob"}});
|
| + expect(output, equals('_bob_'));
|
| + });
|
| + test('List', () {
|
| + var output = parse('{{#section}}_{{var}}_{{/section}}')
|
| + .renderString({"section": [{"var": "bob"}, {"var": "jim"}]});
|
| + expect(output, equals('_bob__jim_'));
|
| + });
|
| + test('Empty List', () {
|
| + var output = parse('{{#section}}_{{var}}_{{/section}}')
|
| + .renderString({"section": []});
|
| + expect(output, equals(''));
|
| + });
|
| + test('False', () {
|
| + var output = parse('{{#section}}_{{var}}_{{/section}}')
|
| + .renderString({"section": false});
|
| + expect(output, equals(''));
|
| + });
|
| + test('Invalid value', () {
|
| + var ex = renderFail(
|
| + '{{#section}}_{{var}}_{{/section}}',
|
| + {"section": 42});
|
| + expect(ex is FormatException, isTrue);
|
| + expect(ex.message, startsWith(BAD_VALUE_SECTION));
|
| + });
|
| + test('True', () {
|
| + var output = parse('{{#section}}_ok_{{/section}}')
|
| + .renderString({"section": true});
|
| + expect(output, equals('_ok_'));
|
| + });
|
| + test('Nested', () {
|
| + var output = parse('{{#section}}.{{var}}.{{#nested}}_{{nestedvar}}_{{/nested}}.{{/section}}')
|
| + .renderString({"section": {
|
| + "var": "bob",
|
| + "nested": [
|
| + {"nestedvar": "jim"},
|
| + {"nestedvar": "sally"}
|
| + ]
|
| + }});
|
| + expect(output, equals('.bob._jim__sally_.'));
|
| + });
|
| + });
|
| +
|
| + group('Inverse Section', () {
|
| + test('Map', () {
|
| + var output = parse('{{^section}}_{{var}}_{{/section}}')
|
| + .renderString({"section": {"var": "bob"}});
|
| + expect(output, equals(''));
|
| + });
|
| + test('List', () {
|
| + var output = parse('{{^section}}_{{var}}_{{/section}}')
|
| + .renderString({"section": [{"var": "bob"}, {"var": "jim"}]});
|
| + expect(output, equals(''));
|
| + });
|
| + test('Empty List', () {
|
| + var output = parse('{{^section}}_ok_{{/section}}')
|
| + .renderString({"section": []});
|
| + expect(output, equals('_ok_'));
|
| + });
|
| + test('False', () {
|
| + var output = parse('{{^section}}_ok_{{/section}}')
|
| + .renderString({"section": false});
|
| + expect(output, equals('_ok_'));
|
| + });
|
| + test('Invalid value', () {
|
| + var ex = renderFail(
|
| + '{{^section}}_{{var}}_{{/section}}',
|
| + {"section": 42});
|
| + expect(ex is FormatException, isTrue);
|
| + expect(ex.message, startsWith(BAD_VALUE_INV_SECTION));
|
| + });
|
| + test('True', () {
|
| + var output = parse('{{^section}}_ok_{{/section}}')
|
| + .renderString({"section": true});
|
| + expect(output, equals(''));
|
| + });
|
| + });
|
| +
|
| + group('Html escape', () {
|
| +
|
| + test('Escape at start', () {
|
| + var output = parse('_{{var}}_')
|
| + .renderString({"var": "&."});
|
| + expect(output, equals('_&._'));
|
| + });
|
| +
|
| + test('Escape at end', () {
|
| + var output = parse('_{{var}}_')
|
| + .renderString({"var": ".&"});
|
| + expect(output, equals('_.&_'));
|
| + });
|
| +
|
| + test('&', () {
|
| + var output = parse('_{{var}}_')
|
| + .renderString({"var": "&"});
|
| + expect(output, equals('_&_'));
|
| + });
|
| +
|
| + test('<', () {
|
| + var output = parse('_{{var}}_')
|
| + .renderString({"var": "<"});
|
| + expect(output, equals('_<_'));
|
| + });
|
| +
|
| + test('>', () {
|
| + var output = parse('_{{var}}_')
|
| + .renderString({"var": ">"});
|
| + expect(output, equals('_>_'));
|
| + });
|
| +
|
| + test('"', () {
|
| + var output = parse('_{{var}}_')
|
| + .renderString({"var": '"'});
|
| + expect(output, equals('_"_'));
|
| + });
|
| +
|
| + test("'", () {
|
| + var output = parse('_{{var}}_')
|
| + .renderString({"var": "'"});
|
| + expect(output, equals('_'_'));
|
| + });
|
| +
|
| + test("/", () {
|
| + var output = parse('_{{var}}_')
|
| + .renderString({"var": "/"});
|
| + expect(output, equals('_/_'));
|
| + });
|
| +
|
| + });
|
| +
|
| + group('Invalid format', () {
|
| + test('Mismatched tag', () {
|
| + var source = '{{#section}}_{{var}}_{{/notsection}}';
|
| + var ex = renderFail(source, {"section": {"var": "bob"}});
|
| + expectFail(ex, 1, 25, 'Mismatched tag');
|
| + });
|
| +
|
| + test('Unexpected EOF', () {
|
| + var source = '{{#section}}_{{var}}_{{/section';
|
| + var ex = renderFail(source, {"section": {"var": "bob"}});
|
| + expectFail(ex, 1, source.length + 2, UNEXPECTED_EOF);
|
| + });
|
| +
|
| + test('Bad tag name, open section', () {
|
| + var source = r'{{#section$%$^%}}_{{var}}_{{/section}}';
|
| + var ex = renderFail(source, {"section": {"var": "bob"}});
|
| + expectFail(ex, null, null, BAD_TAG_NAME);
|
| + });
|
| +
|
| + test('Bad tag name, close section', () {
|
| + var source = r'{{#section}}_{{var}}_{{/section$%$^%}}';
|
| + var ex = renderFail(source, {"section": {"var": "bob"}});
|
| + expectFail(ex, null, null, BAD_TAG_NAME);
|
| + });
|
| +
|
| + test('Bad tag name, variable', () {
|
| + var source = r'{{#section}}_{{var$%$^%}}_{{/section}}';
|
| + var ex = renderFail(source, {"section": {"var": "bob"}});
|
| + expectFail(ex, null, null, BAD_TAG_NAME);
|
| + });
|
| +
|
| + });
|
| +
|
| + group('Lenient', () {
|
| + test('Odd section name', () {
|
| + var output = parse(r'{{#section$%$^%}}_{{var}}_{{/section$%$^%}}', lenient: true)
|
| + .renderString({r'section$%$^%': {'var': 'bob'}}, lenient: true);
|
| + expect(output, equals('_bob_'));
|
| + });
|
| +
|
| + test('Odd variable name', () {
|
| + var output = parse(r'{{#section}}_{{var$%$^%}}_{{/section}}', lenient: true)
|
| + .renderString({'section': {r'var$%$^%': 'bob'}}, lenient: true);
|
| + });
|
| +
|
| + test('Null variable', () {
|
| + var output = parse(r'{{#section}}_{{var}}_{{/section}}', lenient: true)
|
| + .renderString({'section': {'var': null}}, lenient: true);
|
| + expect(output, equals('__'));
|
| + });
|
| +
|
| + test('Null section', () {
|
| + var output = parse('{{#section}}_{{var}}_{{/section}}', lenient: true)
|
| + .renderString({"section": null}, lenient: true);
|
| + expect(output, equals(''));
|
| + });
|
| +
|
| +// Known failure
|
| +// test('Null inverse section', () {
|
| +// var output = parse('{{^section}}_{{var}}_{{/section}}', lenient: true)
|
| +// .renderString({"section": null}, lenient: true);
|
| +// expect(output, equals(''));
|
| +// });
|
| +
|
| + });
|
| +
|
| + group('Escape tags', () {
|
| + test('{{{ ... }}}', () {
|
| + var output = parse('{{{blah}}}')
|
| + .renderString({'blah': '&'});
|
| + expect(output, equals('&'));
|
| + });
|
| + test('{{& ... }}', () {
|
| + var output = parse('{{{blah}}}')
|
| + .renderString({'blah': '&'});
|
| + expect(output, equals('&'));
|
| + });
|
| + });
|
| +
|
| + group('Patial tag', () {
|
| + test('Unimplemented', () {
|
| + var fn = () => parse('{{>partial}}').renderString({});
|
| + expect(fn, throwsUnimplementedError);
|
| + });
|
| + });
|
| +
|
| + group('Other', () {
|
| + test('Standalone line', () {
|
| + var val = parse('|\n{{#bob}}\n{{/bob}}\n|').renderString({'bob': []});
|
| + expect(val, equals('|\n|'));
|
| + });
|
| + });
|
| +
|
| + group('Array indexing', () {
|
| + test('Basic', () {
|
| + var val = parse('{{array.1}}').renderString({'array': [1, 2, 3]});
|
| + expect(val, equals('2'));
|
| + });
|
| + test('RangeError', () {
|
| + var error = renderFail('{{array.5}}', {'array': [1, 2, 3]});
|
| + expect(error, isRangeError);
|
| + });
|
| + });
|
| +
|
| + group('Mirrors', () {
|
| + test('Simple field', () {
|
| + var output = parse('_{{bar}}_')
|
| + .renderString(new Foo()..bar = 'bob');
|
| + expect(output, equals('_bob_'));
|
| + });
|
| + });
|
| +}
|
| +
|
| +renderFail(source, values) {
|
| + try {
|
| + parse(source).renderString(values);
|
| + return null;
|
| + } catch (e) {
|
| + return e;
|
| + }
|
| +}
|
| +
|
| +expectFail(ex, int line, int column, [String msgStartsWith]) {
|
| + expect(ex, isFormatException);
|
| + expect(ex is MustacheFormatException, isTrue);
|
| + if (line != null)
|
| + expect(ex.line, equals(line));
|
| + if (column != null)
|
| + expect(ex.column, equals(column));
|
| + if (msgStartsWith != null)
|
| + expect(ex.message, startsWith(msgStartsWith));
|
| +}
|
| +
|
| +class Foo {
|
| + String bar;
|
| +}
|
|
|