1 # -*- coding: utf-8 -*-
3 unit test for the filters
4 ~~~~~~~~~~~~~~~~~~~~~~~~~
6 :copyright: (c) 2009 by the Jinja Team.
7 :license: BSD, see LICENSE for more details.
9 from jinja2 import Markup, Environment
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},
68 {'foo': 3, 'bar': 4}]|groupby('foo') -%}
69 {{ grouper }}: {{ list|join(', ') }}
71 FILTERTAG = '''{% filter upper|replace('FOO', 'foo') %}foobar{% endfilter %}'''
72 SORT2 = '''{{ ['foo', 'Bar', 'blah']|sort }}'''
75 def test_capitalize():
76 tmpl = env.from_string(CAPITALIZE)
77 assert tmpl.render() == 'Foo bar'
81 tmpl = env.from_string(CENTER)
82 assert tmpl.render() == ' foo '
86 tmpl = env.from_string(DEFAULT)
87 assert tmpl.render(given='yes') == 'no|False|no|yes'
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)]")
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']]")
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']]")
113 tmpl = env.from_string(ESCAPE)
115 assert out == '<">&'
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'
126 def test_filesizeformat():
127 tmpl = env.from_string(FILESIZEFORMAT)
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'
136 tmpl = env.from_string(FIRST)
137 out = tmpl.render(foo=range(10))
142 tmpl = env.from_string(FLOAT)
144 assert out == '42.0|0.0|32.32'
148 tmpl = env.from_string(FORMAT)
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')
162 tmpl = env.from_string(INT)
164 assert out == '42|0|32'
168 tmpl = env.from_string(JOIN)
170 assert out == '1|2|3'
172 env2 = Environment(autoescape=True)
173 tmpl = env2.from_string('{{ ["<foo>", "<span>foo</span>"|safe]|join }}')
174 assert tmpl.render() == '<foo><span>foo</span>'
178 tmpl = env.from_string(LAST)
179 out = tmpl.render(foo=range(10))
184 tmpl = env.from_string(LENGTH)
190 tmpl = env.from_string(LOWER)
196 from pprint import pformat
197 tmpl = env.from_string(PPRINT)
199 assert tmpl.render(data=data) == pformat(data)
203 tmpl = env.from_string(RANDOM)
206 assert int(tmpl.render(seq=seq)) in seq
210 tmpl = env.from_string(REVERSE)
211 assert tmpl.render() == 'raboof|[3, 2, 1]'
215 tmpl = env.from_string(STRING)
216 assert tmpl.render(foo=range(10)) == unicode(xrange(10))
220 tmpl = env.from_string(TITLE)
221 assert tmpl.render() == "Foo Bar"
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'
232 tmpl = env.from_string(UPPER)
233 assert tmpl.render() == 'FOO'
237 tmpl = env.from_string(URLIZE)
238 assert tmpl.render() == 'foo <a href="http://www.example.com/">'\
239 'http://www.example.com/</a> bar'
242 def test_wordcount():
243 tmpl = env.from_string(WORDCOUNT)
244 assert tmpl.render() == '3'
248 tmpl = env.from_string(BLOCK)
249 assert tmpl.render() == '<hehe>'
253 tmpl = env.from_string(CHAINING)
254 assert tmpl.render() == '<FOO>'
258 tmpl = env.from_string(SUM)
259 assert tmpl.render() == '21'
263 tmpl = env.from_string(ABS)
264 return tmpl.render() == '1|1'
268 tmpl = env.from_string(ROUND)
269 return tmpl.render() == '3.0|2.0|2.1|3.0'
273 tmpl = env.from_string(XMLATTR)
274 out = tmpl.render().split()
276 assert 'foo="42"' in out
277 assert 'bar="23"' in out
278 assert 'blub:blub="<?>"' in out
282 tmpl = env.from_string(SORT1)
283 assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]'
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}"
295 def test_filtertag():
296 tmpl = env.from_string(FILTERTAG)
297 assert tmpl.render() == 'fooBAR'
302 tmpl = env.from_string('{{ string|replace("o", 42) }}')
303 assert tmpl.render(string='<foo>') == '<f4242>'
305 env = Environment(autoescape=True)
306 tmpl = env.from_string('{{ string|replace("o", 42) }}')
307 assert tmpl.render(string='<foo>') == '<f4242>'
308 tmpl = env.from_string('{{ string|replace("<", 42) }}')
309 assert tmpl.render(string='<foo>') == '42foo>'
310 tmpl = env.from_string('{{ string|replace("o", ">x<") }}')
311 assert tmpl.render(string=Markup('foo')) == 'f>x<>x<'
314 def test_forceescape():
315 tmpl = env.from_string('{{ x|forceescape }}')
316 assert tmpl.render(x=Markup('<div />')) == u'<div />'
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() == '<div>foo</div>'
328 assert env.from_string(SORT2).render() == "['Bar', 'blah', 'foo']"