More Python 3 support.
[jinja2.git] / tests / test_filters.py
1 # -*- coding: utf-8 -*-
2 """
3     unit test for the filters
4     ~~~~~~~~~~~~~~~~~~~~~~~~~
5
6     :copyright: (c) 2009 by the Jinja Team.
7     :license: BSD, see LICENSE for more details.
8 """
9 from jinja2 import Markup, Environment
10
11 env = Environment()
12
13
14 CAPITALIZE = '''{{ "foo bar"|capitalize }}'''
15 CENTER = '''{{ "foo"|center(9) }}'''
16 DEFAULT = '''{{ missing|default("no") }}|{{ false|default('no') }}|\
17 {{ false|default('no', true) }}|{{ given|default("no") }}'''
18 DICTSORT = '''{{ foo|dictsort }}|\
19 {{ foo|dictsort(true) }}|\
20 {{ foo|dictsort(false, 'value') }}'''
21 BATCH = '''{{ foo|batch(3)|list }}|{{ foo|batch(3, 'X')|list }}'''
22 SLICE = '''{{ foo|slice(3)|list }}|{{ foo|slice(3, 'X')|list }}'''
23 ESCAPE = '''{{ '<">&'|escape }}'''
24 STRIPTAGS = '''{{ foo|striptags }}'''
25 FILESIZEFORMAT = '{{ 100|filesizeformat }}|\
26 {{ 1000|filesizeformat }}|\
27 {{ 1000000|filesizeformat }}|\
28 {{ 1000000000|filesizeformat }}|\
29 {{ 1000000000000|filesizeformat }}|\
30 {{ 100|filesizeformat(true) }}|\
31 {{ 1000|filesizeformat(true) }}|\
32 {{ 1000000|filesizeformat(true) }}|\
33 {{ 1000000000|filesizeformat(true) }}|\
34 {{ 1000000000000|filesizeformat(true) }}'
35 FIRST = '''{{ foo|first }}'''
36 FLOAT = '''{{ "42"|float }}|{{ "ajsghasjgd"|float }}|{{ "32.32"|float }}'''
37 FORMAT = '''{{ "%s|%s"|format("a", "b") }}'''
38 INDENT = '''{{ foo|indent(2) }}|{{ foo|indent(2, true) }}'''
39 INT = '''{{ "42"|int }}|{{ "ajsghasjgd"|int }}|{{ "32.32"|int }}'''
40 JOIN = '''{{ [1, 2, 3]|join("|") }}'''
41 LAST = '''{{ foo|last }}'''
42 LENGTH = '''{{ "hello world"|length }}'''
43 LOWER = '''{{ "FOO"|lower }}'''
44 PPRINT = '''{{ data|pprint }}'''
45 RANDOM = '''{{ seq|random }}'''
46 REVERSE = '''{{ "foobar"|reverse|join }}|{{ [1, 2, 3]|reverse|list }}'''
47 STRING = '''{{ range(10)|string }}'''
48 TITLE = '''{{ "foo bar"|title }}'''
49 TRIM = '''{{ "      foo       "|trim }}'''
50 TRUNCATE = '''{{ data|truncate(15, true, ">>>") }}|\
51 {{ data|truncate(15, false, ">>>") }}|\
52 {{ smalldata|truncate(15) }}'''
53 UPPER = '''{{ "foo"|upper }}'''
54 URLIZE = '''{{ "foo http://www.example.com/ bar"|urlize }}'''
55 WORDCOUNT = '''{{ "foo bar baz"|wordcount }}'''
56 BLOCK = '''{% filter lower|escape %}<HEHE>{% endfilter %}'''
57 CHAINING = '''{{ ['<foo>', '<bar>']|first|upper|escape }}'''
58 SUM = '''{{ [1, 2, 3, 4, 5, 6]|sum }}'''
59 ABS = '''{{ -1|abs }}|{{ 1|abs }}'''
60 ROUND = '''{{ 2.7|round }}|{{ 2.1|round }}|\
61 {{ 2.1234|round(2, 'floor') }}|{{ 2.1|round(0, 'ceil') }}'''
62 XMLATTR = '''{{ {'foo': 42, 'bar': 23, 'fish': none,
63 'spam': missing, 'blub:blub': '<?>'}|xmlattr }}'''
64 SORT1 = '''{{ [2, 3, 1]|sort }}|{{ [2, 3, 1]|sort(true) }}'''
65 GROUPBY = '''{% for grouper, list in [{'foo': 1, 'bar': 2},
66                  {'foo': 2, 'bar': 3},
67                  {'foo': 1, 'bar': 1},
68                  {'foo': 3, 'bar': 4}]|groupby('foo') -%}
69 {{ grouper }}: {{ list|join(', ') }}
70 {% endfor %}'''
71 FILTERTAG = '''{% filter upper|replace('FOO', 'foo') %}foobar{% endfilter %}'''
72 SORT2 = '''{{ ['foo', 'Bar', 'blah']|sort }}'''
73
74
75 def test_capitalize():
76     tmpl = env.from_string(CAPITALIZE)
77     assert tmpl.render() == 'Foo bar'
78
79
80 def test_center():
81     tmpl = env.from_string(CENTER)
82     assert tmpl.render() == '   foo   '
83
84
85 def test_default():
86     tmpl = env.from_string(DEFAULT)
87     assert tmpl.render(given='yes') == 'no|False|no|yes'
88
89
90 def test_dictsort():
91     tmpl = env.from_string(DICTSORT)
92     out = tmpl.render(foo={"a": 0, "b": 1, "c": 2, "A": 3})
93     assert out == ("[('a', 0), ('A', 3), ('b', 1), ('c', 2)]|"
94                    "[('A', 3), ('a', 0), ('b', 1), ('c', 2)]|"
95                    "[('a', 0), ('b', 1), ('c', 2), ('A', 3)]")
96
97
98 def test_batch():
99     tmpl = env.from_string(BATCH)
100     out = tmpl.render(foo=range(10))
101     assert out == ("[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]|"
102                    "[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 'X', 'X']]")
103
104
105 def test_slice():
106     tmpl = env.from_string(SLICE)
107     out = tmpl.render(foo=range(10))
108     assert out == ("[[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]]|"
109                    "[[0, 1, 2, 3], [4, 5, 6, 'X'], [7, 8, 9, 'X']]")
110
111
112 def test_escape():
113     tmpl = env.from_string(ESCAPE)
114     out = tmpl.render()
115     assert out == '&lt;&#34;&gt;&amp;'
116
117
118 def test_striptags():
119     tmpl = env.from_string(STRIPTAGS)
120     out = tmpl.render(foo='  <p>just a small   \n <a href="#">'
121                       'example</a> link</p>\n<p>to a webpage</p> '
122                       '<!-- <p>and some commented stuff</p> -->')
123     assert out == 'just a small example link to a webpage'
124
125
126 def test_filesizeformat():
127     tmpl = env.from_string(FILESIZEFORMAT)
128     out = tmpl.render()
129     assert out == (
130         '100 Bytes|1.0 KB|1.0 MB|1.0 GB|1000.0 GB|'
131         '100 Bytes|1000 Bytes|976.6 KiB|953.7 MiB|931.3 GiB'
132     )
133
134
135 def test_first():
136     tmpl = env.from_string(FIRST)
137     out = tmpl.render(foo=range(10))
138     assert out == '0'
139
140
141 def test_float():
142     tmpl = env.from_string(FLOAT)
143     out = tmpl.render()
144     assert out == '42.0|0.0|32.32'
145
146
147 def test_format():
148     tmpl = env.from_string(FORMAT)
149     out = tmpl.render()
150     assert out == 'a|b'
151
152
153 def test_indent():
154     tmpl = env.from_string(INDENT)
155     text = '\n'.join([' '.join(['foo', 'bar'] * 2)] * 2)
156     out = tmpl.render(foo=text)
157     assert out == ('foo bar foo bar\n  foo bar foo bar|  '
158                    'foo bar foo bar\n  foo bar foo bar')
159
160
161 def test_int():
162     tmpl = env.from_string(INT)
163     out = tmpl.render()
164     assert out == '42|0|32'
165
166
167 def test_join():
168     tmpl = env.from_string(JOIN)
169     out = tmpl.render()
170     assert out == '1|2|3'
171
172     env2 = Environment(autoescape=True)
173     tmpl = env2.from_string('{{ ["<foo>", "<span>foo</span>"|safe]|join }}')
174     assert tmpl.render() == '&lt;foo&gt;<span>foo</span>'
175
176
177 def test_last():
178     tmpl = env.from_string(LAST)
179     out = tmpl.render(foo=range(10))
180     assert out == '9'
181
182
183 def test_length():
184     tmpl = env.from_string(LENGTH)
185     out = tmpl.render()
186     assert out == '11'
187
188
189 def test_lower():
190     tmpl = env.from_string(LOWER)
191     out = tmpl.render()
192     assert out == 'foo'
193
194
195 def test_pprint():
196     from pprint import pformat
197     tmpl = env.from_string(PPRINT)
198     data = range(1000)
199     assert tmpl.render(data=data) == pformat(data)
200
201
202 def test_random():
203     tmpl = env.from_string(RANDOM)
204     seq = range(100)
205     for _ in range(10):
206         assert int(tmpl.render(seq=seq)) in seq
207
208
209 def test_reverse():
210     tmpl = env.from_string(REVERSE)
211     assert tmpl.render() == 'raboof|[3, 2, 1]'
212
213
214 def test_string():
215     tmpl = env.from_string(STRING)
216     assert tmpl.render(foo=range(10)) == unicode(xrange(10))
217
218
219 def test_title():
220     tmpl = env.from_string(TITLE)
221     assert tmpl.render() == "Foo Bar"
222
223
224 def test_truncate():
225     tmpl = env.from_string(TRUNCATE)
226     out = tmpl.render(data='foobar baz bar' * 1000,
227                       smalldata='foobar baz bar')
228     assert out == 'foobar baz barf>>>|foobar baz >>>|foobar baz bar'
229
230
231 def test_upper():
232     tmpl = env.from_string(UPPER)
233     assert tmpl.render() == 'FOO'
234
235
236 def test_urlize():
237     tmpl = env.from_string(URLIZE)
238     assert tmpl.render() == 'foo <a href="http://www.example.com/">'\
239                             'http://www.example.com/</a> bar'
240
241
242 def test_wordcount():
243     tmpl = env.from_string(WORDCOUNT)
244     assert tmpl.render() == '3'
245
246
247 def test_block():
248     tmpl = env.from_string(BLOCK)
249     assert tmpl.render() == '&lt;hehe&gt;'
250
251
252 def test_chaining():
253     tmpl = env.from_string(CHAINING)
254     assert tmpl.render() == '&lt;FOO&gt;'
255
256
257 def test_sum():
258     tmpl = env.from_string(SUM)
259     assert tmpl.render() == '21'
260
261
262 def test_abs():
263     tmpl = env.from_string(ABS)
264     return tmpl.render() == '1|1'
265
266
267 def test_round():
268     tmpl = env.from_string(ROUND)
269     return tmpl.render() == '3.0|2.0|2.1|3.0'
270
271
272 def test_xmlattr():
273     tmpl = env.from_string(XMLATTR)
274     out = tmpl.render().split()
275     assert len(out) == 3
276     assert 'foo="42"' in out
277     assert 'bar="23"' in out
278     assert 'blub:blub="&lt;?&gt;"' in out
279
280
281 def test_sort1():
282     tmpl = env.from_string(SORT1)
283     assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]'
284
285
286 def test_groupby():
287     tmpl = env.from_string(GROUPBY)
288     assert tmpl.render().splitlines() == [
289         "1: {'foo': 1, 'bar': 2}, {'foo': 1, 'bar': 1}",
290         "2: {'foo': 2, 'bar': 3}",
291         "3: {'foo': 3, 'bar': 4}"
292     ]
293
294
295 def test_filtertag():
296     tmpl = env.from_string(FILTERTAG)
297     assert tmpl.render() == 'fooBAR'
298
299
300 def test_replace():
301     env = Environment()
302     tmpl = env.from_string('{{ string|replace("o", 42) }}')
303     assert tmpl.render(string='<foo>') == '<f4242>'
304
305     env = Environment(autoescape=True)
306     tmpl = env.from_string('{{ string|replace("o", 42) }}')
307     assert tmpl.render(string='<foo>') == '&lt;f4242&gt;'
308     tmpl = env.from_string('{{ string|replace("<", 42) }}')
309     assert tmpl.render(string='<foo>') == '42foo&gt;'
310     tmpl = env.from_string('{{ string|replace("o", ">x<") }}')
311     assert tmpl.render(string=Markup('foo')) == 'f&gt;x&lt;&gt;x&lt;'
312
313
314 def test_forceescape():
315     tmpl = env.from_string('{{ x|forceescape }}')
316     assert tmpl.render(x=Markup('<div />')) == u'&lt;div /&gt;'
317
318
319 def test_safe():
320     env = Environment(autoescape=True)
321     tmpl = env.from_string('{{ "<div>foo</div>"|safe }}')
322     assert tmpl.render() == '<div>foo</div>'
323     tmpl = env.from_string('{{ "<div>foo</div>" }}')
324     assert tmpl.render() == '&lt;div&gt;foo&lt;/div&gt;'
325
326
327 def test_sort2():
328     assert env.from_string(SORT2).render() == "['Bar', 'blah', 'foo']"