Home | History | Annotate | Download | only in tests
      1 # -*- coding: utf-8 -*-
      2 import random
      3 
      4 import webapp2
      5 from webapp2 import BaseRoute, RedirectHandler, Request, Route, Router
      6 
      7 import test_base
      8 
      9 
     10 class TestRoute(test_base.BaseTestCase):
     11     def test_no_variable(self):
     12         route = Route(r'/hello', None)
     13         route, args, kwargs = route.match(Request.blank('/hello'))
     14         self.assertEqual(kwargs, {})
     15         url = route.build(Request.blank('/'), (), {})
     16         self.assertEqual(url, '/hello')
     17 
     18         route = Route(r'/hello/world/', None)
     19         route, args, kwargs = route.match(Request.blank('/hello/world/'))
     20         self.assertEqual(kwargs, {})
     21         url = route.build(Request.blank('/'), (), {})
     22         self.assertEqual(url, '/hello/world/')
     23 
     24     def test_repetition_operator(self):
     25         route = Route(r'/<:\d>', None)
     26         self.assertEqual(route.match(Request.blank('/1')), (route, ('1',), {}))
     27         self.assertEqual(route.match(Request.blank('/2')), (route, ('2',), {}))
     28 
     29         route = Route(r'/<:\d{2,3}>', None)
     30         self.assertEqual(route.match(Request.blank('/11')), (route, ('11',), {}))
     31         self.assertEqual(route.match(Request.blank('/111')), (route, ('111',), {}))
     32         self.assertEqual(route.match(Request.blank('/1111')), None)
     33 
     34     def test_unnamed_variable(self):
     35         route = Route(r'/<:\d{4}>', None)
     36         self.assertEqual(route.match(Request.blank('/2010')), (route, ('2010',), {}))
     37         self.assertEqual(route.match(Request.blank('/aaaa')), None)
     38 
     39         route = Route(r'/<:\d{2}>.<:\d{2}>', None)
     40         self.assertEqual(route.match(Request.blank('/98.99')), (route, ('98', '99'), {}))
     41         self.assertEqual(route.match(Request.blank('/aa.aa')), None)
     42 
     43         route = Route(r'/<:\d{2}>.<:\d{2}>/<foo>', None)
     44         self.assertEqual(route.match(Request.blank('/98.99/test')), (route, ('98', '99'), {'foo': 'test'}))
     45         self.assertEqual(route.match(Request.blank('/aa.aa/test')), None)
     46 
     47     def test_simple_variable(self):
     48         route = Route(r'/<foo>', None)
     49         self.assertEqual(route.match(Request.blank('/bar')), (route, (), {'foo': 'bar'}))
     50         url = route.build(Request.blank('/'), (), dict(foo='baz'))
     51         self.assertEqual(url, '/baz')
     52 
     53     def test_expr_variable(self):
     54         route = Route(r'/<year:\d{4}>', None)
     55         self.assertEqual(route.match(Request.blank('/bar')), None)
     56         self.assertEqual(route.match(Request.blank('/2010')), (route, (), {'year': '2010'}))
     57         self.assertEqual(route.match(Request.blank('/1900')), (route, (), {'year': '1900'}))
     58         url = route.build(Request.blank('/'), (), dict(year='2010'))
     59         self.assertEqual(url, '/2010')
     60 
     61     def test_expr_variable2(self):
     62         route = Route(r'/<year:\d{4}>/foo/', None)
     63         url = route.build(Request.blank('/'), (), dict(year='2010'))
     64         self.assertEqual(url, '/2010/foo/')
     65 
     66     def test_build_missing_argument(self):
     67         route = Route(r'/<:\d{4}>', None)
     68         self.assertRaises(KeyError, route.build, Request.blank('/'), (), {})
     69 
     70         route = Route(r'/<:\d{4}>/<:\d{2}>', None)
     71         self.assertRaises(KeyError, route.build, Request.blank('/'), (2010,), {})
     72 
     73     def test_build_invalid_argument(self):
     74         route = Route(r'/<:\d{4}>', None)
     75         self.assertRaises(ValueError, route.build, Request.blank('/'), ('20100',), {})
     76 
     77     def test_build_invalid_argument2(self):
     78         route = Route(r'/<:\d{4}>', None)
     79         self.assertRaises(ValueError, route.build, Request.blank('/'), ('201a',), {})
     80 
     81     def test_build_missing_keyword(self):
     82         route = Route(r'/<year:\d{4}>', None)
     83         self.assertRaises(KeyError, route.build, Request.blank('/'), (), {})
     84 
     85     def test_build_missing_keyword2(self):
     86         route = Route(r'/<year:\d{4}>/<month:\d{2}>', None)
     87         self.assertRaises(KeyError, route.build, Request.blank('/'), (), dict(year='2010'))
     88 
     89     def test_build_invalid_keyword(self):
     90         route = Route(r'/<year:\d{4}>', None)
     91         self.assertRaises(ValueError, route.build, Request.blank('/'), (), dict(year='20100'))
     92 
     93     def test_build_invalid_keyword2(self):
     94         route = Route(r'/<year:\d{4}>', None)
     95         self.assertRaises(ValueError, route.build, Request.blank('/'), (), dict(year='201a'))
     96 
     97     def test_build_with_unnamed_variable(self):
     98         route = Route(r'/<:\d{4}>/<month:\d{2}>', None)
     99 
    100         url = route.build(Request.blank('/'), (2010,), dict(month=10))
    101         self.assertEqual(url, '/2010/10')
    102 
    103         url = route.build(Request.blank('/'), ('1999',), dict(month='07'))
    104         self.assertEqual(url, '/1999/07')
    105 
    106     def test_build_default_keyword(self):
    107         route = Route(r'/<year:\d{4}>/<month:\d{2}>', None,
    108             defaults={'month': 10})
    109         url = route.build(Request.blank('/'), (), dict(year='2010'))
    110         self.assertEqual(url, '/2010/10')
    111 
    112         route = Route(r'/<year:\d{4}>/<month:\d{2}>', None,
    113             defaults={'year': 1900})
    114         url = route.build(Request.blank('/'), (), dict(month='07'))
    115         self.assertEqual(url, '/1900/07')
    116 
    117     def test_build_extra_keyword(self):
    118         route = Route(r'/<year:\d{4}>', None)
    119         url = route.build(Request.blank('/'), (), dict(year='2010', foo='bar'))
    120         self.assertEqual(url, '/2010?foo=bar')
    121         # Arguments are sorted.
    122         url = route.build(Request.blank('/'), (), dict(year='2010', foo='bar', baz='ding'))
    123         self.assertEqual(url, '/2010?baz=ding&foo=bar')
    124 
    125     def test_build_extra_positional_keyword(self):
    126         route = Route(r'/<year:\d{4}>/<:\d{2}>', None)
    127 
    128         url = route.build(Request.blank('/'), ('08', 'i-should-be-ignored', 'me-too'), dict(year='2010', foo='bar'))
    129         self.assertEqual(url, '/2010/08?foo=bar')
    130 
    131         url = route.build(Request.blank('/'), ('08', 'i-should-be-ignored', 'me-too'), dict(year='2010', foo='bar', baz='ding'))
    132         self.assertEqual(url, '/2010/08?baz=ding&foo=bar')
    133 
    134     def test_build_int_keyword(self):
    135         route = Route(r'/<year:\d{4}>', None)
    136         url = route.build(Request.blank('/'), (), dict(year=2010))
    137         self.assertEqual(url, '/2010')
    138 
    139     def test_build_int_variable(self):
    140         route = Route(r'/<:\d{4}>', None)
    141         url = route.build(Request.blank('/'), (2010,), {})
    142         self.assertEqual(url, '/2010')
    143 
    144     def test_router_build_error(self):
    145         router = Router(None)
    146         router.add(Route('/<year:\d{4}>', None, name='year-page'))
    147 
    148         url = router.build(Request.blank('/'), 'year-page', (), dict(year='2010'))
    149         self.assertEqual(url, '/2010')
    150 
    151         self.assertRaises(KeyError, router.build, Request.blank('/'), 'i-dont-exist', (), dict(year='2010'))
    152 
    153     def test_reverse_template(self):
    154         route = Route('/foo', None)
    155         # Access route.regex just to set the lazy properties.
    156         regex = route.regex
    157         self.assertEqual(route.reverse_template, '/foo')
    158 
    159         route = Route('/foo/<bar>', None)
    160         # Access route.regex just to set the lazy properties.
    161         regex = route.regex
    162         self.assertEqual(route.reverse_template, '/foo/%(bar)s')
    163 
    164         route = Route('/foo/<bar>/<baz:\d>', None)
    165         # Access route.regex just to set the lazy properties.
    166         regex = route.regex
    167         self.assertEqual(route.reverse_template, '/foo/%(bar)s/%(baz)s')
    168 
    169     def test_invalid_template(self):
    170         # To break it:
    171         # <>foo:><bar<:baz>
    172         route = Route('/<foo/<:bar', None)
    173         # Access route.regex just to set the lazy properties.
    174         regex = route.regex
    175         self.assertEqual(route.reverse_template, '/<foo/<:bar')
    176 
    177     def test_build_full_without_request(self):
    178         router = Router(None)
    179         router.add(Route(r'/hello', None, name='hello'))
    180         self.assertRaises(AttributeError, router.build, None, 'hello', (), dict(_full=True))
    181         self.assertRaises(AttributeError, router.build, None, 'hello', (), dict(_scheme='https'))
    182 
    183     def test_positions(self):
    184         template = '/<:\d+>' * 98
    185         args = tuple(str(i) for i in range(98))
    186         url_res = '/' + '/'.join(args)
    187 
    188         route = Route(template, None)
    189         self.assertEqual(route.match(Request.blank(url_res)), (route, args, {}))
    190         url = route.build(Request.blank('/'), args, {})
    191         self.assertEqual(url_res, url)
    192 
    193         args = [str(i) for i in range(1000)]
    194         random.shuffle(args)
    195         args = tuple(args[:98])
    196         url_res = '/' + '/'.join(args)
    197         self.assertEqual(route.match(Request.blank(url_res)), (route, args, {}))
    198         url = route.build(Request.blank('/'), args, {})
    199         self.assertEqual(url_res, url)
    200 
    201     def test_build_only_without_name(self):
    202         self.assertRaises(ValueError, Route, r'/<foo>', None, build_only=True)
    203 
    204     def test_route_repr(self):
    205         self.assertEqual(Route(r'/<foo>', None).__repr__(),
    206             "<Route('/<foo>', None, name=None, defaults={}, build_only=False)>")
    207         self.assertEqual(Route(r'/<foo>', None, name='bar', defaults={'baz': 'ding'}, build_only=True).__repr__(),
    208             "<Route('/<foo>', None, name='bar', defaults={'baz': 'ding'}, build_only=True)>")
    209 
    210         self.assertEqual(str(Route(r'/<foo>', None)),
    211             "<Route('/<foo>', None, name=None, defaults={}, build_only=False)>")
    212         self.assertEqual(str(Route(r'/<foo>', None, name='bar', defaults={'baz': 'ding'}, build_only=True)),
    213             "<Route('/<foo>', None, name='bar', defaults={'baz': 'ding'}, build_only=True)>")
    214 
    215     def test_router_repr(self):
    216         router = Router(None)
    217         router.add(Route(r'/hello', None, name='hello', build_only=True))
    218         router.add(Route(r'/world', None))
    219 
    220         self.assertEqual(router.__repr__(), "<Router([<Route('/world', None, name=None, defaults={}, build_only=False)>, <Route('/hello', None, name='hello', defaults={}, build_only=True)>])>")
    221 
    222     def test_base_route(self):
    223         route = BaseRoute('foo', 'bar')
    224         self.assertRaises(NotImplementedError, route.match, None)
    225 
    226     def test_set_matcher(self):
    227         req = Request.blank('/')
    228         def custom_matcher(router, request):
    229             self.assertEqual(request, req)
    230 
    231         router = Router(None)
    232         router.set_matcher(custom_matcher)
    233         router.match(req)
    234 
    235     def test_set_builder(self):
    236         req = Request.blank('/')
    237         def custom_builder(router, request, name, args, kwargs):
    238             self.assertEqual(request, req)
    239             return 'http://www.google.com'
    240 
    241         router = Router(None)
    242         router.set_builder(custom_builder)
    243         res = router.build(req, '', (), {})
    244         self.assertEqual(res, 'http://www.google.com')
    245 
    246     def test_set_adapter(self):
    247         def custom_adapter(router, handler):
    248             class MyAdapter(webapp2.BaseHandlerAdapter):
    249                 def __call__(self, request, response):
    250                     response.write('hello my adapter')
    251 
    252             return MyAdapter(handler)
    253 
    254         def myhandler(request, *args, **kwargs):
    255             return webapp2.Response('hello')
    256 
    257         app = webapp2.WSGIApplication([('/', myhandler)])
    258         app.router.set_adapter(custom_adapter)
    259 
    260         rsp = app.get_response('/')
    261         self.assertEqual(rsp.status_int, 200)
    262         self.assertEqual(rsp.body, 'hello my adapter')
    263 
    264     def test_methods(self):
    265         route = Route(r'/', methods=['GET', 'POST'])
    266         router = Router([route])
    267         req = Request.blank('/')
    268         req.method = 'GET'
    269         self.assertTrue(router.match(req) is not None)
    270         req.method = 'POST'
    271         self.assertTrue(router.match(req) is not None)
    272         req.method = 'PUT'
    273         self.assertRaises(webapp2.exc.HTTPMethodNotAllowed, router.match, req)
    274 
    275     def test_schemes(self):
    276         route = Route(r'/', schemes=['http'])
    277         req = Request.blank('http://mydomain.com/')
    278         self.assertTrue(route.match(req) is not None)
    279         req = Request.blank('https://mydomain.com/')
    280         self.assertTrue(route.match(req) is None)
    281 
    282         route = Route(r'/', schemes=['https'])
    283         req = Request.blank('https://mydomain.com/')
    284         self.assertTrue(route.match(req) is not None)
    285         req = Request.blank('http://mydomain.com/')
    286         self.assertTrue(route.match(req) is None)
    287 
    288 
    289 class TestSimpleRoute(test_base.BaseTestCase):
    290     def test_no_variable(self):
    291         router = webapp2.Router([(r'/', 'my_handler')])
    292 
    293         matched_route, args, kwargs = router.match(webapp2.Request.blank('/'))
    294         self.assertEqual(args, ())
    295         self.assertEqual(kwargs, {})
    296 
    297     def test_simple_variables(self):
    298         router = webapp2.Router([(r'/(\d{4})/(\d{2})', 'my_handler')])
    299 
    300         matched_route, args, kwargs = router.match(webapp2.Request.blank('/2007/10'))
    301         self.assertEqual(args, ('2007', '10'))
    302         self.assertEqual(kwargs, {})
    303 
    304     def test_build(self):
    305         route = webapp2.SimpleRoute('/', None)
    306         self.assertRaises(NotImplementedError, route.build, None, None, None)
    307 
    308     def test_route_repr(self):
    309         self.assertEqual(webapp2.SimpleRoute(r'/<foo>', None).__repr__(), "<SimpleRoute('/<foo>', None)>")
    310         self.assertEqual(str(webapp2.SimpleRoute(r'/<foo>', None)), "<SimpleRoute('/<foo>', None)>")
    311 
    312 
    313 if __name__ == '__main__':
    314     test_base.main()
    315