blob: 81cc53381a367dda76af6c974132514043263474 [file] [log] [blame]
Armin Ronacherecc051b2007-06-01 18:25:28 +02001# -*- coding: utf-8 -*-
2"""
3 unit test for expression syntax
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
6 :copyright: 2007 by Armin Ronacher.
7 :license: BSD, see LICENSE for more details.
8"""
Christoph Hacke9e43bb2008-04-13 23:35:48 +02009from jinja2 import Environment, DictLoader
10from jinja2.exceptions import TemplateSyntaxError
Armin Ronacher1cc232c2007-09-07 17:52:41 +020011
Armin Ronacherecc051b2007-06-01 18:25:28 +020012
13CALL = '''{{ foo('a', c='d', e='f', *['b'], **{'g': 'h'}) }}'''
14SLICING = '''{{ [1, 2, 3][:] }}|{{ [1, 2, 3][::-1] }}'''
15ATTR = '''{{ foo.bar }}|{{ foo['bar'] }}'''
16SUBSCRIPT = '''{{ foo[0] }}|{{ foo[-1] }}'''
17KEYATTR = '''{{ {'items': 'foo'}.items }}|{{ {}.items() }}'''
Armin Ronacher1cc232c2007-09-07 17:52:41 +020018TUPLE = '''{{ () }}|{{ (1,) }}|{{ (1, 2) }}'''
Armin Ronacherecc051b2007-06-01 18:25:28 +020019MATH = '''{{ (1 + 1 * 2) - 3 / 2 }}|{{ 2**3 }}'''
20DIV = '''{{ 3 // 2 }}|{{ 3 / 2 }}|{{ 3 % 2 }}'''
21UNARY = '''{{ +3 }}|{{ -3 }}'''
Armin Ronacher1cc232c2007-09-07 17:52:41 +020022CONCAT = '''{{ [1, 2] ~ 'foo' }}'''
Armin Ronacherecc051b2007-06-01 18:25:28 +020023COMPARE = '''{{ 1 > 0 }}|{{ 1 >= 1 }}|{{ 2 < 3 }}|{{ 2 == 2 }}|{{ 1 <= 1 }}'''
Armin Ronacher1cc232c2007-09-07 17:52:41 +020024INOP = '''{{ 1 in [1, 2, 3] }}|{{ 1 not in [1, 2, 3] }}'''
25LITERALS = '''{{ [] }}|{{ {} }}|{{ () }}|{{ '' }}|{{ @() }}'''
Armin Ronacherecc051b2007-06-01 18:25:28 +020026BOOL = '''{{ true and false }}|{{ false or true }}|{{ not false }}'''
Armin Ronacherdb69d0a2007-06-02 01:35:53 +020027GROUPING = '''{{ (true and false) or (false and true) and not false }}'''
Armin Ronacher1cc232c2007-09-07 17:52:41 +020028CONDEXPR = '''{{ 0 if true else 1 }}'''
29DJANGOATTR = '''{{ [1, 2, 3].0 }}'''
30FILTERPRIORITY = '''{{ "foo"|upper + "bar"|upper }}'''
Armin Ronacher1dcdac52007-12-09 22:53:46 +010031REGEX = r'''{{ @/\S+/.findall('foo bar baz') }}'''
Armin Ronacher1cc232c2007-09-07 17:52:41 +020032TUPLETEMPLATES = [
33 '{{ () }}',
34 '{{ (1, 2) }}',
35 '{{ (1, 2,) }}',
36 '{{ 1, }}',
37 '{{ 1, 2 }}',
38 '{% for foo, bar in seq %}...{% endfor %}',
39 '{% for x in foo, bar %}...{% endfor %}',
40 '{% for x in foo, %}...{% endfor %}',
41 '{% for x in foo, recursive %}...{% endfor %}',
42 '{% for x in foo, bar recursive %}...{% endfor %}',
43 '{% for x, in foo, recursive %}...{% endfor %}'
44]
45TRAILINGCOMMA = '''{{ (1, 2,) }}|{{ [1, 2,] }}|{{ {1: 2,} }}|{{ @(1, 2,) }}'''
Armin Ronacherecc051b2007-06-01 18:25:28 +020046
47
48def test_call():
Christoph Hacke9e43bb2008-04-13 23:35:48 +020049 from jinja2 import Environment
Armin Ronacherecc051b2007-06-01 18:25:28 +020050 env = Environment()
51 env.globals['foo'] = lambda a, b, c, e, g: a + b + c + e + g
52 tmpl = env.from_string(CALL)
53 assert tmpl.render() == 'abdfh'
54
55
56def test_slicing(env):
57 tmpl = env.from_string(SLICING)
58 assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]'
59
60
61def test_attr(env):
62 tmpl = env.from_string(ATTR)
63 assert tmpl.render(foo={'bar': 42}) == '42|42'
64
65
66def test_subscript(env):
67 tmpl = env.from_string(SUBSCRIPT)
68 assert tmpl.render(foo=[0, 1, 2]) == '0|2'
69
70
71def test_keyattr(env):
72 tmpl = env.from_string(KEYATTR)
73 assert tmpl.render() == 'foo|[]'
74
75
76def test_tuple(env):
77 tmpl = env.from_string(TUPLE)
Armin Ronacher1cc232c2007-09-07 17:52:41 +020078 assert tmpl.render() == '()|(1,)|(1, 2)'
Armin Ronacherecc051b2007-06-01 18:25:28 +020079
80
81def test_math(env):
82 tmpl = env.from_string(MATH)
83 assert tmpl.render() == '1.5|8'
84
85
86def test_div(env):
87 tmpl = env.from_string(DIV)
88 assert tmpl.render() == '1|1.5|1'
89
90
91def test_unary(env):
92 tmpl = env.from_string(UNARY)
93 assert tmpl.render() == '3|-3'
94
95
Armin Ronacher1cc232c2007-09-07 17:52:41 +020096def test_concat(env):
97 tmpl = env.from_string(CONCAT)
98 assert tmpl.render() == '[1, 2]foo'
99
100
Armin Ronacherecc051b2007-06-01 18:25:28 +0200101def test_compare(env):
102 tmpl = env.from_string(COMPARE)
103 assert tmpl.render() == 'True|True|True|True|True'
104
105
Armin Ronacher1cc232c2007-09-07 17:52:41 +0200106def test_inop(env):
107 tmpl = env.from_string(INOP)
108 assert tmpl.render() == 'True|False'
109
110
Armin Ronacherecc051b2007-06-01 18:25:28 +0200111def test_literals(env):
112 tmpl = env.from_string(LITERALS)
Armin Ronacher1dcdac52007-12-09 22:53:46 +0100113 assert tmpl.render().lower() == '[]|{}|()||set([])'
Armin Ronacherecc051b2007-06-01 18:25:28 +0200114
115
116def test_bool(env):
117 tmpl = env.from_string(BOOL)
118 assert tmpl.render() == 'False|True|True'
Armin Ronacherdb69d0a2007-06-02 01:35:53 +0200119
120
121def test_grouping(env):
122 tmpl = env.from_string(GROUPING)
123 assert tmpl.render() == 'False'
Armin Ronacher1cc232c2007-09-07 17:52:41 +0200124
125
126def test_django_attr(env):
127 tmpl = env.from_string(DJANGOATTR)
128 assert tmpl.render() == '1'
129
130
131def test_conditional_expression(env):
132 tmpl = env.from_string(CONDEXPR)
133 assert tmpl.render() == '0'
134
135
136def test_filter_priority(env):
137 tmpl = env.from_string(FILTERPRIORITY)
138 assert tmpl.render() == 'FOOBAR'
139
140
141def test_function_calls(env):
142 tests = [
143 (True, '*foo, bar'),
144 (True, '*foo, *bar'),
145 (True, '*foo, bar=42'),
146 (True, '**foo, *bar'),
147 (True, '**foo, bar'),
148 (False, 'foo, bar'),
149 (False, 'foo, bar=42'),
150 (False, 'foo, bar=23, *args'),
151 (False, 'a, b=c, *d, **e'),
152 (False, '*foo, **bar')
153 ]
154 for should_fail, sig in tests:
155 if should_fail:
156 try:
157 print env.from_string('{{ foo(%s) }}' % sig)
158 except TemplateSyntaxError:
159 continue
160 assert False, 'expected syntax error'
161 else:
162 env.from_string('foo(%s)' % sig)
163
164
165def test_regex(env):
166 tmpl = env.from_string(REGEX)
167 assert tmpl.render() == "['foo', 'bar', 'baz']"
168
169
170def test_tuple_expr(env):
171 for tmpl in TUPLETEMPLATES:
172 assert env.from_string(tmpl)
173
174
175def test_trailing_comma(env):
176 tmpl = env.from_string(TRAILINGCOMMA)
Armin Ronacher1dcdac52007-12-09 22:53:46 +0100177 assert tmpl.render().lower() == '(1, 2)|[1, 2]|{1: 2}|set([1, 2])'
Armin Ronacher1cc232c2007-09-07 17:52:41 +0200178
179
180def test_extends_position():
181 env = Environment(loader=DictLoader({
182 'empty': '[{% block empty %}{% endblock %}]'
183 }))
184 tests = [
185 ('{% extends "empty" %}', '[!]'),
186 (' {% extends "empty" %}', '[!]'),
187 (' !\n', ' !\n!'),
188 ('{# foo #} {% extends "empty" %}', '[!]'),
189 ('{% set foo = "blub" %}{% extends "empty" %}', None)
190 ]
191
192 for tmpl, expected_output in tests:
193 try:
194 tmpl = env.from_string(tmpl + '{% block empty %}!{% endblock %}')
195 except TemplateSyntaxError:
196 assert expected_output is None, 'got syntax error'
197 else:
198 assert expected_output == tmpl.render()