blob: 2e8877a7f932b6f2feaf44d76eb4701edf70c162 [file] [log] [blame]
Armin Ronacherecc051b2007-06-01 18:25:28 +02001# -*- coding: utf-8 -*-
2"""
3 unit test for expression syntax
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
Armin Ronacher62ccd1b2009-01-04 14:26:19 +01006 :copyright: (c) 2009 by the Jinja Team.
Armin Ronacherecc051b2007-06-01 18:25:28 +02007 :license: BSD, see LICENSE for more details.
8"""
Christoph Hacke9e43bb2008-04-13 23:35:48 +02009from jinja2 import Environment, DictLoader
Armin Ronacher547d0b62008-07-04 16:35:10 +020010from jinja2.exceptions import TemplateSyntaxError, UndefinedError
Armin Ronacher1cc232c2007-09-07 17:52:41 +020011
Rene Leonhardtc7e6c6d2009-04-20 23:08:53 +020012import conftest
13if conftest.NOSE:
14 from nose.tools import assert_raises as raises
15else:
16 from py.test import raises
17
Armin Ronacherecc051b2007-06-01 18:25:28 +020018
19CALL = '''{{ foo('a', c='d', e='f', *['b'], **{'g': 'h'}) }}'''
20SLICING = '''{{ [1, 2, 3][:] }}|{{ [1, 2, 3][::-1] }}'''
21ATTR = '''{{ foo.bar }}|{{ foo['bar'] }}'''
22SUBSCRIPT = '''{{ foo[0] }}|{{ foo[-1] }}'''
Armin Ronacher1cc232c2007-09-07 17:52:41 +020023TUPLE = '''{{ () }}|{{ (1,) }}|{{ (1, 2) }}'''
Armin Ronacherecc051b2007-06-01 18:25:28 +020024MATH = '''{{ (1 + 1 * 2) - 3 / 2 }}|{{ 2**3 }}'''
25DIV = '''{{ 3 // 2 }}|{{ 3 / 2 }}|{{ 3 % 2 }}'''
26UNARY = '''{{ +3 }}|{{ -3 }}'''
Armin Ronacher1cc232c2007-09-07 17:52:41 +020027CONCAT = '''{{ [1, 2] ~ 'foo' }}'''
Armin Ronacherecc051b2007-06-01 18:25:28 +020028COMPARE = '''{{ 1 > 0 }}|{{ 1 >= 1 }}|{{ 2 < 3 }}|{{ 2 == 2 }}|{{ 1 <= 1 }}'''
Armin Ronacher1cc232c2007-09-07 17:52:41 +020029INOP = '''{{ 1 in [1, 2, 3] }}|{{ 1 not in [1, 2, 3] }}'''
Armin Ronacher203bfcb2008-04-24 21:54:44 +020030LITERALS = '''{{ [] }}|{{ {} }}|{{ () }}'''
Armin Ronacherecc051b2007-06-01 18:25:28 +020031BOOL = '''{{ true and false }}|{{ false or true }}|{{ not false }}'''
Armin Ronacherdb69d0a2007-06-02 01:35:53 +020032GROUPING = '''{{ (true and false) or (false and true) and not false }}'''
Armin Ronacher1cc232c2007-09-07 17:52:41 +020033CONDEXPR = '''{{ 0 if true else 1 }}'''
Armin Ronachercb1b97f2008-09-10 14:03:53 +020034DJANGOATTR = '''{{ [1, 2, 3].0 }}|{{ [[1]].0.0 }}'''
Armin Ronacher1cc232c2007-09-07 17:52:41 +020035FILTERPRIORITY = '''{{ "foo"|upper + "bar"|upper }}'''
Armin Ronacher1cc232c2007-09-07 17:52:41 +020036TUPLETEMPLATES = [
37 '{{ () }}',
38 '{{ (1, 2) }}',
39 '{{ (1, 2,) }}',
40 '{{ 1, }}',
41 '{{ 1, 2 }}',
42 '{% for foo, bar in seq %}...{% endfor %}',
43 '{% for x in foo, bar %}...{% endfor %}',
Armin Ronacherb5124e62008-04-25 00:36:14 +020044 '{% for x in foo, %}...{% endfor %}'
Armin Ronacher1cc232c2007-09-07 17:52:41 +020045]
Armin Ronacher203bfcb2008-04-24 21:54:44 +020046TRAILINGCOMMA = '''{{ (1, 2,) }}|{{ [1, 2,] }}|{{ {1: 2,} }}'''
Armin Ronacherecc051b2007-06-01 18:25:28 +020047
48
49def test_call():
Christoph Hacke9e43bb2008-04-13 23:35:48 +020050 from jinja2 import Environment
Armin Ronacherecc051b2007-06-01 18:25:28 +020051 env = Environment()
52 env.globals['foo'] = lambda a, b, c, e, g: a + b + c + e + g
53 tmpl = env.from_string(CALL)
54 assert tmpl.render() == 'abdfh'
55
56
57def test_slicing(env):
58 tmpl = env.from_string(SLICING)
59 assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]'
60
61
62def test_attr(env):
63 tmpl = env.from_string(ATTR)
64 assert tmpl.render(foo={'bar': 42}) == '42|42'
65
66
67def test_subscript(env):
68 tmpl = env.from_string(SUBSCRIPT)
69 assert tmpl.render(foo=[0, 1, 2]) == '0|2'
70
71
Armin Ronacherecc051b2007-06-01 18:25:28 +020072def test_tuple(env):
73 tmpl = env.from_string(TUPLE)
Armin Ronacher1cc232c2007-09-07 17:52:41 +020074 assert tmpl.render() == '()|(1,)|(1, 2)'
Armin Ronacherecc051b2007-06-01 18:25:28 +020075
76
77def test_math(env):
78 tmpl = env.from_string(MATH)
79 assert tmpl.render() == '1.5|8'
80
81
82def test_div(env):
83 tmpl = env.from_string(DIV)
84 assert tmpl.render() == '1|1.5|1'
85
86
87def test_unary(env):
88 tmpl = env.from_string(UNARY)
89 assert tmpl.render() == '3|-3'
90
91
Armin Ronacher1cc232c2007-09-07 17:52:41 +020092def test_concat(env):
93 tmpl = env.from_string(CONCAT)
94 assert tmpl.render() == '[1, 2]foo'
95
96
Armin Ronacherecc051b2007-06-01 18:25:28 +020097def test_compare(env):
98 tmpl = env.from_string(COMPARE)
99 assert tmpl.render() == 'True|True|True|True|True'
100
101
Armin Ronacher1cc232c2007-09-07 17:52:41 +0200102def test_inop(env):
103 tmpl = env.from_string(INOP)
104 assert tmpl.render() == 'True|False'
105
106
Armin Ronacherecc051b2007-06-01 18:25:28 +0200107def test_literals(env):
108 tmpl = env.from_string(LITERALS)
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200109 assert tmpl.render().lower() == '[]|{}|()'
Armin Ronacherecc051b2007-06-01 18:25:28 +0200110
111
112def test_bool(env):
113 tmpl = env.from_string(BOOL)
114 assert tmpl.render() == 'False|True|True'
Armin Ronacherdb69d0a2007-06-02 01:35:53 +0200115
116
117def test_grouping(env):
118 tmpl = env.from_string(GROUPING)
119 assert tmpl.render() == 'False'
Armin Ronacher1cc232c2007-09-07 17:52:41 +0200120
121
122def test_django_attr(env):
123 tmpl = env.from_string(DJANGOATTR)
Armin Ronachercb1b97f2008-09-10 14:03:53 +0200124 assert tmpl.render() == '1|1'
Armin Ronacher1cc232c2007-09-07 17:52:41 +0200125
126
127def test_conditional_expression(env):
128 tmpl = env.from_string(CONDEXPR)
129 assert tmpl.render() == '0'
130
131
Armin Ronacher547d0b62008-07-04 16:35:10 +0200132def test_short_conditional_expression(env):
133 tmpl = env.from_string('<{{ 1 if false }}>')
134 assert tmpl.render() == '<>'
135
136 tmpl = env.from_string('<{{ (1 if false).bar }}>')
137 raises(UndefinedError, tmpl.render)
138
139
Armin Ronacher1cc232c2007-09-07 17:52:41 +0200140def test_filter_priority(env):
141 tmpl = env.from_string(FILTERPRIORITY)
142 assert tmpl.render() == 'FOOBAR'
143
144
145def test_function_calls(env):
146 tests = [
147 (True, '*foo, bar'),
148 (True, '*foo, *bar'),
149 (True, '*foo, bar=42'),
150 (True, '**foo, *bar'),
151 (True, '**foo, bar'),
152 (False, 'foo, bar'),
153 (False, 'foo, bar=42'),
154 (False, 'foo, bar=23, *args'),
155 (False, 'a, b=c, *d, **e'),
156 (False, '*foo, **bar')
157 ]
158 for should_fail, sig in tests:
159 if should_fail:
Armin Ronacherfd310492008-05-25 00:16:51 +0200160 raises(TemplateSyntaxError, env.from_string, '{{ foo(%s) }}' % sig)
Armin Ronacher1cc232c2007-09-07 17:52:41 +0200161 else:
162 env.from_string('foo(%s)' % sig)
163
164
Armin Ronacher1cc232c2007-09-07 17:52:41 +0200165def test_tuple_expr(env):
166 for tmpl in TUPLETEMPLATES:
Armin Ronacher115de2e2008-05-01 22:20:05 +0200167 print tmpl
Armin Ronacher1cc232c2007-09-07 17:52:41 +0200168 assert env.from_string(tmpl)
169
170
171def test_trailing_comma(env):
172 tmpl = env.from_string(TRAILINGCOMMA)
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200173 assert tmpl.render().lower() == '(1, 2)|[1, 2]|{1: 2}'
Armin Ronacherfd310492008-05-25 00:16:51 +0200174
175
176def test_block_end_name(env):
177 env.from_string('{% block foo %}...{% endblock foo %}')
178 raises(TemplateSyntaxError, env.from_string, '{% block x %}{% endblock y %}')
Armin Ronacher9bb7e472008-05-28 11:26:59 +0200179
180
181def test_contant_casing(env):
182 for const in True, False, None:
183 tmpl = env.from_string('{{ %s }}|{{ %s }}|{{ %s }}' % (
184 str(const), str(const).lower(), str(const).upper()
185 ))
186 assert tmpl.render() == '%s|%s|' % (const, const)
Armin Ronachere3290ea2008-06-12 10:30:01 +0200187
188
189def test_test_chaining(env):
190 raises(TemplateSyntaxError, env.from_string, '{{ foo is string is sequence }}')
191 env.from_string('{{ 42 is string or 42 is number }}').render() == 'True'
Armin Ronacher4778bda2008-06-22 12:48:37 +0200192
193
194def test_string_concatenation(env):
195 tmpl = env.from_string('{{ "foo" "bar" "baz" }}')
196 assert tmpl.render() == 'foobarbaz'
Armin Ronacherd89f0f32009-02-04 18:57:27 +0100197
198
199def test_notin(env):
200 bar = xrange(100)
201 tmpl = env.from_string('''{{ not 42 in bar }}''')
202 assert tmpl.render(bar=bar) == unicode(not 42 in bar)
Armin Ronacheree2d3c42009-02-05 23:13:15 +0100203
204
205def test_implicit_subscribed_tuple(env):
206 class Foo(object):
207 def __getitem__(self, x):
208 return x
209 t = env.from_string('{{ foo[1, 2] }}')
210 assert t.render(foo=Foo()) == u'(1, 2)'