From 0721988b6533d1f7de2e5d2c05e55c63c84ad5dd Mon Sep 17 00:00:00 2001 From: niphlod Date: Wed, 24 Sep 2014 21:39:55 +0200 Subject: [PATCH] added tests for gluon/html.py and gluon/serializers.py uhm --- gluon/tests/__init__.py | 3 +- gluon/tests/test_html.py | 145 +++++++++++++++++++++++++++++++- gluon/tests/test_serializers.py | 67 +++++++++++++++ 3 files changed, 211 insertions(+), 4 deletions(-) create mode 100644 gluon/tests/test_serializers.py diff --git a/gluon/tests/__init__.py b/gluon/tests/__init__.py index 8aedb385..9d66896e 100644 --- a/gluon/tests/__init__.py +++ b/gluon/tests/__init__.py @@ -10,6 +10,7 @@ from test_languages import * from test_router import * from test_routes import * from test_storage import * +from test_serializers import * from test_template import * from test_validators import * from test_utils import * @@ -22,7 +23,7 @@ if sys.version[:3] == '2.7': NOSQL = any([name in (os.getenv("DB") or "") - for name in ("datastore", "mongodb", "imap")]) + for name in ("datastore", "mongodb", "imap")]) if NOSQL: from test_dal_nosql import * diff --git a/gluon/tests/test_html.py b/gluon/tests/test_html.py index bdc35558..27c7b725 100644 --- a/gluon/tests/test_html.py +++ b/gluon/tests/test_html.py @@ -11,6 +11,7 @@ from fix_path import fix_sys_path fix_sys_path(__file__) from html import * +from html import verifyURL from storage import Storage @@ -103,6 +104,28 @@ class TestBareHelpers(unittest.TestCase): def testDIV(self): self.assertEqual(DIV('<>', _a='1', _b='2').xml(), '
<>
') + # attributes can be updated like in a dict + div = DIV('<>', _a='1') + div['_b'] = '2' + self.assertEqual(div.xml(), + '
<>
') + # also with a mapping + div.update(_b=2, _c=3) + self.assertEqual(div.xml(), + '
<>
') + # length of the DIV is the number of components + self.assertEqual(len(DIV('a', 'bc')), 2) + # also if empty, DIV is True in a boolean evaluation + self.assertTrue(True if DIV() else False) + # parent and siblings + a = DIV(SPAN('a'), DIV('b')) + s = a.element('span') + d = s.parent + d['_class'] = 'abc' + self.assertEqual(a.xml(), '
a
b
') + self.assertEqual([el.xml() for el in s.siblings()], ['
b
']) + self.assertEqual(s.sibling().xml(), '
b
') + self.assertEqual(s.siblings('a'), []) def testEM(self): self.assertEqual(EM('<>', _a='1', _b='2').xml(), @@ -176,6 +199,9 @@ class TestBareHelpers(unittest.TestCase): def testP(self): self.assertEqual(P('<>', _a='1', _b='2').xml(), '

<>

') + # test cr2br + self.assertEqual(P('a\nb').xml(), '

a\nb

') + self.assertEqual(P('a\nb', cr2br=True).xml(), '

a
b

') def testPRE(self): self.assertEqual(PRE('<>', _a='1', _b='2').xml(), @@ -186,6 +212,11 @@ class TestBareHelpers(unittest.TestCase): '''''') + self.assertEqual(SCRIPT('<>').xml(), + '''''') + self.assertEqual(SCRIPT().xml(), '') def testSELECT(self): self.assertEqual(SELECT('<>', _a='1', _b='2').xml(), @@ -217,6 +248,10 @@ class TestBareHelpers(unittest.TestCase): self.assertEqual(TEXTAREA('<>', _a='1', _b='2').xml(), '') + # override _rows and _cols + self.assertEqual(TEXTAREA('<>', _a='1', _b='2', _rows=5, _cols=20).xml(), + '') def testTFOOT(self): self.assertEqual(TFOOT('<>', _a='1', _b='2').xml(), @@ -250,6 +285,37 @@ class TestBareHelpers(unittest.TestCase): self.assertEqual(UL('<>', _a='1', _b='2').xml(), '') + def testXML(self): + # sanitization process + self.assertEqual(XML('

HelloWorld

').xml(), + '

HelloWorld

') + # with sanitize, data-attributes are not permitted + self.assertEqual(XML('

HelloWorld

', sanitize=True).xml(), + '

HelloWorld

') + # stringify by default + self.assertEqual(XML(1.3), '1.3') + self.assertEqual(XML(u'
è
').xml(), '
\xc3\xa8
') + # you can calc len on the class, that equals the xml() and the str() + self.assertEqual(len(XML('1.3')), len('1.3')) + self.assertEqual(len(XML('1.3').xml()), len('1.3')) + self.assertEqual(len(str(XML('1.3'))), len('1.3')) + # you can concatenate them to strings (check for __add__ and __radd__ methods) + self.assertEqual(XML('a') + 'b', 'ab') + self.assertEqual(XML('a') + XML('b'), 'ab') + self.assertEqual('a' + XML('b'), 'ab') + # you can compare them + self.assertEqual(XML('a') == XML('a'), True) + # beware that the comparison is made on the XML repr + self.assertEqual(XML('

HelloWorld

', sanitize=True), + XML('

HelloWorld

')) + + def testTAG(self): + self.assertEqual(TAG.first(TAG.second('test'), _key=3).xml(), + 'test') + # ending in underscore "triggers" style + self.assertEqual(TAG.first_(TAG.second('test'), _key=3).xml(), + '') + def testStaticURL(self): # test response.static_version coupled with response.static_version_urls self.assertEqual(URL('a', 'c', 'f'), '/a/c/f') @@ -277,6 +343,7 @@ class TestBareHelpers(unittest.TestCase): from globals import current current.request = request must_return = '/a/c/f' + self.assertEqual(URL(), must_return) self.assertEqual(URL('f'), must_return) self.assertEqual(URL('c', 'f'), must_return) self.assertEqual(URL('a', 'c', 'f'), must_return) @@ -284,15 +351,87 @@ class TestBareHelpers(unittest.TestCase): def weird(): pass self.assertEqual(URL('a', 'c', weird), '/a/c/weird') - self.assertRaises(SyntaxError, URL, *['a','c', 1]) - + self.assertRaises(SyntaxError, URL, *['a', 'c', 1]) + # test signature + rtn = URL( + a='a', c='c', f='f', args=['x', 'y', 'z'], + vars={'p': (1, 3), 'q': 2}, anchor='1', hmac_key='key' + ) + self.assertEqual(rtn, '/a/c/f/x/y/z?p=1&p=3&q=2&_signature=a32530f0d0caa80964bb92aad2bedf8a4486a31f#1') + # test _signature exclusion + rtn = URL( + a='a', c='c', f='f', args=['x', 'y', 'z'], + vars={'p': (1, 3), 'q': 2, '_signature': 'abc'}, + anchor='1', hmac_key='key' + ) + self.assertEqual(rtn, '/a/c/f/x/y/z?p=1&p=3&q=2&_signature=a32530f0d0caa80964bb92aad2bedf8a4486a31f#1') + # emulate user_signature + current.session = Storage(auth=Storage(hmac_key='key')) + self.assertEqual(URL(user_signature=True), '/a/c/f?_signature=c4aed53c08cff08f369dbf8b5ba51889430cf2c2') + # hash_vars combination + rtn = URL('a','c','f', args=['x', 'y', 'z'], vars={'p' : (1,3), 'q' : 2}, hmac_key='key') + self.assertEqual(rtn, '/a/c/f/x/y/z?p=1&p=3&q=2&_signature=a32530f0d0caa80964bb92aad2bedf8a4486a31f') + rtn = URL('a','c','f', args=['x', 'y', 'z'], vars={'p' : (1,3), 'q' : 2}, hmac_key='key', hash_vars=True) + self.assertEqual(rtn, '/a/c/f/x/y/z?p=1&p=3&q=2&_signature=a32530f0d0caa80964bb92aad2bedf8a4486a31f') + rtn = URL('a','c','f', args=['x', 'y', 'z'], vars={'p' : (1,3), 'q' : 2}, hmac_key='key', hash_vars=False) + self.assertEqual(rtn, '/a/c/f/x/y/z?p=1&p=3&q=2&_signature=0b5a0702039992aad23c82794b8496e5dcd59a5b') + rtn = URL('a','c','f', args=['x', 'y', 'z'], vars={'p' : (1,3), 'q' : 2}, hmac_key='key', hash_vars=['p']) + self.assertEqual(rtn, '/a/c/f/x/y/z?p=1&p=3&q=2&_signature=5d01b982fd72b39674b012e0288071034e156d7a') + rtn = URL('a','c','f', args=['x', 'y', 'z'], vars={'p' : (1,3), 'q' : 2}, hmac_key='key', hash_vars='p') + self.assertEqual(rtn, '/a/c/f/x/y/z?p=1&p=3&q=2&_signature=5d01b982fd72b39674b012e0288071034e156d7a') + # test CRLF detection + self.assertRaises(SyntaxError, URL, *['a\n', 'c', 'f']) + self.assertRaises(SyntaxError, URL, *['a\r', 'c', 'f']) + def testverifyURL(self): + r = Storage() + r.application = 'a' + r.controller = 'c' + r.function = 'f' + r.extension = 'html' + r.env = {} + r.get_vars = Storage() + # missing signature as request.get_vars returns False + rtn = verifyURL(r, 'key') + self.assertEqual(rtn, False) + # reverse tests from previous testcase with hash_vars combinations + r.args = ['x', 'y', 'z'] + r.get_vars = Storage(p=(1, 3), q=2) + # add signature + r.get_vars['_signature'] = 'a32530f0d0caa80964bb92aad2bedf8a4486a31f' + rtn = verifyURL(r, 'key') + self.assertEqual(rtn, True) + r.get_vars['_signature'] = 'a32530f0d0caa80964bb92aad2bedf8a4486a31f' + rtn = verifyURL(r, 'key', hash_vars=True) + self.assertEqual(rtn, True) + r.get_vars['_signature'] = '0b5a0702039992aad23c82794b8496e5dcd59a5b' + rtn = verifyURL(r, 'key', hash_vars=False) + self.assertEqual(rtn, True) + r.get_vars['_signature'] = '5d01b982fd72b39674b012e0288071034e156d7a' + rtn = verifyURL(r, 'key', hash_vars=['p']) + self.assertEqual(rtn, True) + r.get_vars['_signature'] = '5d01b982fd72b39674b012e0288071034e156d7a' + rtn = verifyURL(r, 'key', hash_vars='p') + self.assertEqual(rtn, True) + # without session, user_signature returns always False + rtn = verifyURL(r, user_signature=True) + self.assertEqual(rtn, False) + # same goes if you don't use an hmac_key + rtn = verifyURL(r) + self.assertEqual(rtn, False) + # emulate user signature + from globals import current + current.session = Storage(auth=Storage(hmac_key='key')) + r.get_vars['_signature'] = 'a32530f0d0caa80964bb92aad2bedf8a4486a31f' + rtn = verifyURL(r, user_signature=True) + self.assertEqual(rtn, True) class TestData(unittest.TestCase): def testAdata(self): - self.assertEqual(A('<>', data=dict(abc='', cde='standard'), _a='1', _b='2').xml(),'<>') + self.assertEqual(A('<>', data=dict(abc='', cde='standard'), _a='1', _b='2').xml(), + '<>') if __name__ == '__main__': diff --git a/gluon/tests/test_serializers.py b/gluon/tests/test_serializers.py new file mode 100644 index 00000000..c3324238 --- /dev/null +++ b/gluon/tests/test_serializers.py @@ -0,0 +1,67 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +""" + Unit tests for gluon.serializers +""" + +import unittest +from fix_path import fix_sys_path +import datetime +import decimal + +fix_sys_path(__file__) + +from serializers import * +from storage import Storage +# careful with the import path 'cause of isinstance() checks +from gluon.languages import translator +from gluon.html import SPAN + + +class TestSerializers(unittest.TestCase): + + def testJSON(self): + # the main and documented "way" is to use the json() function + # it has a few corner-cases that make json() be somewhat + # different from the standard buyt being compliant + # it's just a matter of conventions + + # incompatible spacing, newer simplejson already account + # for this but it's still better to remember + weird = {'JSON': u"ro" + u'\u2028' + u'ck' + u'\u2029' + u's!'} + rtn = json(weird) + self.assertEqual(rtn, u'{"JSON": "ro\\u2028ck\\u2029s!"}') + # date, datetime, time strictly as strings in isoformat, minus the T + objs = [ + datetime.datetime(2014, 1, 1, 12, 15, 35), + datetime.date(2014, 1, 1), + datetime.time(12, 15, 35) + ] + iso_objs = [obj.isoformat()[:19].replace('T', ' ') for obj in objs] + json_objs = [json(obj) for obj in objs] + json_web2pyfied = [json(obj) for obj in iso_objs] + self.assertEqual(json_objs, json_web2pyfied) + # int or long int()ified + self.assertEqual(json(1), json(1L)) + # decimal stringified + obj = {'a': decimal.Decimal('4.312312312312')} + self.assertEqual(json(obj), u'{"a": "4.312312312312"}') + # lazyT translated + T = translator('', 'en') + lazy_translation = T('abc') + self.assertEqual(json(lazy_translation), u'"abc"') + # html helpers are xml()ed before too + self.assertEqual(json(SPAN('abc')), u'"abc"') + # unicode keys make a difference with loads_json + base = {u'è': 1, 'b': 2} + base_enc = json(base) + base_load = loads_json(base_enc) + self.assertTrue(base == base_load) + # if unicode_keys is false, the standard behaviour is assumed + base_load = loads_json(base_enc, unicode_keys=False) + self.assertFalse(base == base_load) + + +if __name__ == '__main__': + unittest.main()