platform/packages/jael/jael2/test/render/render_test.dart

358 lines
6.8 KiB
Dart
Raw Normal View History

2017-09-29 22:39:37 +00:00
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';
2021-04-29 07:21:31 +00:00
void main() {
2017-09-29 22:39:37 +00:00
test('attribute binding', () {
const template = '''
<html>
<body>
<h1>Hello</h1>
2017-10-16 22:48:35 +00:00
<img ready="always" data-img-src=profile['avatar'] />
2017-10-17 05:14:51 +00:00
<input name="csrf_token" type="hidden" value=csrf_token>
2017-09-29 22:39:37 +00:00
</body>
</html>
''';
2019-07-29 22:12:52 +00:00
var buf = CodeBuffer();
2021-04-28 00:37:33 +00:00
jael.Document? document;
late SymbolTable scope;
2017-10-16 22:48:35 +00:00
try {
2019-07-29 22:01:24 +00:00
document = jael.parseDocument(template, sourceUrl: 'test.jael');
2019-07-29 22:12:52 +00:00
scope = SymbolTable<dynamic>(values: {
2017-10-17 05:14:51 +00:00
'csrf_token': 'foo',
2017-10-16 22:48:35 +00:00
'profile': {
'avatar': 'thosakwe.png',
}
});
2018-04-03 05:04:34 +00:00
} on jael.JaelError catch (e) {
2017-10-16 22:48:35 +00:00
print(e);
print(e.stackTrace);
}
2017-09-29 22:39:37 +00:00
2017-10-16 22:48:35 +00:00
expect(document, isNotNull);
2021-04-28 00:37:33 +00:00
const jael.Renderer().render(document!, buf, scope);
2017-09-29 22:39:37 +00:00
print(buf);
expect(
buf.toString(),
'''
<html>
<body>
<h1>
Hello
</h1>
2017-10-16 22:48:35 +00:00
<img ready="always" data-img-src="thosakwe.png">
2017-10-17 05:14:51 +00:00
<input name="csrf_token" type="hidden" value="foo">
2017-09-29 22:39:37 +00:00
</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>
''';
2019-07-29 22:12:52 +00:00
var buf = CodeBuffer();
2019-07-29 22:01:24 +00:00
//jael.scan(template, sourceUrl: 'test.jael').tokens.forEach(print);
2021-04-28 00:37:33 +00:00
var document = jael.parseDocument(template, sourceUrl: 'test.jael')!;
2019-07-29 22:12:52 +00:00
var scope = SymbolTable<dynamic>(values: {
2017-09-29 22:39:37 +00:00
'pokemon': const _Pokemon('Darkrai', 'Dark'),
});
const jael.Renderer().render(document, buf, scope);
print(buf);
expect(
2018-04-03 05:04:34 +00:00
buf.toString().replaceAll('\n', '').replaceAll(' ', '').trim(),
2017-09-29 22:39:37 +00:00
'''
<!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
2018-04-03 18:07:34 +00:00
<img/>
2017-09-29 22:39:37 +00:00
</body>
</html>
'''
2018-04-03 05:04:34 +00:00
.replaceAll('\n', '')
.replaceAll(' ', '')
2017-09-29 22:39:37 +00:00
.trim());
});
test('for loop', () {
const template = '''
<html>
<body>
<h1>Pokémon</h1>
<ul>
2018-06-27 23:54:43 +00:00
<li for-each=starters as="starter" index-as="idx">#{{ idx }} {{ starter.name }} - {{ starter.type }}</li>
2017-09-29 22:39:37 +00:00
</ul>
</body>
</html>
''';
2019-07-29 22:12:52 +00:00
var buf = CodeBuffer();
2021-04-28 00:37:33 +00:00
var document = jael.parseDocument(template, sourceUrl: 'test.jael')!;
2019-07-29 22:12:52 +00:00
var scope = SymbolTable<dynamic>(values: {
2017-09-29 22:39:37 +00:00
'starters': starters,
});
const jael.Renderer().render(document, buf, scope);
print(buf);
expect(
buf.toString(),
'''
<html>
<body>
<h1>
Pokémon
</h1>
<ul>
<li>
2018-06-27 23:54:43 +00:00
#0 Bulbasaur - Grass
2017-09-29 22:39:37 +00:00
</li>
<li>
2018-06-27 23:54:43 +00:00
#1 Charmander - Fire
2017-09-29 22:39:37 +00:00
</li>
<li>
2018-06-27 23:54:43 +00:00
#2 Squirtle - Water
2017-09-29 22:39:37 +00:00
</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>
''';
2019-07-29 22:12:52 +00:00
var buf = CodeBuffer();
2021-04-28 00:37:33 +00:00
var document = jael.parseDocument(template, sourceUrl: 'test.jael')!;
2019-07-29 22:12:52 +00:00
var scope = SymbolTable<dynamic>(values: {
2017-09-29 22:39:37 +00:00
'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());
});
2017-10-02 15:46:00 +00:00
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>
''';
2019-07-29 22:12:52 +00:00
var buf = CodeBuffer();
2021-04-28 00:37:33 +00:00
var document = jael.parseDocument(template, sourceUrl: 'test.jael')!;
2019-07-29 22:12:52 +00:00
var scope = SymbolTable();
2017-10-02 15:46:00 +00:00
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>
''';
2019-07-29 22:12:52 +00:00
var buf = CodeBuffer();
2021-04-28 00:37:33 +00:00
var document = jael.parseDocument(template, sourceUrl: 'test.jael')!;
2019-07-29 22:12:52 +00:00
var scope = SymbolTable();
2017-10-02 15:46:00 +00:00
const jael.Renderer().render(document, buf, scope);
print(buf);
expect(
2018-04-03 18:07:34 +00:00
buf.toString().replaceAll('\n', '').replaceAll(' ', '').trim(),
2017-10-02 15:46:00 +00:00
'''
<div>
<img src="<SCARY XSS>">
<MORE SCARY XSS>
</div>
'''
2018-04-03 18:07:34 +00:00
.replaceAll('\n', '')
.replaceAll(' ', '')
2017-10-02 15:46:00 +00:00
.trim());
});
test('quoted attribute name', () {
const template = '''
<button '(click)'="myEventHandler(\$event)"></button>
''';
2019-07-29 22:12:52 +00:00
var buf = CodeBuffer();
2021-04-28 00:37:33 +00:00
var document = jael.parseDocument(template, sourceUrl: 'test.jael')!;
2019-07-29 22:12:52 +00:00
var scope = SymbolTable();
2017-10-02 15:46:00 +00:00
const jael.Renderer().render(document, buf, scope);
print(buf);
expect(
buf.toString(),
'''
<button (click)="myEventHandler(\$event)">
</button>
'''
.trim());
});
2017-10-02 16:29:13 +00:00
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>
''';
2019-07-29 22:12:52 +00:00
var buf = CodeBuffer();
2021-04-28 00:37:33 +00:00
var document = jael.parseDocument(template, sourceUrl: 'test.jael')!;
2019-07-29 22:12:52 +00:00
var scope = SymbolTable<dynamic>(values: {
'account': _Account(isDisabled: true),
2017-10-02 16:29:13 +00:00
});
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>
''';
2019-07-29 22:12:52 +00:00
var buf = CodeBuffer();
2021-04-28 00:37:33 +00:00
var document = jael.parseDocument(template, sourceUrl: 'test.jael')!;
2019-07-29 22:12:52 +00:00
var scope = SymbolTable<dynamic>(values: {
'account': _Account(isDisabled: null),
2017-10-02 16:29:13 +00:00
});
const jael.Renderer().render(document, buf, scope);
print(buf);
expect(buf.toString().trim(), 'Weird...');
});
2017-09-29 22:39:37 +00:00
}
2019-07-29 22:12:52 +00:00
const List<_Pokemon> starters = [
_Pokemon('Bulbasaur', 'Grass'),
_Pokemon('Charmander', 'Fire'),
_Pokemon('Squirtle', 'Water'),
2017-09-29 22:39:37 +00:00
];
class _Pokemon {
final String name, type;
const _Pokemon(this.name, this.type);
}
2017-10-02 16:29:13 +00:00
class _Account {
2021-04-28 00:37:33 +00:00
final bool? isDisabled;
2017-10-02 16:29:13 +00:00
_Account({this.isDisabled});
}