355aa0c9b52f3ace022ac641b5d8e334bd3220d6
[jinja2.git] / jinja2 / testsuite / inheritance.py
1 # -*- coding: utf-8 -*-
2 """
3     jinja2.testsuite.inheritance
4     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
6     Tests the template inheritance feature.
7
8     :copyright: (c) 2010 by the Jinja Team.
9     :license: BSD, see LICENSE for more details.
10 """
11 import unittest
12
13 from jinja2.testsuite import JinjaTestCase
14
15 from jinja2 import Environment, DictLoader
16
17
18 LAYOUTTEMPLATE = '''\
19 |{% block block1 %}block 1 from layout{% endblock %}
20 |{% block block2 %}block 2 from layout{% endblock %}
21 |{% block block3 %}
22 {% block block4 %}nested block 4 from layout{% endblock %}
23 {% endblock %}|'''
24
25 LEVEL1TEMPLATE = '''\
26 {% extends "layout" %}
27 {% block block1 %}block 1 from level1{% endblock %}'''
28
29 LEVEL2TEMPLATE = '''\
30 {% extends "level1" %}
31 {% block block2 %}{% block block5 %}nested block 5 from level2{%
32 endblock %}{% endblock %}'''
33
34 LEVEL3TEMPLATE = '''\
35 {% extends "level2" %}
36 {% block block5 %}block 5 from level3{% endblock %}
37 {% block block4 %}block 4 from level3{% endblock %}
38 '''
39
40 LEVEL4TEMPLATE = '''\
41 {% extends "level3" %}
42 {% block block3 %}block 3 from level4{% endblock %}
43 '''
44
45 WORKINGTEMPLATE = '''\
46 {% extends "layout" %}
47 {% block block1 %}
48   {% if false %}
49     {% block block2 %}
50       this should workd
51     {% endblock %}
52   {% endif %}
53 {% endblock %}
54 '''
55
56 env = Environment(loader=DictLoader({
57     'layout':       LAYOUTTEMPLATE,
58     'level1':       LEVEL1TEMPLATE,
59     'level2':       LEVEL2TEMPLATE,
60     'level3':       LEVEL3TEMPLATE,
61     'level4':       LEVEL4TEMPLATE,
62     'working':      WORKINGTEMPLATE
63 }), trim_blocks=True)
64
65
66 class InheritanceTestCase(JinjaTestCase):
67
68     def test_layout(self):
69         tmpl = env.get_template('layout')
70         assert tmpl.render() == ('|block 1 from layout|block 2 from '
71                                  'layout|nested block 4 from layout|')
72
73     def test_level1(self):
74         tmpl = env.get_template('level1')
75         assert tmpl.render() == ('|block 1 from level1|block 2 from '
76                                  'layout|nested block 4 from layout|')
77
78     def test_level2(self):
79         tmpl = env.get_template('level2')
80         assert tmpl.render() == ('|block 1 from level1|nested block 5 from '
81                                  'level2|nested block 4 from layout|')
82
83     def test_level3(self):
84         tmpl = env.get_template('level3')
85         assert tmpl.render() == ('|block 1 from level1|block 5 from level3|'
86                                  'block 4 from level3|')
87
88     def test_level4(sel):
89         tmpl = env.get_template('level4')
90         assert tmpl.render() == ('|block 1 from level1|block 5 from '
91                                  'level3|block 3 from level4|')
92
93     def test_super(self):
94         env = Environment(loader=DictLoader({
95             'a': '{% block intro %}INTRO{% endblock %}|'
96                  'BEFORE|{% block data %}INNER{% endblock %}|AFTER',
97             'b': '{% extends "a" %}{% block data %}({{ '
98                  'super() }}){% endblock %}',
99             'c': '{% extends "b" %}{% block intro %}--{{ '
100                  'super() }}--{% endblock %}\n{% block data '
101                  '%}[{{ super() }}]{% endblock %}'
102         }))
103         tmpl = env.get_template('c')
104         assert tmpl.render() == '--INTRO--|BEFORE|[(INNER)]|AFTER'
105
106     def test_working(self):
107         tmpl = env.get_template('working')
108
109     def test_reuse_blocks(self):
110         tmpl = env.from_string('{{ self.foo() }}|{% block foo %}42'
111                                '{% endblock %}|{{ self.foo() }}')
112         assert tmpl.render() == '42|42|42'
113
114     def test_preserve_blocks(self):
115         env = Environment(loader=DictLoader({
116             'a': '{% if false %}{% block x %}A{% endblock %}{% endif %}{{ self.x() }}',
117             'b': '{% extends "a" %}{% block x %}B{{ super() }}{% endblock %}'
118         }))
119         tmpl = env.get_template('b')
120         assert tmpl.render() == 'BA'
121
122     def test_dynamic_inheritance(self):
123         env = Environment(loader=DictLoader({
124             'master1': 'MASTER1{% block x %}{% endblock %}',
125             'master2': 'MASTER2{% block x %}{% endblock %}',
126             'child': '{% extends master %}{% block x %}CHILD{% endblock %}'
127         }))
128         tmpl = env.get_template('child')
129         for m in range(1, 3):
130             assert tmpl.render(master='master%d' % m) == 'MASTER%dCHILD' % m
131
132     def test_multi_inheritance(self):
133         env = Environment(loader=DictLoader({
134             'master1': 'MASTER1{% block x %}{% endblock %}',
135             'master2': 'MASTER2{% block x %}{% endblock %}',
136             'child': '''{% if master %}{% extends master %}{% else %}{% extends
137                         'master1' %}{% endif %}{% block x %}CHILD{% endblock %}'''
138         }))
139         tmpl = env.get_template('child')
140         assert tmpl.render(master='master2') == 'MASTER2CHILD'
141         assert tmpl.render(master='master1') == 'MASTER1CHILD'
142         assert tmpl.render() == 'MASTER1CHILD'
143
144     def test_scoped_block(self):
145         env = Environment(loader=DictLoader({
146             'master.html': '{% for item in seq %}[{% block item scoped %}'
147                            '{% endblock %}]{% endfor %}'
148         }))
149         t = env.from_string('{% extends "master.html" %}{% block item %}'
150                             '{{ item }}{% endblock %}')
151         assert t.render(seq=range(5)) == '[0][1][2][3][4]'
152
153     def test_super_in_scoped_block(self):
154         env = Environment(loader=DictLoader({
155             'master.html': '{% for item in seq %}[{% block item scoped %}'
156                            '{{ item }}{% endblock %}]{% endfor %}'
157         }))
158         t = env.from_string('{% extends "master.html" %}{% block item %}'
159                             '{{ super() }}|{{ item * 2 }}{% endblock %}')
160         assert t.render(seq=range(5)) == '[0|0][1|2][2|4][3|6][4|8]'
161
162     def test_scoped_block_after_inheritance(self):
163         env = Environment(loader=DictLoader({
164             'layout.html': '''
165             {% block useless %}{% endblock %}
166             ''',
167             'index.html': '''
168             {%- extends 'layout.html' %}
169             {% from 'helpers.html' import foo with context %}
170             {% block useless %}
171                 {% for x in [1, 2, 3] %}
172                     {% block testing scoped %}
173                         {{ foo(x) }}
174                     {% endblock %}
175                 {% endfor %}
176             {% endblock %}
177             ''',
178             'helpers.html': '''
179             {% macro foo(x) %}{{ the_foo + x }}{% endmacro %}
180             '''
181         }))
182         rv = env.get_template('index.html').render(the_foo=42).split()
183         assert rv == ['43', '44', '45']
184
185
186 class BugFixTestCase(JinjaTestCase):
187
188     def test_fixed_macro_scoping_bug(self):
189         assert Environment(loader=DictLoader({
190             'test.html': '''\
191         {% extends 'details.html' %}
192
193         {% macro my_macro() %}
194         my_macro
195         {% endmacro %}
196
197         {% block inner_box %}
198             {{ my_macro() }}
199         {% endblock %}
200             ''',
201             'details.html': '''\
202         {% extends 'standard.html' %}
203
204         {% macro my_macro() %}
205         my_macro
206         {% endmacro %}
207
208         {% block content %}
209             {% block outer_box %}
210                 outer_box
211                 {% block inner_box %}
212                     inner_box
213                 {% endblock %}
214             {% endblock %}
215         {% endblock %}
216         ''',
217             'standard.html': '''
218         {% block content %} {% endblock %}
219         '''
220         })).get_template("test.html").render().split() == [u'outer_box', u'my_macro']
221
222
223 def suite():
224     suite = unittest.TestSuite()
225     suite.addTest(unittest.makeSuite(InheritanceTestCase))
226     suite.addTest(unittest.makeSuite(BugFixTestCase))
227     return suite