1 | #!/usr/bin/env python |
---|
2 | # -*- coding: utf-8 -*- |
---|
3 | """ |
---|
4 | Unit tests for gluon.template |
---|
5 | """ |
---|
6 | |
---|
7 | import unittest |
---|
8 | import sys |
---|
9 | |
---|
10 | from yatl import render |
---|
11 | from yatl.template import DummyResponse, RestrictedError, NOESCAPE |
---|
12 | |
---|
13 | |
---|
14 | class TestTemplate(unittest.TestCase): |
---|
15 | |
---|
16 | def testRun(self): |
---|
17 | self.assertEqual(render(content='{{for i in range(n):}}{{=i}}{{pass}}', |
---|
18 | context=dict(n=3)), '012') |
---|
19 | self.assertEqual(render(content='{{if n>2:}}ok{{pass}}', |
---|
20 | context=dict(n=3)), 'ok') |
---|
21 | self.assertEqual( |
---|
22 | render(content='{{try:}}{{n/0}}{{except:}}fail{{pass}}', |
---|
23 | context=dict(n=3)), 'fail') |
---|
24 | self.assertEqual(render(content='{{="<&>"}}'), '<&>') |
---|
25 | self.assertEqual(render(content='"abc"'), '"abc"') |
---|
26 | self.assertEqual(render(content='"a\'bc"'), '"a\'bc"') |
---|
27 | self.assertEqual(render(content='"a\"bc"'), '"a\"bc"') |
---|
28 | self.assertEqual(render(content=r'"a\"bc"'), r'"a\"bc"') |
---|
29 | self.assertEqual(render(content=r'"""abc\""""'), r'"""abc\""""') |
---|
30 | |
---|
31 | def testEqualWrite(self): |
---|
32 | "test generation of response.write" |
---|
33 | self.assertEqual(render(content='{{=2+2}}'), '4') |
---|
34 | self.assertEqual(render(content='{{="abc"}}'), 'abc') |
---|
35 | # whitespace is stripped |
---|
36 | self.assertEqual(render(content='{{ ="abc"}}'), 'abc') |
---|
37 | self.assertEqual(render(content='{{ ="abc" }}'), 'abc') |
---|
38 | self.assertEqual(render(content='{{pass\n="abc" }}'), 'abc') |
---|
39 | # = recognized only at the beginning of a physical line |
---|
40 | self.assertEqual(render( |
---|
41 | content='{{xyz = "xyz"\n="abc"\n="def"\n=xyz }}'), 'abcdefxyz') |
---|
42 | # = in python blocks |
---|
43 | self.assertEqual(render(content='{{if True:\n="abc"\npass }}'), 'abc') |
---|
44 | self.assertEqual( |
---|
45 | render(content='{{if True:\n="abc"\npass\n="def" }}'), 'abcdef') |
---|
46 | self.assertEqual( |
---|
47 | render(content='{{if False:\n="abc"\npass\n="def" }}'), 'def') |
---|
48 | self.assertEqual(render( |
---|
49 | content='{{if True:\n="abc"\nelse:\n="def"\npass }}'), 'abc') |
---|
50 | self.assertEqual(render( |
---|
51 | content='{{if False:\n="abc"\nelse:\n="def"\npass }}'), 'def') |
---|
52 | # codeblock-leading = handles internal newlines, escaped or not |
---|
53 | self.assertEqual(render(content='{{=list((1,2,3))}}'), '[1, 2, 3]') |
---|
54 | self.assertEqual(render(content='{{=list((1,2,\\\n3))}}'), '[1, 2, 3]') |
---|
55 | self.assertEqual(render(content='{{=list((1,2,\n3))}}'), '[1, 2, 3]') |
---|
56 | # ...but that means no more = operators in the codeblock |
---|
57 | self.assertRaises(SyntaxError, render, content='{{="abc"\n="def" }}') |
---|
58 | # = embedded in codeblock won't handle newlines in its argument |
---|
59 | self.assertEqual( |
---|
60 | render(content='{{pass\n=list((1,2,\\\n3))}}'), '[1, 2, 3]') |
---|
61 | self.assertRaises( |
---|
62 | SyntaxError, render, content='{{pass\n=list((1,2,\n3))}}') |
---|
63 | |
---|
64 | def testWithDummyFileSystem(self): |
---|
65 | from os.path import join as pjoin |
---|
66 | import contextlib |
---|
67 | if sys.version_info[0] == 2: |
---|
68 | from cStringIO import StringIO |
---|
69 | else: |
---|
70 | from io import StringIO |
---|
71 | |
---|
72 | @contextlib.contextmanager |
---|
73 | def monkey_patch(module, fn_name, patch): |
---|
74 | try: |
---|
75 | unpatch = getattr(module, fn_name) |
---|
76 | except AttributeError: |
---|
77 | unpatch = None |
---|
78 | setattr(module, fn_name, patch) |
---|
79 | try: |
---|
80 | yield |
---|
81 | finally: |
---|
82 | if unpatch is None: |
---|
83 | delattr(module, fn_name) |
---|
84 | else: |
---|
85 | setattr(module, fn_name, unpatch) |
---|
86 | |
---|
87 | def dummy_open(path): |
---|
88 | if path == pjoin('views', 'layout.html'): |
---|
89 | return ("{{block left_sidebar}}left{{end}}" |
---|
90 | "{{include}}" |
---|
91 | "{{block right_sidebar}}right{{end}}") |
---|
92 | elif path == pjoin('views', 'layoutbrackets.html'): |
---|
93 | return ("[[block left_sidebar]]left[[end]]" |
---|
94 | "[[include]]" |
---|
95 | "[[block right_sidebar]]right[[end]]") |
---|
96 | elif path == pjoin('views', 'default', 'index.html'): |
---|
97 | return ("{{extend 'layout.html'}}" |
---|
98 | "{{block left_sidebar}}{{super}} {{end}}" |
---|
99 | "to" |
---|
100 | "{{block right_sidebar}} {{super}}{{end}}") |
---|
101 | elif path == pjoin('views', 'default', 'indexbrackets.html'): |
---|
102 | return ("[[extend 'layoutbrackets.html']]" |
---|
103 | "[[block left_sidebar]][[super]] [[end]]" |
---|
104 | "to" |
---|
105 | "[[block right_sidebar]] [[super]][[end]]") |
---|
106 | elif path == pjoin('views', 'default', 'missing.html'): |
---|
107 | return ("{{extend 'wut'}}" |
---|
108 | "{{block left_sidebar}}{{super}} {{end}}" |
---|
109 | "to" |
---|
110 | "{{block right_sidebar}} {{super}}{{end}}") |
---|
111 | elif path == pjoin('views', 'default', 'noescape.html'): |
---|
112 | return "{{=NOESCAPE('<script></script>')}}" |
---|
113 | raise IOError |
---|
114 | |
---|
115 | self.assertEqual( |
---|
116 | render(filename=pjoin('views', 'default', 'index.html'), |
---|
117 | path='views', reader=dummy_open), |
---|
118 | 'left to right') |
---|
119 | self.assertEqual( |
---|
120 | render(filename=pjoin('views', 'default', 'indexbrackets.html'), |
---|
121 | path='views', delimiters='[[ ]]', reader=dummy_open), |
---|
122 | 'left to right') |
---|
123 | #self.assertRaises( |
---|
124 | # RestrictedError, |
---|
125 | # render, |
---|
126 | # filename=pjoin('views', 'default', 'missing.html'), |
---|
127 | # path='views', |
---|
128 | # reader=dummy_open) |
---|
129 | response = DummyResponse() |
---|
130 | response.delimiters = ('[[', ']]') |
---|
131 | self.assertEqual( |
---|
132 | render(filename=pjoin('views', 'default', 'indexbrackets.html'), |
---|
133 | path='views', context={'response': response}, reader=dummy_open), |
---|
134 | 'left to right') |
---|
135 | self.assertEqual( |
---|
136 | render(filename=pjoin('views', 'default', 'noescape.html'), |
---|
137 | context={'NOESCAPE': NOESCAPE}, reader=dummy_open), |
---|
138 | '<script></script>') |
---|