1 # -*- coding: utf-8 -*-
3 jinja2.testsuite.core_tags
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~
6 Test the core tags like for and if.
8 :copyright: (c) 2010 by the Jinja Team.
9 :license: BSD, see LICENSE for more details.
13 from jinja2
.testsuite
import JinjaTestCase
15 from jinja2
import Environment
, TemplateSyntaxError
, UndefinedError
, \
21 class ForLoopTestCase(JinjaTestCase
):
23 def test_simple(self
):
24 tmpl
= env
.from_string('{% for item in seq %}{{ item }}{% endfor %}')
25 assert tmpl
.render(seq
=range(10)) == '0123456789'
28 tmpl
= env
.from_string('{% for item in seq %}XXX{% else %}...{% endfor %}')
29 assert tmpl
.render() == '...'
31 def test_empty_blocks(self
):
32 tmpl
= env
.from_string('<{% for item in seq %}{% else %}{% endfor %}>')
33 assert tmpl
.render() == '<>'
35 def test_context_vars(self
):
36 tmpl
= env
.from_string('''{% for item in seq -%}
37 {{ loop.index }}|{{ loop.index0 }}|{{ loop.revindex }}|{{
38 loop.revindex0 }}|{{ loop.first }}|{{ loop.last }}|{{
39 loop.length }}###{% endfor %}''')
40 one
, two
, _
= tmpl
.render(seq
=[0, 1]).split('###')
41 (one_index
, one_index0
, one_revindex
, one_revindex0
, one_first
,
42 one_last
, one_length
) = one
.split('|')
43 (two_index
, two_index0
, two_revindex
, two_revindex0
, two_first
,
44 two_last
, two_length
) = two
.split('|')
46 assert int(one_index
) == 1 and int(two_index
) == 2
47 assert int(one_index0
) == 0 and int(two_index0
) == 1
48 assert int(one_revindex
) == 2 and int(two_revindex
) == 1
49 assert int(one_revindex0
) == 1 and int(two_revindex0
) == 0
50 assert one_first
== 'True' and two_first
== 'False'
51 assert one_last
== 'False' and two_last
== 'True'
52 assert one_length
== two_length
== '2'
54 def test_cycling(self
):
55 tmpl
= env
.from_string('''{% for item in seq %}{{
56 loop.cycle('<1>', '<2>') }}{% endfor %}{%
57 for item in seq %}{{ loop.cycle(*through) }}{% endfor %}''')
58 output
= tmpl
.render(seq
=range(4), through
=('<1>', '<2>'))
59 assert output
== '<1><2>' * 4
62 tmpl
= env
.from_string('{% for item in seq %}{% endfor %}{{ item }}')
63 output
= tmpl
.render(seq
=range(10))
66 def test_varlen(self
):
70 tmpl
= env
.from_string('{% for item in iter %}{{ item }}{% endfor %}')
71 output
= tmpl
.render(iter=inner())
72 assert output
== '01234'
74 def test_noniter(self
):
75 tmpl
= env
.from_string('{% for item in none %}...{% endfor %}')
76 self
.assert_raises(TypeError, tmpl
.render
)
78 def test_recursive(self
):
79 tmpl
= env
.from_string('''{% for item in seq recursive -%}
80 [{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
82 assert tmpl
.render(seq
=[
83 dict(a
=1, b
=[dict(a
=1), dict(a
=2)]),
84 dict(a
=2, b
=[dict(a
=1), dict(a
=2)]),
85 dict(a
=3, b
=[dict(a
='a')])
86 ]) == '[1<[1][2]>][2<[1][2]>][3<[a]>]'
88 def test_looploop(self
):
89 tmpl
= env
.from_string('''{% for row in table %}
90 {%- set rowloop = loop -%}
91 {% for cell in row -%}
92 [{{ rowloop.index }}|{{ loop.index }}]
95 assert tmpl
.render(table
=['ab', 'cd']) == '[1|1][1|2][2|1][2|2]'
97 def test_reversed_bug(self
):
98 tmpl
= env
.from_string('{% for i in items %}{{ i }}'
99 '{% if not loop.last %}'
100 ',{% endif %}{% endfor %}')
101 assert tmpl
.render(items
=reversed([3, 2, 1])) == '1,2,3'
103 def test_loop_errors(self
):
104 tmpl
= env
.from_string('''{% for item in [1] if loop.index
105 == 0 %}...{% endfor %}''')
106 self
.assert_raises(UndefinedError
, tmpl
.render
)
107 tmpl
= env
.from_string('''{% for item in [] %}...{% else
108 %}{{ loop }}{% endfor %}''')
109 assert tmpl
.render() == ''
111 def test_loop_filter(self
):
112 tmpl
= env
.from_string('{% for item in range(10) if item '
113 'is even %}[{{ item }}]{% endfor %}')
114 assert tmpl
.render() == '[0][2][4][6][8]'
115 tmpl
= env
.from_string('''
116 {%- for item in range(10) if item is even %}[{{
117 loop.index }}:{{ item }}]{% endfor %}''')
118 assert tmpl
.render() == '[1:0][2:2][3:4][4:6][5:8]'
120 def test_loop_unassignable(self
):
121 self
.assert_raises(TemplateSyntaxError
, env
.from_string
,
122 '{% for loop in seq %}...{% endfor %}')
124 def test_scoped_special_var(self
):
125 t
= env
.from_string('{% for s in seq %}[{{ loop.first }}{% for c in s %}'
126 '|{{ loop.first }}{% endfor %}]{% endfor %}')
127 assert t
.render(seq
=('ab', 'cd')) == '[True|True|False][False|True|False]'
129 def test_scoped_loop_var(self
):
130 t
= env
.from_string('{% for x in seq %}{{ loop.first }}'
131 '{% for y in seq %}{% endfor %}{% endfor %}')
132 assert t
.render(seq
='ab') == 'TrueFalse'
133 t
= env
.from_string('{% for x in seq %}{% for y in seq %}'
134 '{{ loop.first }}{% endfor %}{% endfor %}')
135 assert t
.render(seq
='ab') == 'TrueFalseTrueFalse'
137 def test_recursive_empty_loop_iter(self
):
138 t
= env
.from_string('''
139 {%- for item in foo recursive -%}{%- endfor -%}
141 assert t
.render(dict(foo
=[])) == ''
143 def test_call_in_loop(self
):
144 t
= env
.from_string('''
145 {%- macro do_something() -%}
149 {%- for i in [1, 2, 3] %}
150 {%- call do_something() -%}
155 assert t
.render() == '[1][2][3]'
157 def test_scoping_bug(self
):
158 t
= env
.from_string('''
159 {%- for item in foo %}...{{ item }}...{% endfor %}
160 {%- macro item(a) %}...{{ a }}...{% endmacro %}
163 assert t
.render(foo
=(1,)) == '...1......2...'
165 def test_unpacking(self
):
166 tmpl
= env
.from_string('{% for a, b, c in [[1, 2, 3]] %}'
167 '{{ a }}|{{ b }}|{{ c }}{% endfor %}')
168 assert tmpl
.render() == '1|2|3'
171 class IfConditionTestCase(JinjaTestCase
):
173 def test_simple(self
):
174 tmpl
= env
.from_string('''{% if true %}...{% endif %}''')
175 assert tmpl
.render() == '...'
178 tmpl
= env
.from_string('''{% if false %}XXX{% elif true
179 %}...{% else %}XXX{% endif %}''')
180 assert tmpl
.render() == '...'
183 tmpl
= env
.from_string('{% if false %}XXX{% else %}...{% endif %}')
184 assert tmpl
.render() == '...'
186 def test_empty(self
):
187 tmpl
= env
.from_string('[{% if true %}{% else %}{% endif %}]')
188 assert tmpl
.render() == '[]'
190 def test_complete(self
):
191 tmpl
= env
.from_string('{% if a %}A{% elif b %}B{% elif c == d %}'
192 'C{% else %}D{% endif %}')
193 assert tmpl
.render(a
=0, b
=False, c
=42, d
=42.0) == 'C'
195 def test_no_scope(self
):
196 tmpl
= env
.from_string('{% if a %}{% set foo = 1 %}{% endif %}{{ foo }}')
197 assert tmpl
.render(a
=True) == '1'
198 tmpl
= env
.from_string('{% if true %}{% set foo = 1 %}{% endif %}{{ foo }}')
199 assert tmpl
.render() == '1'
202 class MacrosTestCase(JinjaTestCase
):
203 env
= Environment(trim_blocks
=True)
205 def test_simple(self
):
206 tmpl
= self
.env
.from_string('''\
207 {% macro say_hello(name) %}Hello {{ name }}!{% endmacro %}
208 {{ say_hello('Peter') }}''')
209 assert tmpl
.render() == 'Hello Peter!'
211 def test_scoping(self
):
212 tmpl
= self
.env
.from_string('''\
213 {% macro level1(data1) %}
214 {% macro level2(data2) %}{{ data1 }}|{{ data2 }}{% endmacro %}
215 {{ level2('bar') }}{% endmacro %}
216 {{ level1('foo') }}''')
217 assert tmpl
.render() == 'foo|bar'
219 def test_arguments(self
):
220 tmpl
= self
.env
.from_string('''\
221 {% macro m(a, b, c='c', d='d') %}{{ a }}|{{ b }}|{{ c }}|{{ d }}{% endmacro %}
222 {{ m() }}|{{ m('a') }}|{{ m('a', 'b') }}|{{ m(1, 2, 3) }}''')
223 assert tmpl
.render() == '||c|d|a||c|d|a|b|c|d|1|2|3|d'
225 def test_varargs(self
):
226 tmpl
= self
.env
.from_string('''\
227 {% macro test() %}{{ varargs|join('|') }}{% endmacro %}\
228 {{ test(1, 2, 3) }}''')
229 assert tmpl
.render() == '1|2|3'
231 def test_simple_call(self
):
232 tmpl
= self
.env
.from_string('''\
233 {% macro test() %}[[{{ caller() }}]]{% endmacro %}\
234 {% call test() %}data{% endcall %}''')
235 assert tmpl
.render() == '[[data]]'
237 def test_complex_call(self
):
238 tmpl
= self
.env
.from_string('''\
239 {% macro test() %}[[{{ caller('data') }}]]{% endmacro %}\
240 {% call(data) test() %}{{ data }}{% endcall %}''')
241 assert tmpl
.render() == '[[data]]'
243 def test_caller_undefined(self
):
244 tmpl
= self
.env
.from_string('''\
245 {% set caller = 42 %}\
246 {% macro test() %}{{ caller is not defined }}{% endmacro %}\
248 assert tmpl
.render() == 'True'
250 def test_include(self
):
251 self
.env
= Environment(loader
=DictLoader({'include':
252 '{% macro test(foo) %}[{{ foo }}]{% endmacro %}'}))
253 tmpl
= self
.env
.from_string('{% from "include" import test %}{{ test("foo") }}')
254 assert tmpl
.render() == '[foo]'
256 def test_macro_api(self
):
257 tmpl
= self
.env
.from_string('{% macro foo(a, b) %}{% endmacro %}'
258 '{% macro bar() %}{{ varargs }}{{ kwargs }}{% endmacro %}'
259 '{% macro baz() %}{{ caller() }}{% endmacro %}')
260 assert tmpl
.module
.foo
.arguments
== ('a', 'b')
261 assert tmpl
.module
.foo
.defaults
== ()
262 assert tmpl
.module
.foo
.name
== 'foo'
263 assert not tmpl
.module
.foo
.caller
264 assert not tmpl
.module
.foo
.catch_kwargs
265 assert not tmpl
.module
.foo
.catch_varargs
266 assert tmpl
.module
.bar
.arguments
== ()
267 assert tmpl
.module
.bar
.defaults
== ()
268 assert not tmpl
.module
.bar
.caller
269 assert tmpl
.module
.bar
.catch_kwargs
270 assert tmpl
.module
.bar
.catch_varargs
271 assert tmpl
.module
.baz
.caller
273 def test_callself(self
):
274 tmpl
= self
.env
.from_string('{% macro foo(x) %}{{ x }}{% if x > 1 %}|'
275 '{{ foo(x - 1) }}{% endif %}{% endmacro %}'
277 assert tmpl
.render() == '5|4|3|2|1'
281 suite
= unittest
.TestSuite()
282 suite
.addTest(unittest
.makeSuite(ForLoopTestCase
))
283 suite
.addTest(unittest
.makeSuite(IfConditionTestCase
))
284 suite
.addTest(unittest
.makeSuite(MacrosTestCase
))