platform/packages/jael/jael2/test/render/render_test.dart
2021-05-15 17:38:15 +08:00

357 lines
6.8 KiB
Dart

import 'package:code_buffer/code_buffer.dart';
import 'package:jael/jael.dart' as jael;
import 'package:symbol_table/symbol_table.dart';
import 'package:test/test.dart';
void main() {
test('attribute binding', () {
const template = '''
<html>
<body>
<h1>Hello</h1>
<img ready="always" data-img-src=profile['avatar'] />
<input name="csrf_token" type="hidden" value=csrf_token>
</body>
</html>
''';
var buf = CodeBuffer();
jael.Document? document;
late SymbolTable scope;
try {
document = jael.parseDocument(template, sourceUrl: 'test.jael');
scope = SymbolTable<dynamic>(values: {
'csrf_token': 'foo',
'profile': {
'avatar': 'thosakwe.png',
}
});
} on jael.JaelError catch (e) {
print(e);
print(e.stackTrace);
}
expect(document, isNotNull);
const jael.Renderer().render(document!, buf, scope);
print(buf);
expect(
buf.toString(),
'''
<html>
<body>
<h1>
Hello
</h1>
<img ready="always" data-img-src="thosakwe.png">
<input name="csrf_token" type="hidden" value="foo">
</body>
</html>
'''
.trim());
});
test('interpolation', () {
const template = '''
<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<body>
<h1>Pokémon</h1>
{{ pokemon.name }} - {{ pokemon.type }}
<img>
</body>
</html>
''';
var buf = CodeBuffer();
//jael.scan(template, sourceUrl: 'test.jael').tokens.forEach(print);
var document = jael.parseDocument(template, sourceUrl: 'test.jael')!;
var scope = SymbolTable<dynamic>(values: {
'pokemon': const _Pokemon('Darkrai', 'Dark'),
});
const jael.Renderer().render(document, buf, scope);
print(buf);
expect(
buf.toString().replaceAll('\n', '').replaceAll(' ', '').trim(),
'''
<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<body>
<h1>
Pokémon
</h1>
Darkrai - Dark
<img/>
</body>
</html>
'''
.replaceAll('\n', '')
.replaceAll(' ', '')
.trim());
});
test('for loop', () {
const template = '''
<html>
<body>
<h1>Pokémon</h1>
<ul>
<li for-each=starters as="starter" index-as="idx">#{{ idx }} {{ starter.name }} - {{ starter.type }}</li>
</ul>
</body>
</html>
''';
var buf = CodeBuffer();
var document = jael.parseDocument(template, sourceUrl: 'test.jael')!;
var scope = SymbolTable<dynamic>(values: {
'starters': starters,
});
const jael.Renderer().render(document, buf, scope);
print(buf);
expect(
buf.toString(),
'''
<html>
<body>
<h1>
Pokémon
</h1>
<ul>
<li>
#0 Bulbasaur - Grass
</li>
<li>
#1 Charmander - Fire
</li>
<li>
#2 Squirtle - Water
</li>
</ul>
</body>
</html>
'''
.trim());
});
test('conditional', () {
const template = '''
<html>
<body>
<h1>Conditional</h1>
<b if=starters.isEmpty>Empty</b>
<b if=starters.isNotEmpty>Not empty</b>
</body>
</html>
''';
var buf = CodeBuffer();
var document = jael.parseDocument(template, sourceUrl: 'test.jael')!;
var scope = SymbolTable<dynamic>(values: {
'starters': starters,
});
const jael.Renderer().render(document, buf, scope);
print(buf);
expect(
buf.toString(),
'''
<html>
<body>
<h1>
Conditional
</h1>
<b>
Not empty
</b>
</body>
</html>
'''
.trim());
});
test('declare', () {
const template = '''
<div>
<declare one=1 two=2 three=3>
<ul>
<li>{{one}}</li>
<li>{{two}}</li>
<li>{{three}}</li>
</ul>
<ul>
<declare three=4>
<li>{{one}}</li>
<li>{{two}}</li>
<li>{{three}}</li>
</declare>
</ul>
</declare>
</div>
''';
var buf = CodeBuffer();
var document = jael.parseDocument(template, sourceUrl: 'test.jael')!;
var scope = SymbolTable();
const jael.Renderer().render(document, buf, scope);
print(buf);
expect(
buf.toString(),
'''
<div>
<ul>
<li>
1
</li>
<li>
2
</li>
<li>
3
</li>
</ul>
<ul>
<li>
1
</li>
<li>
2
</li>
<li>
4
</li>
</ul>
</div>
'''
.trim());
});
test('unescaped attr/interp', () {
const template = '''
<div>
<img src!="<SCARY XSS>" />
{{- "<MORE SCARY XSS>" }}
</div>
''';
var buf = CodeBuffer();
var document = jael.parseDocument(template, sourceUrl: 'test.jael')!;
var scope = SymbolTable();
const jael.Renderer().render(document, buf, scope);
print(buf);
expect(
buf.toString().replaceAll('\n', '').replaceAll(' ', '').trim(),
'''
<div>
<img src="<SCARY XSS>">
<MORE SCARY XSS>
</div>
'''
.replaceAll('\n', '')
.replaceAll(' ', '')
.trim());
});
test('quoted attribute name', () {
const template = '''
<button '(click)'="myEventHandler(\$event)"></button>
''';
var buf = CodeBuffer();
var document = jael.parseDocument(template, sourceUrl: 'test.jael')!;
var scope = SymbolTable();
const jael.Renderer().render(document, buf, scope);
print(buf);
expect(
buf.toString(),
'''
<button (click)="myEventHandler(\$event)">
</button>
'''
.trim());
});
test('switch', () {
const template = '''
<switch value=account.isDisabled>
<case value=true>
BAN HAMMER LOLOL
</case>
<case value=false>
You are in good standing.
</case>
<default>
Weird...
</default>
</switch>
''';
var buf = CodeBuffer();
var document = jael.parseDocument(template, sourceUrl: 'test.jael')!;
var scope = SymbolTable<dynamic>(values: {
'account': _Account(isDisabled: true),
});
const jael.Renderer().render(document, buf, scope);
print(buf);
expect(buf.toString().trim(), 'BAN HAMMER LOLOL');
});
test('default', () {
const template = '''
<switch value=account.isDisabled>
<case value=true>
BAN HAMMER LOLOL
</case>
<case value=false>
You are in good standing.
</case>
<default>
Weird...
</default>
</switch>
''';
var buf = CodeBuffer();
var document = jael.parseDocument(template, sourceUrl: 'test.jael')!;
var scope = SymbolTable<dynamic>(values: {
'account': _Account(isDisabled: null),
});
const jael.Renderer().render(document, buf, scope);
print(buf);
expect(buf.toString().trim(), 'Weird...');
});
}
const List<_Pokemon> starters = [
_Pokemon('Bulbasaur', 'Grass'),
_Pokemon('Charmander', 'Fire'),
_Pokemon('Squirtle', 'Water'),
];
class _Pokemon {
final String name, type;
const _Pokemon(this.name, this.type);
}
class _Account {
final bool? isDisabled;
_Account({this.isDisabled});
}