blob: cde7bb87929f56211ccac47ed8fa0df64f92118f [file] [log] [blame]
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('Section', () {
test('Map', () {
var output = parse('{{#section}}_{{var}}_{{/section}}')
.render({"section": {"var": "bob"}});
expect(output, equals('_bob_'));
});
test('List', () {
var output = parse('{{#section}}_{{var}}_{{/section}}')
.render({"section": [{"var": "bob"}, {"var": "jim"}]});
expect(output, equals('_bob__jim_'));
});
test('Empty List', () {
var output = parse('{{#section}}_{{var}}_{{/section}}')
.render({"section": []});
expect(output, equals(''));
});
test('False', () {
var output = parse('{{#section}}_{{var}}_{{/section}}')
.render({"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}}')
.render({"section": true});
expect(output, equals('_ok_'));
});
test('Nested', () {
var output = parse('{{#section}}.{{var}}.{{#nested}}_{{nestedvar}}_{{/nested}}.{{/section}}')
.render({"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}}')
.render({"section": {"var": "bob"}});
expect(output, equals(''));
});
test('List', () {
var output = parse('{{^section}}_{{var}}_{{/section}}')
.render({"section": [{"var": "bob"}, {"var": "jim"}]});
expect(output, equals(''));
});
test('Empty List', () {
var output = parse('{{^section}}_ok_{{/section}}')
.render({"section": []});
expect(output, equals('_ok_'));
});
test('False', () {
var output = parse('{{^section}}_ok_{{/section}}')
.render({"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}}')
.render({"section": true});
expect(output, equals(''));
});
});
group('Html escape', () {
test('Escape at start', () {
var output = parse('_{{var}}_')
.render({"var": "&."});
expect(output, equals('_&._'));
});
test('Escape at end', () {
var output = parse('_{{var}}_')
.render({"var": ".&"});
expect(output, equals('_.&_'));
});
test('&', () {
var output = parse('_{{var}}_')
.render({"var": "&"});
expect(output, equals('_&_'));
});
test('<', () {
var output = parse('_{{var}}_')
.render({"var": "<"});
expect(output, equals('_&lt;_'));
});
test('>', () {
var output = parse('_{{var}}_')
.render({"var": ">"});
expect(output, equals('_&gt;_'));
});
test('"', () {
var output = parse('_{{var}}_')
.render({"var": '"'});
expect(output, equals('_&quot;_'));
});
test("'", () {
var output = parse('_{{var}}_')
.render({"var": "'"});
expect(output, equals('_&#x27;_'));
});
test("/", () {
var output = parse('_{{var}}_')
.render({"var": "/"});
expect(output, equals('_&#x2F;_'));
});
});
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);
});
test('Null section', () {
var source = '{{#section}}_{{var}}_{{/section}}';
var ex = renderFail(source, {'section': null});
expectFail(ex, null, null, VALUE_NULL);
});
test('Null inverse section', () {
var source = '{{^section}}_{{var}}_{{/section}}';
var ex = renderFail(source, {'section': null});
expectFail(ex, null, null, VALUE_NULL);
});
test('Null variable', () {
var source = '{{#section}}_{{var}}_{{/section}}';
var ex = renderFail(source, {'section': {'var': null}});
expectFail(ex, null, null, VALUE_NULL);
});
});
group('Lenient', () {
test('Odd section name', () {
var output = parse(r'{{#section$%$^%}}_{{var}}_{{/section$%$^%}}', lenient: true)
.render({r'section$%$^%': {'var': 'bob'}}, lenient: true);
expect(output, equals('_bob_'));
});
test('Odd variable name', () {
var output = parse(r'{{#section}}_{{var$%$^%}}_{{/section}}', lenient: true)
.render({'section': {r'var$%$^%': 'bob'}}, lenient: true);
});
test('Null variable', () {
var output = parse(r'{{#section}}_{{var}}_{{/section}}', lenient: true)
.render({'section': {'var': null}}, lenient: true);
expect(output, equals('__'));
});
test('Null section', () {
var output = parse('{{#section}}_{{var}}_{{/section}}', lenient: true)
.render({"section": null}, lenient: true);
expect(output, equals(''));
});
test('Null inverse section', () {
var output = parse('{{^section}}_{{var}}_{{/section}}', lenient: true)
.render({"section": null}, lenient: true);
expect(output, equals(''));
});
});
}
renderFail(source, values) {
try {
parse(source).render(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));
}