1 # -*- coding: utf-8 -*-
6 Tests the public API and related stuff.
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
, Undefined
, DebugUndefined
, \
16 StrictUndefined
, UndefinedError
, meta
, \
17 is_undefined
, Template
, DictLoader
18 from jinja2
.utils
import Cycler
23 class ExtendedAPITestCase(JinjaTestCase
):
25 def test_item_and_attribute(self
):
26 from jinja2
.sandbox
import SandboxedEnvironment
28 for env
in Environment(), SandboxedEnvironment():
29 # the |list is necessary for python3
30 tmpl
= env
.from_string('{{ foo.items()|list }}')
31 assert tmpl
.render(foo
={'items': 42}) == "[('items', 42)]"
32 tmpl
= env
.from_string('{{ foo|attr("items")()|list }}')
33 assert tmpl
.render(foo
={'items': 42}) == "[('items', 42)]"
34 tmpl
= env
.from_string('{{ foo["items"] }}')
35 assert tmpl
.render(foo
={'items': 42}) == '42'
37 def test_finalizer(self
):
38 def finalize_none_empty(value
):
42 env
= Environment(finalize
=finalize_none_empty
)
43 tmpl
= env
.from_string('{% for item in seq %}|{{ item }}{% endfor %}')
44 assert tmpl
.render(seq
=(None, 1, "foo")) == '||1|foo'
45 tmpl
= env
.from_string('<{{ none }}>')
46 assert tmpl
.render() == '<>'
48 def test_cycler(self
):
51 for item
in items
+ items
:
52 assert c
.current
== item
53 assert c
.next() == item
59 def test_expressions(self
):
60 expr
= env
.compile_expression("foo")
62 assert expr(foo
=42) == 42
63 expr2
= env
.compile_expression("foo", undefined_to_none
=False)
64 assert is_undefined(expr2())
66 expr
= env
.compile_expression("42 + foo")
67 assert expr(foo
=42) == 84
69 def test_template_passthrough(self
):
70 t
= Template('Content')
71 assert env
.get_template(t
) is t
72 assert env
.select_template([t
]) is t
73 assert env
.get_or_select_template([t
]) is t
74 assert env
.get_or_select_template(t
) is t
76 def test_autoescape_autoselect(self
):
77 def select_autoescape(name
):
78 if name
is None or '.' not in name
:
80 return name
.endswith('.html')
81 env
= Environment(autoescape
=select_autoescape
,
83 'test.txt': '{{ foo }}',
84 'test.html': '{{ foo }}'
86 t
= env
.get_template('test.txt')
87 assert t
.render(foo
='<foo>') == '<foo>'
88 t
= env
.get_template('test.html')
89 assert t
.render(foo
='<foo>') == '<foo>'
90 t
= env
.from_string('{{ foo }}')
91 assert t
.render(foo
='<foo>') == '<foo>'
94 class MetaTestCase(JinjaTestCase
):
96 def test_find_undeclared_variables(self
):
97 ast
= env
.parse('{% set foo = 42 %}{{ bar + foo }}')
98 x
= meta
.find_undeclared_variables(ast
)
99 assert x
== set(['bar'])
101 ast
= env
.parse('{% set foo = 42 %}{{ bar + foo }}'
102 '{% macro meh(x) %}{{ x }}{% endmacro %}'
103 '{% for item in seq %}{{ muh(item) + meh(seq) }}{% endfor %}')
104 x
= meta
.find_undeclared_variables(ast
)
105 assert x
== set(['bar', 'seq', 'muh'])
107 def test_find_refererenced_templates(self
):
108 ast
= env
.parse('{% extends "layout.html" %}{% include helper %}')
109 i
= meta
.find_referenced_templates(ast
)
110 assert i
.next() == 'layout.html'
111 assert i
.next() is None
114 ast
= env
.parse('{% extends "layout.html" %}'
115 '{% from "test.html" import a, b as c %}'
116 '{% import "meh.html" as meh %}'
117 '{% include "muh.html" %}')
118 i
= meta
.find_referenced_templates(ast
)
119 assert list(i
) == ['layout.html', 'test.html', 'meh.html', 'muh.html']
121 def test_find_included_templates(self
):
122 ast
= env
.parse('{% include ["foo.html", "bar.html"] %}')
123 i
= meta
.find_referenced_templates(ast
)
124 assert list(i
) == ['foo.html', 'bar.html']
126 ast
= env
.parse('{% include ("foo.html", "bar.html") %}')
127 i
= meta
.find_referenced_templates(ast
)
128 assert list(i
) == ['foo.html', 'bar.html']
130 ast
= env
.parse('{% include ["foo.html", "bar.html", foo] %}')
131 i
= meta
.find_referenced_templates(ast
)
132 assert list(i
) == ['foo.html', 'bar.html', None]
134 ast
= env
.parse('{% include ("foo.html", "bar.html", foo) %}')
135 i
= meta
.find_referenced_templates(ast
)
136 assert list(i
) == ['foo.html', 'bar.html', None]
139 class StreamingTestCase(JinjaTestCase
):
141 def test_basic_streaming(self
):
142 tmpl
= env
.from_string("<ul>{% for item in seq %}<li>{{ loop.index "
143 "}} - {{ item }}</li>{%- endfor %}</ul>")
144 stream
= tmpl
.stream(seq
=range(4))
145 self
.assert_equal(stream
.next(), '<ul>')
146 self
.assert_equal(stream
.next(), '<li>1 - 0</li>')
147 self
.assert_equal(stream
.next(), '<li>2 - 1</li>')
148 self
.assert_equal(stream
.next(), '<li>3 - 2</li>')
149 self
.assert_equal(stream
.next(), '<li>4 - 3</li>')
150 self
.assert_equal(stream
.next(), '</ul>')
152 def test_buffered_streaming(self
):
153 tmpl
= env
.from_string("<ul>{% for item in seq %}<li>{{ loop.index "
154 "}} - {{ item }}</li>{%- endfor %}</ul>")
155 stream
= tmpl
.stream(seq
=range(4))
156 stream
.enable_buffering(size
=3)
157 self
.assert_equal(stream
.next(), u
'<ul><li>1 - 0</li><li>2 - 1</li>')
158 self
.assert_equal(stream
.next(), u
'<li>3 - 2</li><li>4 - 3</li></ul>')
160 def test_streaming_behavior(self
):
161 tmpl
= env
.from_string("")
162 stream
= tmpl
.stream()
163 assert not stream
.buffered
164 stream
.enable_buffering(20)
165 assert stream
.buffered
166 stream
.disable_buffering()
167 assert not stream
.buffered
170 class UndefinedTestCase(JinjaTestCase
):
172 def test_stopiteration_is_undefined(self
):
174 raise StopIteration()
175 t
= Template('A{{ test() }}B')
176 assert t
.render(test
=test
) == 'AB'
177 t
= Template('A{{ test().missingattribute }}B')
178 self
.assert_raises(UndefinedError
, t
.render
, test
=test
)
180 def test_undefined_and_special_attributes(self
):
182 Undefined('Foo').__dict
__
183 except AttributeError:
186 assert False, "Expected actual attribute error"
188 def test_default_undefined(self
):
189 env
= Environment(undefined
=Undefined
)
190 self
.assert_equal(env
.from_string('{{ missing }}').render(), u
'')
191 self
.assert_raises(UndefinedError
,
192 env
.from_string('{{ missing.attribute }}').render
)
193 self
.assert_equal(env
.from_string('{{ missing|list }}').render(), '[]')
194 self
.assert_equal(env
.from_string('{{ missing is not defined }}').render(), 'True')
195 self
.assert_equal(env
.from_string('{{ foo.missing }}').render(foo
=42), '')
196 self
.assert_equal(env
.from_string('{{ not missing }}').render(), 'True')
198 def test_debug_undefined(self
):
199 env
= Environment(undefined
=DebugUndefined
)
200 self
.assert_equal(env
.from_string('{{ missing }}').render(), '{{ missing }}')
201 self
.assert_raises(UndefinedError
,
202 env
.from_string('{{ missing.attribute }}').render
)
203 self
.assert_equal(env
.from_string('{{ missing|list }}').render(), '[]')
204 self
.assert_equal(env
.from_string('{{ missing is not defined }}').render(), 'True')
205 self
.assert_equal(env
.from_string('{{ foo.missing }}').render(foo
=42),
206 u
"{{ no such element: int object['missing'] }}")
207 self
.assert_equal(env
.from_string('{{ not missing }}').render(), 'True')
209 def test_strict_undefined(self
):
210 env
= Environment(undefined
=StrictUndefined
)
211 self
.assert_raises(UndefinedError
, env
.from_string('{{ missing }}').render
)
212 self
.assert_raises(UndefinedError
, env
.from_string('{{ missing.attribute }}').render
)
213 self
.assert_raises(UndefinedError
, env
.from_string('{{ missing|list }}').render
)
214 self
.assert_equal(env
.from_string('{{ missing is not defined }}').render(), 'True')
215 self
.assert_raises(UndefinedError
, env
.from_string('{{ foo.missing }}').render
, foo
=42)
216 self
.assert_raises(UndefinedError
, env
.from_string('{{ not missing }}').render
)
218 def test_indexing_gives_undefined(self
):
219 t
= Template("{{ var[42].foo }}")
220 self
.assert_raises(UndefinedError
, t
.render
, var
=0)
222 def test_none_gives_proper_error(self
):
224 Environment().getattr(None, 'split')()
225 except UndefinedError
, e
:
226 assert e
.message
== "'None' has no attribute 'split'"
228 assert False, 'expected exception'
230 def test_object_repr(self
):
232 Undefined(obj
=42, name
='upper')()
233 except UndefinedError
, e
:
234 assert e
.message
== "'int object' has no attribute 'upper'"
236 assert False, 'expected exception'
240 suite
= unittest
.TestSuite()
241 suite
.addTest(unittest
.makeSuite(ExtendedAPITestCase
))
242 suite
.addTest(unittest
.makeSuite(MetaTestCase
))
243 suite
.addTest(unittest
.makeSuite(StreamingTestCase
))
244 suite
.addTest(unittest
.makeSuite(UndefinedTestCase
))