root / trunk / breve / tests / tags.py

Revision 406, 15.6 kB (checked in by cliff, 9 months ago)

AutoTag? support

Line 
1# -*- coding: utf-8 -*-
2
3import sys, os
4import doctest, unittest
5
6if __name__ == '__main__':
7    # force import from source directory rather than site-packages
8    sys.path.insert ( 0, os.path.abspath ( '../..' ) )
9    import breve
10
11from breve.tags import Tag, AutoTag
12from breve.tags.html import tags
13from breve.tags.entities import entities as E
14from breve.tags import macro, assign, xml, test, let
15from breve.flatten import flatten 
16from breve.util import Namespace
17from breve.tests.lib import my_name
18
19
20class SerializationTestCase ( unittest.TestCase ):
21
22    def test_tag_serialization ( self ):
23        '''basic tag flattening'''
24
25        T = tags
26        template = T.html [
27            T.head [ T.title [ my_name ( ) ] ],
28            T.body [ T.div [ 'okay' ] ]
29        ]
30        output = flatten ( template )
31        self.assertEqual ( 
32            output,
33            ( u'<html><head><title>test_tag_serialization</title></head>'
34              u'<body><div>okay</div></body></html>' )
35        )
36
37    def test_unicode ( self ):
38        '''unicode and string coercion'''
39
40        T = tags
41        template = T.html [
42            T.head [ T.title [ my_name ( ) ] ],
43            T.body [
44                'Brev\xc3\xa9 converts plain strings', T.br,
45                u'Brev\xe9 handles unicode strings', T.br,
46                T.div [ "Àåå? ▾ ", T.em [ "я Ме пПМОЌаю" ], "▾ 3 km²" ]
47            ]
48        ] 
49        output = flatten ( template )
50        self.assertEqual ( 
51            output,
52            ( u'<html><head><title>test_unicode</title></head>'
53              u'<body>Brevé converts plain strings<br />'
54              u'Brevé handles unicode strings<br />'
55              u'<div>Àåå? ▾ <em>я Ме пПМОЌаю</em>▾ 3 km²</div></body></html>' )
56        )
57
58    def test_unicode_attributes ( self ):
59        '''unicode and string coercion in attributes'''
60
61        T = tags
62        template = T.html [
63            T.head [ T.title [ my_name ( ) ] ],
64            T.body [
65                T.span ( id='уЎержОвать' ) [ "Coerce byte string to Unicode" ],
66                T.span ( id='Ме ПставляющОй сПЌМеМОй' ) [ "Explicit Unicode object" ]
67            ]
68        ]
69        output = flatten ( template )
70
71        self.assertEqual ( 
72            output,
73            ( u'<html><head><title>test_unicode_attributes</title></head><body>'
74              u'<span id="уЎержОвать">Coerce byte string to Unicode</span>'
75              u'<span id="Ме ПставляющОй сПЌМеМОй">Explicit Unicode object</span></body></html>' )
76        )
77
78    def test_test ( self ):
79        '''test() function'''
80
81        T = tags
82        template = T.html [
83            T.head [ T.title [ my_name ( ) ] ],
84            T.body [
85                test ( 1 == 1 ) and (
86                    T.span [ 'This is displayed' ]
87                ),
88                test ( 1 == 0 ) and (
89                    T.span [ 'This is not displayed' ]
90                )
91            ]
92        ]
93        output = flatten ( template )
94        self.assertEqual (
95            output,
96            ( u'<html><head><title>test_test</title></head>'
97              u'<body><span>This is displayed</span></body></html>' )
98        )
99
100    def test_escaping ( self ):
101        '''escaping, xml() directive'''
102
103        T = tags
104        template = T.html [
105            T.head [ T.title [ my_name ( ) ] ],
106            T.body [
107                T.div ( style = 'width: 400px;<should be &escaped&>' ) [
108                    T.p ( class_ = 'foo' ) [ '&&&' ],
109                    T.p [ 'Coffee', E.nbsp, E.amp, E.nbsp, 'cream' ],
110                    xml ( '''<div>this should be <u>unescaped</u> &amp; unaltered.</div>''' )
111                ]
112            ]
113        ]
114        output = flatten ( template )
115        self.assertEqual (
116            output,
117            ( u'<html><head><title>test_escaping</title></head>'
118              u'<body><div style="width: 400px;&lt;should be &amp;escaped&amp;&gt;">'
119              u'<p class="foo">&amp;&amp;&amp;</p><p>Coffee&#160;&#38;&#160;cream</p>'
120              u'<div>this should be <u>unescaped</u> &amp; unaltered.</div></div></body></html>' )
121        )
122
123    def test_tag_multiplication ( self ):
124        '''tag multiplication'''
125
126        T = tags
127        url_data = [
128            dict ( url = 'http://www.google.com', label = 'Google' ),
129            dict ( url = 'http://www.yahoo.com', label = 'Yahoo!' ),
130            dict ( url = 'http://www.amazon.com', label = 'Amazon' )
131        ]
132
133        template = T.html [
134            T.head [ T.title [ my_name ( ) ] ],
135            T.body [
136                T.ul [
137                    T.li [ T.a ( href="$url" ) [ "$label" ] ] * url_data
138                ]
139            ]
140        ]
141        output = flatten ( template )
142        self.assertEqual ( 
143            output,
144            ( u'<html><head><title>test_tag_multiplication</title></head>'
145              u'<body><ul><li><a href="http://www.google.com">Google</a></li>'
146              u'<li><a href="http://www.yahoo.com">Yahoo!</a></li>'
147              u'<li><a href="http://www.amazon.com">Amazon</a></li></ul></body></html>' )
148        )
149
150    def test_flatten_callable ( self ):
151        '''test flattening of callables'''
152
153        def my_callable ( ):
154            return "Hello, World"
155
156        T = tags
157        template = (
158            T.html [
159                T.head [ T.title [ my_name ( ) ] ],
160                T.body [
161                    T.div [ my_callable ]
162                ]
163            ]
164        )
165        actual = flatten ( template )
166        self.assertEqual ( 
167            actual,
168            ( u'<html><head><title>test_flatten_callable</title></head>'
169              u'<body><div>Hello, World</div></body></html>' )
170        )
171
172class MacrosTestCase ( unittest.TestCase ):
173    def test_macros ( self ):
174        '''test macros'''
175
176        T = tags
177        url_data = [
178            { 'url': 'http://www.google.com', 'label': 'Google' },
179            { 'url': 'http://www.yahoo.com', 'label': 'Yahoo!' },
180            { 'url': 'http://www.amazon.com', 'label': 'Amazon' }
181        ]
182
183        template = ( 
184            macro ( 'test_macro', lambda url, label: 
185                T.a ( href = url ) [ label ]
186            ),
187            T.html [
188                T.head [ T.title [ my_name ( ) ] ],
189                T.body [
190                    T.ul [ 
191                        [ T.li [ test_macro ( **_item ) ]
192                          for _item in url_data ]
193                    ]
194                ]
195            ]
196        )
197        output = flatten ( template )
198        self.assertEqual (
199            output,
200            ( u'<html><head><title>test_macros</title></head>'
201              u'<body><ul><li><a href="http://www.google.com">Google</a></li>'
202              u'<li><a href="http://www.yahoo.com">Yahoo!</a></li>'
203              u'<li><a href="http://www.amazon.com">Amazon</a></li></ul></body></html>' )
204        )
205
206    def test_nested_macros ( self ):
207        '''test nested macros'''
208
209        T = tags
210        url_data = [
211            { 'url': 'http://www.google.com', 'label': 'Google' },
212            { 'url': 'http://www.yahoo.com', 'label': 'Yahoo!' },
213            { 'url': 'http://www.amazon.com', 'label': 'Amazon' }
214        ]
215
216        template = ( 
217            macro ( 'list_macro', lambda url, label: (
218                macro ( 'link_macro', lambda _u, _l:
219                    T.a ( href = _u ) [ _l ]
220                ),
221                T.li [ link_macro ( url, label ) ]
222            ) ),
223            T.html [
224                T.head [ T.title [ my_name ( ) ] ],
225                T.body [
226                    T.ul [ 
227                        [ list_macro ( **_item )
228                          for _item in url_data ]
229                    ]
230                ]
231            ]
232        )
233        output = flatten ( template )
234        self.assertEqual (
235            output,
236            ( u'<html><head><title>test_nested_macros</title></head>'
237              u'<body><ul><li><a href="http://www.google.com">Google</a></li>'
238              u'<li><a href="http://www.yahoo.com">Yahoo!</a></li>'
239              u'<li><a href="http://www.amazon.com">Amazon</a></li></ul></body></html>' )
240        )
241
242    def test_tag_multiplication_with_macro ( self ):
243        '''tag multiplication including macro'''
244
245        T = tags
246        url_data = [
247            { 'url': 'http://www.google.com', 'label': 'Google', 'class': 'link' },
248            { 'url': 'http://www.yahoo.com', 'label': 'Yahoo!', 'class': 'link' },
249            { 'url': 'http://www.amazon.com', 'label': 'Amazon', 'class': 'link' }
250        ]
251
252        template = ( 
253            macro ( 'test_macro', lambda url: 
254                T.a ( href = url ) [ "$label" ]
255            ),
256            T.html [
257                T.head [ T.title [ my_name ( ) ] ],
258                T.body [
259                    T.ul [ 
260                        T.li ( class_="$class") [ test_macro ( "$url" ) ] * url_data 
261                    ]
262                ]
263            ]
264        )
265        output = flatten ( template )
266        self.assertEqual ( 
267            output,
268            ( u'<html><head><title>test_tag_multiplication_with_macro</title></head>'
269              u'<body><ul><li class="link"><a href="http://www.google.com">Google</a></li>'
270              u'<li class="link"><a href="http://www.yahoo.com">Yahoo!</a></li>'
271              u'<li class="link"><a href="http://www.amazon.com">Amazon</a></li></ul></body></html>' )
272        )
273
274    def test_let ( self ):
275        '''let directive'''
276
277        T = tags
278        template = ( 
279            let ( msg = 'okay' ),
280            T.html [
281                T.head [ T.title [ my_name ( ) ] ],
282                T.body [ T.div [ msg ] ]
283            ]
284        )
285        output = flatten ( template )
286        self.assertEqual (
287            output,
288            u'<html><head><title>test_let</title></head><body><div>okay</div></body></html>'
289        )
290
291    def test_assign ( self ):
292        '''assign directive'''
293
294        T = tags
295        template = ( 
296            assign ( 'msg', 'okay' ),
297            T.html [
298                T.head [ T.title [ my_name ( ) ] ],
299                T.body [ T.div [ msg ] ]
300            ]
301        )
302        output = flatten ( template )
303        self.assertEqual (
304            output,
305            u'<html><head><title>test_assign</title></head><body><div>okay</div></body></html>'
306        )
307
308    def test_assign_with_macro ( self ):
309        '''assign directive with macro'''
310
311        T = tags
312        template = ( 
313            assign ( 'msg', 'okay' ),
314            macro ( 'display_msg', lambda _m:
315                T.span [ _m ]
316            ),
317            T.html [
318                T.head [ T.title [ my_name ( ) ] ],
319                T.body [ T.div [ display_msg ( msg ) ] ]
320            ]
321        )
322        output = flatten ( template )
323        self.assertEqual (
324            output,
325            ( u'<html><head><title>test_assign_with_macro</title></head>'
326              u'<body><div><span>okay</span></div></body></html>' )
327        )
328
329
330class DOMTestCase ( unittest.TestCase ):
331
332    def test_dom_traversal ( self ):
333        '''tag.walk() DOM traversal'''
334
335        T = tags
336        template = T.html [
337            T.head [ T.title [ my_name ( ) ] ],
338            T.body [ T.div [ 'okay' ] ]
339        ]
340
341        traversal = [ ]
342        def callback ( item, is_tag ):
343            if is_tag:
344                traversal.append ( item.name )
345            else:
346                traversal.append ( item )
347
348        template.walk ( callback )
349        output = ''.join ( traversal )
350        self.assertEqual ( 
351            output,
352            u'htmlheadtitle%sbodydivokay' % my_name ( ),
353        )
354       
355    def test_dom_traversal_from_macro ( self ):
356        '''macro abuse: self-traversing template'''
357
358        T = tags
359        template = ( 
360            assign ( 'selectors', [ ] ),
361            macro ( 'css_sep', lambda attr:
362                attr == 'class' and '.' or '#'
363            ),
364            macro ( 'get_selectors', lambda tag, is_tag:
365                selectors.extend ( [
366                    "%s%s%s { }" % ( tag.name, css_sep ( _k.strip ( '_' ) ), _v )
367                    for _k, _v in tag.attrs.items ( )
368                    if _k.strip ( '_' ) in ( 'id', 'class' )
369                ] )
370            ),
371            macro ( 'extract_css', lambda tag:
372                tag.walk ( get_selectors, True ) and tag
373            ),
374            macro ( 'css_results', lambda selectors:
375                T.pre [ '\n'.join ( selectors ) ]
376            ),
377
378            T.html [
379                T.head [ T.title [ 'macro madness' ] ],
380                T.body [ extract_css (
381                    T.div ( class_ = 'text', id = 'main-content' ) [
382                        T.img ( src = '/images/breve-logo.png', alt = 'breve logo' ),
383                        T.br,
384                        T.span ( class_='bold' ) [ '''Hello from Breve!''' ]
385                    ]
386                ), css_results ( selectors ) ]
387            ]
388
389        )
390        output = flatten ( template )
391
392        self.assertEqual ( 
393            output,
394            ( u'<html><head><title>macro madness</title></head>'
395              u'<body><div class="text" id="main-content">'
396              u'<img src="/images/breve-logo.png" alt="breve logo"></img>'
397              u'<br /><span class="bold">Hello from Breve!</span></div>'
398              u'<pre>div.text { }\ndiv#main-content { }\nspan.bold { }</pre>'
399              u'</body></html>' )
400        )
401
402class CustomTagsTestCase ( unittest.TestCase ):
403
404    def test_custom_tags ( self ):
405        '''custom tags'''
406
407        from breve.tests.sitemap import tags, xmlns
408        T = Namespace ( tags )
409
410        # test data
411        loc = 'http://www.example.com/',
412        lastmod = '2008-01-01',
413        changefreq = 'monthly',
414        priority = 0.8 
415
416        template = T.urlset ( xmlns = xmlns ) [
417            T.url [
418                T.loc [ loc ],
419                T.lastmod [ lastmod ],
420                T.changefreq [ changefreq ],
421                T.priority [ priority ]
422            ]
423        ]
424        output = flatten ( template )
425
426        self.assertEqual ( 
427            output,
428            ( u'<urlset xmlns="http://www.google.com/schemas/sitemap/0.84/sitemap.xsd">'
429              u'<url><loc>http://www.example.com/</loc><lastmod>2008-01-01</lastmod>'
430              u'<changefreq>monthly</changefreq><priority>0.8</priority></url></urlset>' )
431        )
432
433    def test_dynamic_tags ( self ):
434        '''test dynamic creation of tags'''
435
436        template = (
437            assign ( 'mytag', Tag ( 'mytag' ) ),
438            mytag ( feature='foo' ) [
439                'hello, from mytag',
440                Tag ( 'explicit' ) ( feature='bar' ) [ 
441                    'hello from explicit tag'
442                ]
443            ]
444        )
445        actual = flatten ( template )
446        self.assertEqual ( 
447            actual,
448            u'<mytag feature="foo">hello, from mytag<explicit feature="bar">hello from explicit tag</explicit></mytag>'
449        )
450
451    def test_auto_tags ( self ):
452        '''test AutoTag class'''
453
454        T = AutoTag ( )
455        template = (
456            T.foo ( attr='foo' ) [
457                T.bar ( attr='bar' ),
458                T.baz ( attr='baz' )
459            ]
460        )
461        actual = flatten ( template )
462        self.assertEqual (
463            actual,
464            u'<foo attr="foo"><bar attr="bar"></bar><baz attr="baz"></baz></foo>'
465        )
466
467
468def suite ( ):
469    suite = unittest.TestSuite ( )
470
471    suite.addTest ( unittest.makeSuite ( SerializationTestCase, 'test' ) )
472    suite.addTest ( unittest.makeSuite ( MacrosTestCase, 'test' ) )
473    suite.addTest ( unittest.makeSuite ( DOMTestCase, 'test' ) )
474    suite.addTest ( unittest.makeSuite ( CustomTagsTestCase, 'test' ) )
475
476    return suite
477
478if __name__ == '__main__':
479    unittest.main ( defaultTest = 'suite' )
Note: See TracBrowser for help on using the browser.