source: OpenRLabs-Git/deploy/rlabs-docker/web2py-rlabs/gluon/tests/test_html.py @ 42095c5

mainqndtest v1.1.1
Last change on this file since 42095c5 was 42bd667, checked in by David Fuertes <dfuertes@…>, 4 years ago

Historial Limpio

  • Property mode set to 100755
File size: 40.3 KB
Line 
1#!/bin/python
2# -*- coding: utf-8 -*-
3
4"""
5    Unit tests for gluon.html
6"""
7
8import unittest
9
10
11from gluon.html import A, ASSIGNJS, B, BEAUTIFY, P, BODY, BR, BUTTON, CAT, CENTER, CODE, COL, COLGROUP, DIV, SPAN, URL, verifyURL
12from gluon.html import truncate_string, EM, FIELDSET, FORM, H1, H2, H3, H4, H5, H6, HEAD, HR, HTML, I, IFRAME, IMG, INPUT, EMBED
13from gluon.html import LABEL, LEGEND, LI, LINK, MARKMIN, MENU, META, OBJECT, OL, OPTGROUP, OPTION, PRE, SCRIPT, SELECT, STRONG
14from gluon.html import STYLE, TABLE, TR, TD, TAG, TBODY, THEAD, TEXTAREA, TFOOT, TH, TITLE, TT, UL, XHTML, XML, web2pyHTMLParser
15from gluon.storage import Storage
16from gluon.html import XML_pickle, XML_unpickle
17from gluon.html import TAG_pickler, TAG_unpickler
18from gluon._compat import xrange, PY2, to_native
19from gluon.decoder import decoder
20import re
21
22class TestBareHelpers(unittest.TestCase):
23
24    # xmlescape() = covered by other tests
25
26    # TODO: def test_call_as_list(self):
27
28    def test_truncate_string(self):
29        # Ascii text
30        self.assertEqual(truncate_string('Lorem ipsum dolor sit amet, consectetur adipiscing elit, '
31                                         'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
32                                         length=30), 'Lorem ipsum dolor sit amet,...')
33        self.assertEqual(truncate_string('Short text shorter than the length parameter.', length=100),
34                         'Short text shorter than the length parameter.')
35        # French text
36        self.assertEqual(truncate_string('Un texte en français avec des accents et des caractères bizarre.', length=30),
37                         'Un texte en français avec d...')
38
39    def test_StaticURL(self):
40        # test response.static_version coupled with response.static_version_urls
41        self.assertEqual(URL('a', 'c', 'f'), '/a/c/f')
42        self.assertEqual(URL('a', 'static', 'design.css'), '/a/static/design.css')
43        response = Storage()
44        response.static_version = '1.2.3'
45        from gluon.globals import current
46        current.response = response
47        self.assertEqual(URL('a', 'static', 'design.css'), '/a/static/design.css')
48        response.static_version_urls = True
49        self.assertEqual(URL('a', 'static', 'design.css'), '/a/static/_1.2.3/design.css')
50
51    def test_URL(self):
52        self.assertEqual(URL('a', 'c', 'f', args='1'), '/a/c/f/1')
53        self.assertEqual(URL('a', 'c', 'f', args=('1', '2')), '/a/c/f/1/2')
54        self.assertEqual(URL('a', 'c', 'f', args=['1', '2']), '/a/c/f/1/2')
55        self.assertEqual(URL('a', 'c', '/f'), '/a/c/f')
56        self.assertEqual(URL('a', 'c', 'f.json'), '/a/c/f.json')
57        from gluon.globals import current
58        current.request = None
59        self.assertRaises(SyntaxError, URL, *['a'])
60
61        request = Storage()
62        request.application = 'a'
63        request.controller = 'c'
64        request.function = 'f'
65        request.env = {}
66
67        from gluon.globals import current  # Can't be moved with other import
68        current.request = request
69
70        must_return = '/a/c/f'
71        self.assertEqual(URL(), must_return)
72        self.assertEqual(URL('f'), must_return)
73        self.assertEqual(URL('c', 'f'), must_return)
74        self.assertEqual(URL('a', 'c', 'f'), must_return)
75        self.assertEqual(URL('a', 'c', 'f', extension='json'), '/a/c/f.json')
76
77        def weird():
78            pass
79        self.assertEqual(URL('a', 'c', weird), '/a/c/weird')
80        self.assertRaises(SyntaxError, URL, *['a', 'c', 1])
81        # test signature
82        rtn = URL(a='a', c='c', f='f', args=['x', 'y', 'z'],
83                  vars={'p': (1, 3), 'q': 2}, anchor='1', hmac_key='key')
84        self.assertEqual(rtn, '/a/c/f/x/y/z?p=1&p=3&q=2&_signature=a32530f0d0caa80964bb92aad2bedf8a4486a31f#1')
85        # test _signature exclusion
86        rtn = URL(a='a', c='c', f='f', args=['x', 'y', 'z'],
87                  vars={'p': (1, 3), 'q': 2, '_signature': 'abc'},
88                  anchor='1', hmac_key='key')
89        self.assertEqual(rtn, '/a/c/f/x/y/z?p=1&p=3&q=2&_signature=a32530f0d0caa80964bb92aad2bedf8a4486a31f#1')
90        # emulate user_signature
91        current.session = Storage(auth=Storage(hmac_key='key'))
92        self.assertEqual(URL(user_signature=True), '/a/c/f?_signature=c4aed53c08cff08f369dbf8b5ba51889430cf2c2')
93        # hash_vars combination
94        rtn = URL('a', 'c', 'f', args=['x', 'y', 'z'], vars={'p': (1, 3), 'q': 2}, hmac_key='key')
95        self.assertEqual(rtn, '/a/c/f/x/y/z?p=1&p=3&q=2&_signature=a32530f0d0caa80964bb92aad2bedf8a4486a31f')
96        rtn = URL('a', 'c', 'f', args=['x', 'y', 'z'], vars={'p': (1, 3), 'q': 2}, hmac_key='key', hash_vars=True)
97        self.assertEqual(rtn, '/a/c/f/x/y/z?p=1&p=3&q=2&_signature=a32530f0d0caa80964bb92aad2bedf8a4486a31f')
98        rtn = URL('a', 'c', 'f', args=['x', 'y', 'z'], vars={'p': (1, 3), 'q': 2}, hmac_key='key', hash_vars=False)
99        self.assertEqual(rtn, '/a/c/f/x/y/z?p=1&p=3&q=2&_signature=0b5a0702039992aad23c82794b8496e5dcd59a5b')
100        rtn = URL('a', 'c', 'f', args=['x', 'y', 'z'], vars={'p': (1, 3), 'q': 2}, hmac_key='key', hash_vars=['p'])
101        self.assertEqual(rtn, '/a/c/f/x/y/z?p=1&p=3&q=2&_signature=5d01b982fd72b39674b012e0288071034e156d7a')
102        rtn = URL('a', 'c', 'f', args=['x', 'y', 'z'], vars={'p': (1, 3), 'q': 2}, hmac_key='key', hash_vars='p')
103        self.assertEqual(rtn, '/a/c/f/x/y/z?p=1&p=3&q=2&_signature=5d01b982fd72b39674b012e0288071034e156d7a')
104        # test CRLF detection
105        self.assertRaises(SyntaxError, URL, *['a\n', 'c', 'f'])
106        self.assertRaises(SyntaxError, URL, *['a\r', 'c', 'f'])
107        # test url_encode
108        rtn = URL('a', 'c', 'f', args=['x', 'y', 'z'], vars={'maï': (1, 3), 'lié': 2}, url_encode=True)
109        self.assertEqual(rtn, '/a/c/f/x/y/z?li%C3%A9=2&ma%C3%AF=1&ma%C3%AF=3')
110
111    @unittest.skipIf(not PY2, "Skipping Python 3.x tests for test_URL_encode")
112    def test_URL_encode(self):
113        rtn = URL('a', 'c', 'f', args=['x', 'y', 'z'], vars={'maï': (1, 3), 'lié': 2}, url_encode=False)
114        self.assertEqual(rtn, '/a/c/f/x/y/z?li\xc3\xa9=2&ma\xc3\xaf=1&ma\xc3\xaf=3')
115
116    def test_verifyURL(self):
117        r = Storage()
118        r.application = 'a'
119        r.controller = 'c'
120        r.function = 'f'
121        r.extension = 'html'
122        r.env = {}
123        r.get_vars = Storage()
124        # missing signature as request.get_vars returns False
125        rtn = verifyURL(r, 'key')
126        self.assertEqual(rtn, False)
127        # reverse tests from previous testcase with hash_vars combinations
128        r.args = ['x', 'y', 'z']
129        r.get_vars = Storage(p=(1, 3), q=2)
130        # add signature
131        r.get_vars['_signature'] = 'a32530f0d0caa80964bb92aad2bedf8a4486a31f'
132        rtn = verifyURL(r, 'key')
133        self.assertEqual(rtn, True)
134        r.get_vars['_signature'] = 'a32530f0d0caa80964bb92aad2bedf8a4486a31f'
135        rtn = verifyURL(r, 'key', hash_vars=True)
136        self.assertEqual(rtn, True)
137        r.get_vars['_signature'] = '0b5a0702039992aad23c82794b8496e5dcd59a5b'
138        rtn = verifyURL(r, 'key', hash_vars=False)
139        self.assertEqual(rtn, True)
140        r.get_vars['_signature'] = '5d01b982fd72b39674b012e0288071034e156d7a'
141        rtn = verifyURL(r, 'key', hash_vars=['p'])
142        self.assertEqual(rtn, True)
143        r.get_vars['_signature'] = '5d01b982fd72b39674b012e0288071034e156d7a'
144        rtn = verifyURL(r, 'key', hash_vars='p')
145        self.assertEqual(rtn, True)
146        # without session, user_signature returns always False
147        rtn = verifyURL(r, user_signature=True)
148        self.assertEqual(rtn, False)
149        # same goes if you don't use an hmac_key
150        rtn = verifyURL(r)
151        self.assertEqual(rtn, False)
152        # emulate user signature
153        from gluon.globals import current
154        current.session = Storage(auth=Storage(hmac_key='key'))
155        r.get_vars['_signature'] = 'a32530f0d0caa80964bb92aad2bedf8a4486a31f'
156        rtn = verifyURL(r, user_signature=True)
157        self.assertEqual(rtn, True)
158
159    # TODO: def test_XmlComponent(self):
160
161    def test_XML(self):
162        # sanitization process
163        self.assertEqual(XML('<h1>Hello<a data-hello="world">World</a></h1>').xml(),
164                         b'<h1>Hello<a data-hello="world">World</a></h1>')
165        # with sanitize, data-attributes are not permitted
166        self.assertEqual(XML('<h1>Hello<a data-hello="world">World</a></h1>', sanitize=True).xml(),
167                         b'<h1>HelloWorld</h1>')
168        # stringify by default
169        # FIXME PY3
170        # seams that __repr__ is no longer enough
171        ##self.assertEqual(XML('1.3'), '1.3')
172        self.assertEqual(XML(u'<div>è</div>').xml(), b'<div>\xc3\xa8</div>')
173        # make sure unicode works with sanitize
174        self.assertEqual(XML(u'<div>è</div>', sanitize=True).xml(), b'<div>\xc3\xa8</div>')
175        # you can calc len on the class, that equals the xml() and the str()
176        ##self.assertEqual(len(XML('1.3')), len('1.3'))
177        self.assertEqual(len(XML('1.3').xml()), len('1.3'))
178        ##self.assertEqual(len(str(XML('1.3'))), len('1.3'))
179        # you can concatenate them to strings (check for __add__ and __radd__ methods)
180        ##self.assertEqual(XML('a') + 'b', 'ab')
181        ##self.assertEqual(XML('a') + XML('b'), 'ab')
182        ##self.assertEqual('a' + XML('b'), 'ab')
183        # you can compare them
184        ##self.assertEqual(XML('a') == XML('a'), True)
185        # beware that the comparison is made on the XML repr
186
187        self.assertEqual(XML('<h1>Hello<a data-hello="world">World</a></h1>', sanitize=True).__repr__(),
188                         XML('<h1>HelloWorld</h1>').__repr__())
189        # bug check for the sanitizer for closing no-close tags
190        self.assertEqual(XML('<p>Test</p><br/><p>Test</p><br/>', sanitize=True).xml(),
191                         XML('<p>Test</p><br /><p>Test</p><br />').xml())
192        # basic flatten test
193        self.assertEqual(XML('<p>Test</p>').flatten(), '<p>Test</p>')
194        self.assertEqual(XML('<p>Test</p>').flatten(render=lambda text, tag, attr: text), '<p>Test</p>')
195
196    def test_XML_pickle_unpickle(self):
197        self.assertEqual(str(XML_unpickle(XML_pickle('data to be pickle')[1][0])), 'data to be pickle')
198
199    def test_DIV(self):
200        # Empty DIV()
201        self.assertEqual(DIV().xml(), b'<div></div>')
202        self.assertEqual(DIV('<>', _a='1', _b='2').xml(),
203                         b'<div a="1" b="2">&lt;&gt;</div>')
204        # attributes can be updated like in a dict
205        div = DIV('<>', _a='1')
206        div['_b'] = '2'
207        self.assertEqual(div.xml(),
208                         b'<div a="1" b="2">&lt;&gt;</div>')
209        # also with a mapping
210        div.update(_b=2, _c=3)
211        self.assertEqual(div.xml(),
212                         b'<div a="1" b="2" c="3">&lt;&gt;</div>')
213        # length of the DIV is the number of components
214        self.assertEqual(len(DIV('a', 'bc')), 2)
215        # also if empty, DIV is True in a boolean evaluation
216        self.assertTrue(True if DIV() else False)
217        # parent and siblings
218        a = DIV(SPAN('a'), DIV('b'))
219        s = a.element('span')
220        d = s.parent
221        d['_class'] = 'abc'
222        self.assertEqual(a.xml(), b'<div class="abc"><span>a</span><div>b</div></div>')
223        self.assertEqual([el.xml() for el in s.siblings()], [b'<div>b</div>'])
224        self.assertEqual(s.sibling().xml(), b'<div>b</div>')
225        # siblings with wrong args
226        self.assertEqual(s.siblings('a'), [])
227        # siblings with good args
228        self.assertEqual(s.siblings('div')[0].xml(), b'<div>b</div>')
229        # Check for siblings with wrong kargs and value
230        self.assertEqual(s.siblings(a='d'), [])
231        # Check for siblings with good kargs and value
232        # Can't figure this one out what is a right value here??
233        # Commented for now...
234        # self.assertEqual(s.siblings(div='<div>b</div>'), ???)
235        # No other sibling should return None
236        self.assertEqual(DIV(P('First element')).element('p').sibling(), None)
237        # --------------------------------------------------------------------------------------------------------------
238        # This use unicode to hit xmlescape() line :
239        #     """
240        #     elif isinstance(data, unicode):
241        #         data = data.encode('utf8', 'xmlcharrefreplace')
242        #     """
243        self.assertEqual(DIV(u'Texte en français avec des caractères accentués...').xml(),
244                         b'<div>Texte en fran\xc3\xa7ais avec des caract\xc3\xa8res accentu\xc3\xa9s...</div>')
245        # --------------------------------------------------------------------------------------------------------------
246        self.assertEqual(DIV('Test with an ID', _id='id-of-the-element').xml(),
247                         b'<div id="id-of-the-element">Test with an ID</div>')
248        self.assertEqual(DIV().element('p'), None)
249
250        # Corner case for raise coverage of one line
251        # I think such assert fail cause of python 2.6
252        # Work under python 2.7
253        # with self.assertRaises(SyntaxError) as cm:
254        #     DIV(BR('<>')).xml()
255        # self.assertEqual(cm.exception[0], '<br/> tags cannot have components')
256
257        # test .get('attrib')
258        self.assertEqual(DIV('<p>Test</p>', _class="class_test").get('_class'), 'class_test')
259        self.assertEqual(DIV(b'a').xml(), b'<div>a</div>')
260
261    def test_decoder(self):
262        tag_html = '<div><span><a id="1-1" u:v="$">hello</a></span><p class="this is a test">world</p></div>'
263        a = decoder(tag_html)
264        self.assertEqual(a, tag_html)
265
266    def test_CAT(self):
267        # Empty CAT()
268        self.assertEqual(CAT().xml(), b'')
269        # CAT('')
270        self.assertEqual(CAT('').xml(), b'')
271        # CAT(' ')
272        self.assertEqual(CAT(' ').xml(), b' ')
273
274    def test_TAG_pickler_unpickler(self):
275        # weird test
276        self.assertEqual(TAG_unpickler(TAG_pickler(TAG.div('data to be pickle'))[1][0]).xml(),
277                         b'<div>data to be pickle</div>')
278
279    def test_TAG(self):
280        self.assertEqual(TAG.first(TAG.second('test'), _key=3).xml(),
281                         b'<first key="3"><second>test</second></first>')
282        # ending in underscore "triggers" <input /> style
283        self.assertEqual(TAG.first_(TAG.second('test'), _key=3).xml(),
284                         b'<first key="3" />')
285        # unicode test for TAG
286        self.assertEqual(TAG.div(u'Texte en français avec des caractères accentués...').xml(),
287                         b'<div>Texte en fran\xc3\xa7ais avec des caract\xc3\xa8res accentu\xc3\xa9s...</div>')
288
289    def test_HTML(self):
290        self.assertEqual(HTML('<>', _a='1', _b='2').xml(),
291                         b'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">\n<html a="1" b="2" lang="en">&lt;&gt;</html>')
292        self.assertEqual(HTML('<>', _a='1', _b='2', doctype='strict').xml(),
293                         b'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html a="1" b="2" lang="en">&lt;&gt;</html>')
294        self.assertEqual(HTML('<>', _a='1', _b='2', doctype='transitional').xml(),
295                         b'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">\n<html a="1" b="2" lang="en">&lt;&gt;</html>')
296        self.assertEqual(HTML('<>', _a='1', _b='2', doctype='frameset').xml(),
297                         b'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">\n<html a="1" b="2" lang="en">&lt;&gt;</html>')
298        self.assertEqual(HTML('<>', _a='1', _b='2', doctype='html5').xml(),
299                         b'<!DOCTYPE HTML>\n<html a="1" b="2" lang="en">&lt;&gt;</html>')
300        self.assertEqual(HTML('<>', _a='1', _b='2', doctype='').xml(),
301                         b'<html a="1" b="2" lang="en">&lt;&gt;</html>')
302        self.assertEqual(HTML('<>', _a='1', _b='2', doctype='CustomDocType').xml(),
303                         b'CustomDocType\n<html a="1" b="2" lang="en">&lt;&gt;</html>')
304
305    def test_XHTML(self):
306        # Empty XHTML test
307        self.assertEqual(XHTML().xml(),
308                         b'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n<html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"></html>')
309        # Not Empty XHTML test
310        self.assertEqual(XHTML('<>', _a='1', _b='2').xml(),
311                         b'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n<html a="1" b="2" lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">&lt;&gt;</html>')
312        self.assertEqual(XHTML('<>', _a='1', _b='2', doctype='').xml(),
313                         b'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n<html a="1" b="2" lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">&lt;&gt;</html>')
314        self.assertEqual(XHTML('<>', _a='1', _b='2', doctype='strict').xml(),
315                         b'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n<html a="1" b="2" lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">&lt;&gt;</html>')
316        self.assertEqual(XHTML('<>', _a='1', _b='2', doctype='transitional').xml(),
317                         b'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n<html a="1" b="2" lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">&lt;&gt;</html>')
318        self.assertEqual(XHTML('<>', _a='1', _b='2', doctype='frameset').xml(),
319                         b'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">\n<html a="1" b="2" lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">&lt;&gt;</html>')
320        self.assertEqual(XHTML('<>', _a='1', _b='2', doctype='xmlns').xml(),
321                         b'xmlns\n<html a="1" b="2" lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">&lt;&gt;</html>')
322        self.assertEqual(XHTML('<>', _a='1', _b='2', _xmlns='xmlns').xml(),
323                         b'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n<html a="1" b="2" lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">&lt;&gt;</html>')
324
325    def test_HEAD(self):
326        self.assertEqual(HEAD('<>', _a='1', _b='2').xml(),
327                         b'<head a="1" b="2">&lt;&gt;</head>')
328
329    def test_TITLE(self):
330        self.assertEqual(TITLE('<>', _a='1', _b='2').xml(),
331                         b'<title a="1" b="2">&lt;&gt;</title>')
332
333    def test_META(self):
334        self.assertEqual(META(_a='1', _b='2').xml(),
335                         b'<meta a="1" b="2" />')
336
337    def test_LINK(self):
338        self.assertEqual(LINK(_a='1', _b='2').xml(),
339                         b'<link a="1" b="2" />')
340
341    def test_SCRIPT(self):
342        self.assertEqual(SCRIPT('<>', _a='1', _b='2').xml(),
343                         b'''<script a="1" b="2"><!--
344<>
345//--></script>''')
346        self.assertEqual(SCRIPT('<>').xml(),
347                         b'''<script><!--
348<>
349//--></script>''')
350        self.assertEqual(SCRIPT().xml(), b'<script></script>')
351        self.assertEqual(SCRIPT(';').xml() + DIV().xml(),
352                         b'<script><!--\n;\n//--></script><div></div>')
353
354    def test_STYLE(self):
355        self.assertEqual(STYLE('<>', _a='1', _b='2').xml(),
356                         b'<style a="1" b="2"><!--/*--><![CDATA[/*><!--*/\n<>\n/*]]>*/--></style>')
357        # Try to hit : return DIV.xml(self)
358        self.assertEqual(STYLE().xml(), b'<style></style>')
359
360    def test_IMG(self):
361        self.assertEqual(IMG(_a='1', _b='2').xml(),
362                         b'<img a="1" b="2" />')
363
364    def test_SPAN(self):
365        self.assertEqual(SPAN('<>', _a='1', _b='2').xml(),
366                         b'<span a="1" b="2">&lt;&gt;</span>')
367
368    def test_BODY(self):
369        self.assertEqual(BODY('<>', _a='1', _b='2').xml(),
370                         b'<body a="1" b="2">&lt;&gt;</body>')
371
372    def test_H1(self):
373        self.assertEqual(H1('<>', _a='1', _b='2').xml(),
374                         b'<h1 a="1" b="2">&lt;&gt;</h1>')
375
376    def test_H2(self):
377        self.assertEqual(H2('<>', _a='1', _b='2').xml(),
378                         b'<h2 a="1" b="2">&lt;&gt;</h2>')
379
380    def test_H3(self):
381        self.assertEqual(H3('<>', _a='1', _b='2').xml(),
382                         b'<h3 a="1" b="2">&lt;&gt;</h3>')
383
384    def test_H4(self):
385        self.assertEqual(H4('<>', _a='1', _b='2').xml(),
386                         b'<h4 a="1" b="2">&lt;&gt;</h4>')
387
388    def test_H5(self):
389        self.assertEqual(H5('<>', _a='1', _b='2').xml(),
390                         b'<h5 a="1" b="2">&lt;&gt;</h5>')
391
392    def test_H6(self):
393        self.assertEqual(H6('<>', _a='1', _b='2').xml(),
394                         b'<h6 a="1" b="2">&lt;&gt;</h6>')
395
396    def test_P(self):
397        self.assertEqual(P('<>', _a='1', _b='2').xml(),
398                         b'<p a="1" b="2">&lt;&gt;</p>')
399        # test cr2br
400        self.assertEqual(P('a\nb').xml(), b'<p>a\nb</p>')
401        self.assertEqual(P('a\nb', cr2br=True).xml(), b'<p>a<br />b</p>')
402
403    def test_STRONG(self):
404        self.assertEqual(STRONG('<>', _a='1', _b='2').xml(),
405                         b'<strong a="1" b="2">&lt;&gt;</strong>')
406
407    def test_B(self):
408        self.assertEqual(B('<>', _a='1', _b='2').xml(),
409                         b'<b a="1" b="2">&lt;&gt;</b>')
410
411    def test_BR(self):
412        # empty BR()
413        self.assertEqual(BR().xml(), b'<br />')
414        self.assertEqual(BR(_a='1', _b='2').xml(), b'<br a="1" b="2" />')
415
416    def test_HR(self):
417        self.assertEqual(HR(_a='1', _b='2').xml(), b'<hr a="1" b="2" />')
418
419    def test_A(self):
420        self.assertEqual(A('<>', _a='1', _b='2').xml(),
421                         b'<a a="1" b="2">&lt;&gt;</a>')
422        self.assertEqual(A('a', cid='b').xml(),
423                         b'<a data-w2p_disable_with="default" data-w2p_method="GET" data-w2p_target="b">a</a>')
424        self.assertEqual(A('a', callback='b', _id='c').xml(),
425                         b'<a data-w2p_disable_with="default" data-w2p_method="POST" href="b" id="c">a</a>')
426        # Callback with no id trigger web2py_uuid() call
427        from gluon.html import web2pyHTMLParser
428        #a = A('a', callback='b').xml()
429
430        #for tag in web2pyHTMLParser(a).tree.elements('a'):
431        #    uuid_generated = tag.attributes['_id']
432        #self.assertEqual(a,
433        #                 b'<a data-w2p_disable_with="default" data-w2p_method="POST" href="b" id="{id}">a</a>'.format(id=uuid_generated))
434        self.assertEqual(A('a', delete='tr').xml(),
435                         b'<a data-w2p_disable_with="default" data-w2p_remove="tr">a</a>')
436        self.assertEqual(A('a', _id='b', target='<self>').xml(),
437                         b'<a data-w2p_disable_with="default" data-w2p_target="b" id="b">a</a>')
438        self.assertEqual(A('a', component='b').xml(),
439                         b'<a data-w2p_disable_with="default" data-w2p_method="GET" href="b">a</a>')
440        self.assertEqual(A('a', _id='b', callback='c', noconfirm=True).xml(),
441                         b'<a data-w2p_disable_with="default" data-w2p_method="POST" href="c" id="b">a</a>')
442        self.assertEqual(A('a', cid='b').xml(),
443                         b'<a data-w2p_disable_with="default" data-w2p_method="GET" data-w2p_target="b">a</a>')
444        self.assertEqual(A('a', cid='b', _disable_with='processing...').xml(),
445                         b'<a data-w2p_disable_with="processing..." data-w2p_method="GET" data-w2p_target="b">a</a>')
446        self.assertEqual(A('a', callback='b', delete='tr', noconfirm=True, _id='c').xml(),
447                         b'<a data-w2p_disable_with="default" data-w2p_method="POST" data-w2p_remove="tr" href="b" id="c">a</a>')
448        self.assertEqual(A('a', callback='b', delete='tr', confirm='Are you sure?', _id='c').xml(),
449                         b'<a data-w2p_confirm="Are you sure?" data-w2p_disable_with="default" data-w2p_method="POST" data-w2p_remove="tr" href="b" id="c">a</a>')
450
451    def test_BUTTON(self):
452        self.assertEqual(BUTTON('test', _type='button').xml(),
453                         b'<button type="button">test</button>')
454
455    def test_EM(self):
456        self.assertEqual(EM('<>', _a='1', _b='2').xml(),
457                         b'<em a="1" b="2">&lt;&gt;</em>')
458
459    def test_EMBED(self):
460        self.assertEqual(EMBED(_a='1', _b='2').xml(),
461                         b'<embed a="1" b="2" />')
462
463    def test_TT(self):
464        self.assertEqual(TT('<>', _a='1', _b='2').xml(),
465                         b'<tt a="1" b="2">&lt;&gt;</tt>')
466
467    def test_PRE(self):
468        self.assertEqual(PRE('<>', _a='1', _b='2').xml(),
469                         b'<pre a="1" b="2">&lt;&gt;</pre>')
470
471    def test_CENTER(self):
472        self.assertEqual(CENTER('<>', _a='1', _b='2').xml(),
473                         b'<center a="1" b="2">&lt;&gt;</center>')
474
475    def test_CODE(self):
476        self.assertEqual(CODE("print 'hello world'",
477                              language='python',
478                              link=None,
479                              counter=1,
480                              styles={},
481                              highlight_line=None).xml(),
482                         '<table><tr style="vertical-align:top;"><td style="min-width:40px; text-align: right;"><pre style="\nfont-size: 11px;\nfont-family: Bitstream Vera Sans Mono,monospace;\nbackground-color: transparent;\nmargin: 0;\npadding: 5px;\nborder: none;\ncolor: #A0A0A0;\n">1.</pre></td><td><pre style="\nfont-size: 11px;\nfont-family: Bitstream Vera Sans Mono,monospace;\nbackground-color: transparent;\nmargin: 0;\npadding: 5px;\nborder: none;\noverflow: auto;\nwhite-space: pre !important;\n"><span style="color:#185369; font-weight: bold">print </span><span style="color: #FF9966">\'hello world\'</span></pre></td></tr></table>')
483
484    def test_LABEL(self):
485        self.assertEqual(LABEL('<>', _a='1', _b='2').xml(),
486                         b'<label a="1" b="2">&lt;&gt;</label>')
487
488    def test_LI(self):
489        self.assertEqual(LI('<>', _a='1', _b='2').xml(),
490                         b'<li a="1" b="2">&lt;&gt;</li>')
491
492    def test_UL(self):
493        self.assertEqual(UL('<>', _a='1', _b='2').xml(),
494                         b'<ul a="1" b="2"><li>&lt;&gt;</li></ul>')
495
496    def test_OL(self):
497        self.assertEqual(OL('<>', _a='1', _b='2').xml(),
498                         b'<ol a="1" b="2"><li>&lt;&gt;</li></ol>')
499
500    def test_TD(self):
501        self.assertEqual(TD('<>', _a='1', _b='2').xml(),
502                         b'<td a="1" b="2">&lt;&gt;</td>')
503
504    def test_TH(self):
505        self.assertEqual(TH('<>', _a='1', _b='2').xml(),
506                         b'<th a="1" b="2">&lt;&gt;</th>')
507
508    def test_TR(self):
509        self.assertEqual(TR('<>', _a='1', _b='2').xml(),
510                         b'<tr a="1" b="2"><td>&lt;&gt;</td></tr>')
511
512    def test_THEAD(self):
513        self.assertEqual(THEAD('<>', _a='1', _b='2').xml(),
514                         b'<thead a="1" b="2"><tr><th>&lt;&gt;</th></tr></thead>')
515        # self.assertEqual(THEAD(TRHEAD('<>'), _a='1', _b='2').xml(),
516        #                  '<thead a="1" b="2"><tr><th>&lt;&gt;</th></tr></thead>')
517        self.assertEqual(THEAD(TR('<>'), _a='1', _b='2').xml(),
518                         b'<thead a="1" b="2"><tr><td>&lt;&gt;</td></tr></thead>')
519
520    def test_TBODY(self):
521        self.assertEqual(TBODY('<>', _a='1', _b='2').xml(),
522                         b'<tbody a="1" b="2"><tr><td>&lt;&gt;</td></tr></tbody>')
523
524    def test_TFOOT(self):
525        self.assertEqual(TFOOT('<>', _a='1', _b='2').xml(),
526                         b'<tfoot a="1" b="2"><tr><td>&lt;&gt;</td></tr></tfoot>')
527
528    def test_COL(self):
529        # Empty COL test
530        self.assertEqual(COL().xml(), b'<col />')
531        # Not Empty COL test
532        self.assertEqual(COL(_span='2').xml(), b'<col span="2" />')
533        # Commented for now not so sure how to make it pass properly was passing locally
534        # I think this test is interesting and add value
535        # This fail relate to python 2.6 limitation I think
536        # Failing COL test
537        # with self.assertRaises(SyntaxError) as cm:
538        #     COL('<>').xml()
539        # self.assertEqual(cm.exception[0], '<col/> tags cannot have components')
540        # For now
541        self.assertRaises(SyntaxError, COL, b'<>')
542
543    def test_COLGROUP(self):
544        # Empty COLGROUP test
545        self.assertEqual(COLGROUP().xml(), b'<colgroup></colgroup>')
546        # Not Empty COLGROUP test
547        self.assertEqual(COLGROUP('<>', _a='1', _b='2').xml(), b'<colgroup a="1" b="2">&lt;&gt;</colgroup>')
548
549    def test_TABLE(self):
550        self.assertEqual(TABLE('<>', _a='1', _b='2').xml(),
551                         b'<table a="1" b="2"><tr><td>&lt;&gt;</td></tr>' +
552                         b'</table>')
553
554    def test_I(self):
555        self.assertEqual(I('<>', _a='1', _b='2').xml(),
556                         b'<i a="1" b="2">&lt;&gt;</i>')
557
558    def test_IFRAME(self):
559        self.assertEqual(IFRAME('<>', _a='1', _b='2').xml(),
560                         b'<iframe a="1" b="2">&lt;&gt;</iframe>')
561
562    def test_INPUT(self):
563        self.assertEqual(INPUT(_a='1', _b='2').xml(), b'<input a="1" b="2" type="text" />')
564        # list value
565        self.assertEqual(INPUT(_value=[1, 2, 3]).xml(), b'<input type="text" value="[1, 2, 3]" />')
566
567    def test_TEXTAREA(self):
568        self.assertEqual(TEXTAREA('<>', _a='1', _b='2').xml(),
569                         b'<textarea a="1" b="2" cols="40" rows="10">&lt;&gt;' +
570                         b'</textarea>')
571        # override _rows and _cols
572        self.assertEqual(TEXTAREA('<>', _a='1', _b='2', _rows=5, _cols=20).xml(),
573                         b'<textarea a="1" b="2" cols="20" rows="5">&lt;&gt;' +
574                         b'</textarea>')
575        self.assertEqual(TEXTAREA('<>', value='bla bla bla...', _rows=10, _cols=40).xml(),
576                         b'<textarea cols="40" rows="10">bla bla bla...</textarea>')
577
578    def test_OPTION(self):
579        self.assertEqual(OPTION('<>', _a='1', _b='2').xml(),
580                         b'<option a="1" b="2" value="&lt;&gt;">&lt;&gt;' +
581                         b'</option>')
582
583    def test_OBJECT(self):
584        self.assertEqual(OBJECT('<>', _a='1', _b='2').xml(),
585                         b'<object a="1" b="2">&lt;&gt;</object>')
586
587    def test_OPTGROUP(self):
588        # Empty OPTGROUP test
589        self.assertEqual(OPTGROUP().xml(),
590                         b'<optgroup></optgroup>')
591        # Not Empty OPTGROUP test
592        self.assertEqual(OPTGROUP('<>', _a='1', _b='2').xml(),
593                         b'<optgroup a="1" b="2"><option value="&lt;&gt;">&lt;&gt;</option></optgroup>')
594        # With an OPTION
595        self.assertEqual(OPTGROUP(OPTION('Option 1', _value='1'), _label='Group 1').xml(),
596                         b'<optgroup label="Group 1"><option value="1">Option 1</option></optgroup>')
597
598    def test_SELECT(self):
599        self.assertEqual(SELECT('<>', _a='1', _b='2').xml(),
600                         b'<select a="1" b="2">' +
601                         b'<option value="&lt;&gt;">&lt;&gt;</option></select>')
602        self.assertEqual(SELECT(OPTION('option 1', _value='1'),
603                                OPTION('option 2', _value='2')).xml(),
604                         b'<select><option value="1">option 1</option><option value="2">option 2</option></select>')
605        self.assertEqual(SELECT(OPTION('option 1', _value='1', _selected='selected'),
606                                OPTION('option 2', _value='2'),
607                                _multiple='multiple').xml(),
608                         b'<select multiple="multiple"><option selected="selected" value="1">option 1</option><option value="2">option 2</option></select>')
609        # More then one select with mutilple
610        self.assertEqual(SELECT(OPTION('option 1', _value='1', _selected='selected'),
611                                OPTION('option 2', _value='2', _selected='selected'),
612                                _multiple='multiple').xml(),
613                         b'<select multiple="multiple"><option selected="selected" value="1">option 1</option><option selected="selected" value="2">option 2</option></select>'
614                         )
615        # OPTGROUP
616        self.assertEqual(SELECT(OPTGROUP(OPTION('option 1', _value='1'),
617                                         OPTION('option 2', _value='2'),
618                                         _label='Group 1',)).xml(),
619                         b'<select><optgroup label="Group 1"><option value="1">option 1</option><option value="2">option 2</option></optgroup></select>')
620        # List
621        self.assertEqual(SELECT([1, 2, 3, 4, 5]).xml(),
622                         b'<select><option value="1">1</option><option value="2">2</option><option value="3">3</option><option value="4">4</option><option value="5">5</option></select>')
623        # Tuple
624        self.assertEqual(SELECT((1, 2, 3, 4, 5)).xml(),
625                         b'<select><option value="1">1</option><option value="2">2</option><option value="3">3</option><option value="4">4</option><option value="5">5</option></select>')
626        # String value
627        self.assertEqual(SELECT('Option 1', 'Option 2').xml(),
628                         b'<select><option value="Option 1">Option 1</option><option value="Option 2">Option 2</option></select>')
629        # list as a value
630        self.assertEqual(SELECT(OPTION('option 1', _value=[1, 2, 3]),
631                                OPTION('option 2', _value=[4, 5, 6], _selected='selected'),
632                                _multiple='multiple').xml(),
633                         b'<select multiple="multiple"><option value="[1, 2, 3]">option 1</option><option selected="selected" value="[4, 5, 6]">option 2</option></select>')
634
635    def test_FIELDSET(self):
636        self.assertEqual(FIELDSET('<>', _a='1', _b='2').xml(),
637                         b'<fieldset a="1" b="2">&lt;&gt;</fieldset>')
638
639    def test_LEGEND(self):
640        self.assertEqual(LEGEND('<>', _a='1', _b='2').xml(),
641                         b'<legend a="1" b="2">&lt;&gt;</legend>')
642
643    def test_FORM(self):
644        self.assertEqual(FORM('<>', _a='1', _b='2').xml(),
645                         b'<form a="1" action="#" b="2" enctype="multipart/form-data" method="post">&lt;&gt;</form>')
646        # These 2 crash AppVeyor and Travis with: "ImportError: No YAML serializer available"
647        # self.assertEqual(FORM('<>', _a='1', _b='2').as_yaml(),
648        #                  "accepted: null\nattributes: {_a: '1', _action: '#', _b: '2', _enctype: multipart/form-data, _method: post}\ncomponents: [<>]\nerrors: {}\nlatest: {}\nparent: null\nvars: {}\n")
649        # TODO check tags content
650        self.assertEqual(len(FORM('<>', _a='1', _b='2').as_xml()), 334)
651
652    def test_BEAUTIFY(self):
653        #self.assertEqual(BEAUTIFY(['a', 'b', {'hello': 'world'}]).xml(),
654        #                 '<div><table><tr><td><div>a</div></td></tr><tr><td><div>b</div></td></tr><tr><td><div><table><tr><td style="font-weight:bold;vertical-align:top;">hello</td><td style="vertical-align:top;">:</td><td><div>world</div></td></tr></table></div></td></tr></table></div>')
655        # unicode
656        self.assertEqual(BEAUTIFY([P(u'àéèûôç'), 'a', 'b', {'hello': 'world'}]).xml(),
657                         b'<div><table><tr><td><div><p>\xc3\xa0\xc3\xa9\xc3\xa8\xc3\xbb\xc3\xb4\xc3\xa7</p></div></td></tr><tr><td><div>a</div></td></tr><tr><td><div>b</div></td></tr><tr><td><div><table><tr><td style="font-weight:bold;vertical-align:top;">hello</td><td style="vertical-align:top;">:</td><td><div>world</div></td></tr></table></div></td></tr></table></div>')
658
659    def test_MENU(self):
660        self.assertEqual(MENU([('Home', False, '/welcome/default/index', [])]).xml(),
661                         b'<ul class="web2py-menu web2py-menu-vertical"><li class="web2py-menu-first"><a href="/welcome/default/index">Home</a></li></ul>')
662        # Multiples entries menu
663        self.assertEqual(MENU([('Home', False, '/welcome/default/index', []),
664                               ('Item 1', False, '/welcome/default/func_one', []),
665                               ('Item 2', False, '/welcome/default/func_two', []),
666                               ('Item 3', False, '/welcome/default/func_three', []),
667                               ('Item 4', False, '/welcome/default/func_four', [])]).xml(),
668                         b'<ul class="web2py-menu web2py-menu-vertical"><li class="web2py-menu-first"><a href="/welcome/default/index">Home</a></li><li><a href="/welcome/default/func_one">Item 1</a></li><li><a href="/welcome/default/func_two">Item 2</a></li><li><a href="/welcome/default/func_three">Item 3</a></li><li class="web2py-menu-last"><a href="/welcome/default/func_four">Item 4</a></li></ul>'
669                         )
670        # mobile=True
671        self.assertEqual(MENU([('Home', False, '/welcome/default/index', [])], mobile=True).xml(),
672                         b'<select class="web2py-menu web2py-menu-vertical" onchange="window.location=this.value"><option value="/welcome/default/index">Home</option></select>')
673        # Multiples entries menu for mobile
674        self.assertEqual(MENU([('Home', False, '/welcome/default/index', []),
675                               ('Item 1', False, '/welcome/default/func_one', []),
676                               ('Item 2', False, '/welcome/default/func_two', []),
677                               ('Item 3', False, '/welcome/default/func_three', []),
678                               ('Item 4', False, '/welcome/default/func_four', [])], mobile=True).xml(),
679                         b'<select class="web2py-menu web2py-menu-vertical" onchange="window.location=this.value"><option value="/welcome/default/index">Home</option><option value="/welcome/default/func_one">Item 1</option><option value="/welcome/default/func_two">Item 2</option><option value="/welcome/default/func_three">Item 3</option><option value="/welcome/default/func_four">Item 4</option></select>')
680
681    # TODO: def test_embed64(self):
682
683    def test_web2pyHTMLParser(self):
684        #tag should not be a byte
685        self.assertEqual(web2pyHTMLParser("<div></div>").tree.components[0].tag, 'div')
686        a = str(web2pyHTMLParser('<div>a<span>b</div>c').tree)
687        self.assertEqual(a, "<div>a<span>b</span></div>c")
688
689        tree = web2pyHTMLParser('hello<div a="b">world</div>').tree
690        tree.element(_a='b')['_c']=5
691        self.assertEqual(str(tree), 'hello<div a="b" c="5">world</div>')
692
693        a = str(web2pyHTMLParser('<div><img class="img"/></div>', closed=['img']).tree)
694        self.assertEqual(a, '<div><img class="img" /></div>')
695
696        #greater-than sign ( > )  --> decimal &#62; --> hexadecimal &#x3E;
697        #Less-than sign    ( < )  --> decimal &#60; --> hexadecimal &#x3C;
698        # test decimal
699        a = str(web2pyHTMLParser('<div>&#60; &#62;</div>').tree)
700        self.assertEqual(a, '<div>&lt; &gt;</div>')
701        # test hexadecimal
702        a = str(web2pyHTMLParser('<div>&#x3C; &#x3E;</div>').tree)
703        self.assertEqual(a, '<div>&lt; &gt;</div>')
704
705    def test_markdown(self):
706        def markdown(text, tag=None, attributes={}):
707            r = {None: re.sub('\s+',' ',text), \
708                 'h1':'#'+text+'\\n\\n', \
709                 'p':text+'\\n'}.get(tag,text)
710            return r
711        a=TAG('<h1>Header</h1><p>this is a     test</p>')
712        ret = a.flatten(markdown)
713        self.assertEqual(ret, '#Header\\n\\nthis is a test\\n')
714
715    # TODO: def test_markdown_serializer(self):
716
717    # TODO: def test_markmin_serializer(self):
718
719    def test_MARKMIN(self):
720        # This test pass with python 2.7 but expected to fail under 2.6
721        # with self.assertRaises(TypeError) as cm:
722        #     MARKMIN().xml()
723        # self.assertEqual(cm.exception[0], '__init__() takes at least 2 arguments (1 given)')
724        # For now
725        self.assertRaises(TypeError, MARKMIN)
726        self.assertEqual(MARKMIN('').xml(), b'')
727        self.assertEqual(MARKMIN('<>').xml(),
728                         b'<p>&lt;&gt;</p>')
729        self.assertEqual(MARKMIN("``hello_world = 'Hello World!'``:python").xml(),
730                         b'<code class="python">hello_world = \'Hello World!\'</code>')
731        self.assertEqual(MARKMIN('<>').flatten(), b'<>')
732
733    def test_ASSIGNJS(self):
734        # empty assignation
735        self.assertEqual(ASSIGNJS().xml(), b'')
736        # text assignation
737        self.assertEqual(ASSIGNJS(var1='1').xml(), b'var var1 = "1";\n')
738        # int assignation
739        self.assertEqual(ASSIGNJS(var2=2).xml(), b'var var2 = 2;\n')
740
741
742class TestData(unittest.TestCase):
743
744    def test_Adata(self):
745        self.assertEqual(A('<>', data=dict(abc='<def?asd>', cde='standard'), _a='1', _b='2').xml(),
746                         b'<a a="1" b="2" data-abc="&lt;def?asd&gt;" data-cde="standard">&lt;&gt;</a>')
Note: See TracBrowser for help on using the repository browser.