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