Started working on unittest powered testsuite.
[jinja2.git] / jinja2 / testsuite / ext.py
1 # -*- coding: utf-8 -*-
2 """
3     jinja2.testsuite.ext
4     ~~~~~~~~~~~~~~~~~~~~
5
6     Tests for the extensions.
7
8     :copyright: (c) 2010 by the Jinja Team.
9     :license: BSD, see LICENSE for more details.
10 """
11 import re
12 import unittest
13
14 from jinja2.testsuite import JinjaTestCase, filesystem_loader
15
16 from jinja2 import Environment, nodes
17 from jinja2.ext import Extension
18 from jinja2.lexer import Token, count_newlines
19
20
21 importable_object = 23
22
23 _gettext_re = re.compile(r'_\((.*?)\)(?s)')
24
25
26 class TestExtension(Extension):
27     tags = set(['test'])
28     ext_attr = 42
29
30     def parse(self, parser):
31         return nodes.Output([self.call_method('_dump', [
32             nodes.EnvironmentAttribute('sandboxed'),
33             self.attr('ext_attr'),
34             nodes.ImportedName(__name__ + '.importable_object'),
35             nodes.ContextReference()
36         ])]).set_lineno(parser.stream.next().lineno)
37
38     def _dump(self, sandboxed, ext_attr, imported_object, context):
39         return '%s|%s|%s|%s' % (
40             sandboxed,
41             ext_attr,
42             imported_object,
43             context.blocks
44         )
45
46
47 class PreprocessorExtension(Extension):
48
49     def preprocess(self, source, name, filename=None):
50         return source.replace('[[TEST]]', '({{ foo }})')
51
52
53 class StreamFilterExtension(Extension):
54
55     def filter_stream(self, stream):
56         for token in stream:
57             if token.type == 'data':
58                 for t in self.interpolate(token):
59                     yield t
60             else:
61                 yield token
62
63     def interpolate(self, token):
64         pos = 0
65         end = len(token.value)
66         lineno = token.lineno
67         while 1:
68             match = _gettext_re.search(token.value, pos)
69             if match is None:
70                 break
71             value = token.value[pos:match.start()]
72             if value:
73                 yield Token(lineno, 'data', value)
74             lineno += count_newlines(token.value)
75             yield Token(lineno, 'variable_begin', None)
76             yield Token(lineno, 'name', 'gettext')
77             yield Token(lineno, 'lparen', None)
78             yield Token(lineno, 'string', match.group(1))
79             yield Token(lineno, 'rparen', None)
80             yield Token(lineno, 'variable_end', None)
81             pos = match.end()
82         if pos < end:
83             yield Token(lineno, 'data', token.value[pos:])
84
85
86 class ExtensionsTestCase(JinjaTestCase):
87
88     def test_loop_controls(self):
89         env = Environment(extensions=['jinja2.ext.loopcontrols'])
90
91         tmpl = env.from_string('''
92             {%- for item in [1, 2, 3, 4] %}
93                 {%- if item % 2 == 0 %}{% continue %}{% endif -%}
94                 {{ item }}
95             {%- endfor %}''')
96         assert tmpl.render() == '13'
97
98         tmpl = env.from_string('''
99             {%- for item in [1, 2, 3, 4] %}
100                 {%- if item > 2 %}{% break %}{% endif -%}
101                 {{ item }}
102             {%- endfor %}''')
103         assert tmpl.render() == '12'
104
105     def test_do(self):
106         env = Environment(extensions=['jinja2.ext.do'])
107         tmpl = env.from_string('''
108             {%- set items = [] %}
109             {%- for char in "foo" %}
110                 {%- do items.append(loop.index0 ~ char) %}
111             {%- endfor %}{{ items|join(', ') }}''')
112         assert tmpl.render() == '0f, 1o, 2o'
113
114     def test_with(self):
115         env = Environment(extensions=['jinja2.ext.with_'])
116         tmpl = env.from_string('''\
117         {% with a=42, b=23 -%}
118             {{ a }} = {{ b }}
119         {% endwith -%}
120             {{ a }} = {{ b }}\
121         ''')
122         assert [x.strip() for x in tmpl.render(a=1, b=2).splitlines()] \
123             == ['42 = 23', '1 = 2']
124
125     def test_extension_nodes(self):
126         env = Environment(extensions=[TestExtension])
127         tmpl = env.from_string('{% test %}')
128         assert tmpl.render() == 'False|42|23|{}'
129
130     def test_identifier(self):
131         assert TestExtension.identifier == __name__ + '.TestExtension'
132
133     def test_rebinding(self):
134         original = Environment(extensions=[TestExtension])
135         overlay = original.overlay()
136         for env in original, overlay:
137             for ext in env.extensions.itervalues():
138                 assert ext.environment is env
139
140     def test_preprocessor_extension(self):
141         env = Environment(extensions=[PreprocessorExtension])
142         tmpl = env.from_string('{[[TEST]]}')
143         assert tmpl.render(foo=42) == '{(42)}'
144
145     def test_streamfilter_extension(self):
146         env = Environment(extensions=[StreamFilterExtension])
147         env.globals['gettext'] = lambda x: x.upper()
148         tmpl = env.from_string('Foo _(bar) Baz')
149         out = tmpl.render()
150         assert out == 'Foo BAR Baz'
151
152
153 def suite():
154     suite = unittest.TestSuite()
155     suite.addTest(unittest.makeSuite(ExtensionsTestCase))
156     return suite