1"""test_resources"""
2import unittest
3from nose.tools import eq_, assert_raises
4
5from routes import *
6
7class TestResourceGeneration(unittest.TestCase):
8    def _assert_restful_routes(self, m, options, path_prefix=''):
9        baseroute = '/' + path_prefix + options['controller']
10        eq_(baseroute, m.generate(action='index', **options))
11        eq_(baseroute + '.xml', m.generate(action='index', format='xml', **options))
12        eq_(baseroute + '/new', m.generate(action='new', **options))
13        eq_(baseroute + '/1', m.generate(action='show', id='1', **options))
14        eq_(baseroute + '/1/edit', m.generate(action='edit',id='1', **options))
15        eq_(baseroute + '/1.xml', m.generate(action='show', id='1',format='xml', **options))
16
17        eq_(baseroute, m.generate(action='create', method='post', **options))
18        eq_(baseroute + '/1', m.generate(action='update', method='put', id='1', **options))
19        eq_(baseroute + '/1', m.generate(action='delete', method='delete', id='1', **options))
20
21    def test_resources(self):
22        m = Mapper()
23        m.resource('message', 'messages')
24        m.resource('massage', 'massages')
25        m.resource('passage', 'passages')
26        m.create_regs(['messages'])
27        options = dict(controller='messages')
28        eq_('/messages', url_for('messages'))
29        eq_('/messages.xml', url_for('formatted_messages', format='xml'))
30        eq_('/messages/1', url_for('message', id=1))
31        eq_('/messages/1.xml', url_for('formatted_message', id=1, format='xml'))
32        eq_('/messages/new', url_for('new_message'))
33        eq_('/messages/1.xml', url_for('formatted_message', id=1, format='xml'))
34        eq_('/messages/1/edit', url_for('edit_message', id=1))
35        eq_('/messages/1/edit.xml', url_for('formatted_edit_message', id=1, format='xml'))
36        self._assert_restful_routes(m, options)
37
38    def test_resources_with_path_prefix(self):
39        m = Mapper()
40        m.resource('message', 'messages', path_prefix='/thread/:threadid')
41        m.create_regs(['messages'])
42        options = dict(controller='messages', threadid='5')
43        self._assert_restful_routes(m, options, path_prefix='thread/5/')
44
45    def test_resources_with_collection_action(self):
46        m = Mapper()
47        m.resource('message', 'messages', collection=dict(rss='GET'))
48        m.create_regs(['messages'])
49        options = dict(controller='messages')
50        self._assert_restful_routes(m, options)
51        eq_('/messages/rss', m.generate(controller='messages', action='rss'))
52        eq_('/messages/rss', url_for('rss_messages'))
53        eq_('/messages/rss.xml', m.generate(controller='messages', action='rss', format='xml'))
54        eq_('/messages/rss.xml', url_for('formatted_rss_messages', format='xml'))
55
56    def test_resources_with_member_action(self):
57        for method in ['put', 'post']:
58            m = Mapper()
59            m.resource('message', 'messages', member=dict(mark=method))
60            m.create_regs(['messages'])
61            options = dict(controller='messages')
62            self._assert_restful_routes(m, options)
63            eq_('/messages/1/mark', m.generate(method=method, action='mark', id='1', **options))
64            eq_('/messages/1/mark.xml',
65                m.generate(method=method, action='mark', id='1', format='xml', **options))
66
67    def test_resources_with_new_action(self):
68        m = Mapper()
69        m.resource('message', 'messages/', new=dict(preview='POST'))
70        m.create_regs(['messages'])
71        options = dict(controller='messages')
72        self._assert_restful_routes(m, options)
73        eq_('/messages/new/preview', m.generate(controller='messages', action='preview', method='post'))
74        eq_('/messages/new/preview', url_for('preview_new_message'))
75        eq_('/messages/new/preview.xml',
76            m.generate(controller='messages', action='preview', method='post', format='xml'))
77        eq_('/messages/new/preview.xml', url_for('formatted_preview_new_message', format='xml'))
78
79    def test_resources_with_name_prefix(self):
80        m = Mapper()
81        m.resource('message', 'messages', name_prefix='category_', new=dict(preview='POST'))
82        m.create_regs(['messages'])
83        options = dict(controller='messages')
84        self._assert_restful_routes(m, options)
85        eq_('/messages/new/preview', url_for('category_preview_new_message'))
86        assert_raises(Exception, url_for, 'category_preview_new_message', method='get')
87
88    def test_resources_with_requirements(self):
89        m = Mapper()
90        m.resource('message', 'messages', path_prefix='/{project_id}/{user_id}/',
91                   requirements={'project_id': r'[0-9a-f]{4}', 'user_id': r'\d+'})
92        options = dict(controller='messages', project_id='cafe', user_id='123')
93        self._assert_restful_routes(m, options, path_prefix='cafe/123/')
94
95        # in addition to the positive tests we need to guarantee we
96        # are not matching when the requirements don't match.
97        eq_({'action': u'create', 'project_id': u'cafe', 'user_id': u'123', 'controller': u'messages'},
98            m.match('/cafe/123/messages'))
99        eq_(None, m.match('/extensions/123/messages'))
100        eq_(None, m.match('/b0a3/123b/messages'))
101        eq_(None, m.match('/foo/bar/messages'))
102
103
104class TestResourceRecognition(unittest.TestCase):
105    def test_resource(self):
106        m = Mapper()
107        m.resource('person', 'people')
108        m.create_regs(['people'])
109
110        con = request_config()
111        con.mapper = m
112        def test_path(path, method):
113            env = dict(HTTP_HOST='example.com', PATH_INFO=path, REQUEST_METHOD=method)
114            con.mapper_dict = {}
115            con.environ = env
116
117        test_path('/people', 'GET')
118        eq_({'controller':'people', 'action':'index'}, con.mapper_dict)
119        test_path('/people.xml', 'GET')
120        eq_({'controller':'people', 'action':'index', 'format':'xml'}, con.mapper_dict)
121
122        test_path('/people', 'POST')
123        eq_({'controller':'people', 'action':'create'}, con.mapper_dict)
124        test_path('/people.html', 'POST')
125        eq_({'controller':'people', 'action':'create', 'format':'html'}, con.mapper_dict)
126
127        test_path('/people/2.xml', 'GET')
128        eq_({'controller':'people', 'action':'show', 'id':'2', 'format':'xml'}, con.mapper_dict)
129        test_path('/people/2', 'GET')
130        eq_({'controller':'people', 'action':'show', 'id':'2'}, con.mapper_dict)
131
132        test_path('/people/2/edit', 'GET')
133        eq_({'controller':'people', 'action':'edit', 'id':'2'}, con.mapper_dict)
134        test_path('/people/2/edit.xml', 'GET')
135        eq_({'controller':'people', 'action':'edit', 'id':'2', 'format':'xml'}, con.mapper_dict)
136
137        test_path('/people/2', 'DELETE')
138        eq_({'controller':'people', 'action':'delete', 'id':'2'}, con.mapper_dict)
139
140        test_path('/people/2', 'PUT')
141        eq_({'controller':'people', 'action':'update', 'id':'2'}, con.mapper_dict        )
142        test_path('/people/2.json', 'PUT')
143        eq_({'controller':'people', 'action':'update', 'id':'2', 'format':'json'}, con.mapper_dict        )
144
145        # Test for dots in urls
146        test_path('/people/2\.13', 'PUT')
147        eq_({'controller':'people', 'action':'update', 'id':'2\.13'}, con.mapper_dict)
148        test_path('/people/2\.13.xml', 'PUT')
149        eq_({'controller':'people', 'action':'update', 'id':'2\.13', 'format':'xml'}, con.mapper_dict)
150        test_path('/people/user\.name', 'PUT')
151        eq_({'controller':'people', 'action':'update', 'id':'user\.name'}, con.mapper_dict)
152        test_path('/people/user\.\.\.name', 'PUT')
153        eq_({'controller':'people', 'action':'update', 'id':'user\.\.\.name'}, con.mapper_dict)
154        test_path('/people/user\.name\.has\.dots', 'PUT')
155        eq_({'controller':'people', 'action':'update', 'id':'user\.name\.has\.dots'}, con.mapper_dict)
156        test_path('/people/user\.name\.is\.something.xml', 'PUT')
157        eq_({'controller':'people', 'action':'update', 'id':'user\.name\.is\.something', 'format':'xml'}, con.mapper_dict)
158        test_path('/people/user\.name\.ends\.with\.dot\..xml', 'PUT')
159        eq_({'controller':'people', 'action':'update', 'id':'user\.name\.ends\.with\.dot\.', 'format':'xml'}, con.mapper_dict)
160        test_path('/people/user\.name\.ends\.with\.dot\.', 'PUT')
161        eq_({'controller':'people', 'action':'update', 'id':'user\.name\.ends\.with\.dot\.'}, con.mapper_dict)
162        test_path('/people/\.user\.name\.starts\.with\.dot', 'PUT')
163        eq_({'controller':'people', 'action':'update', 'id':'\.user\.name\.starts\.with\.dot'}, con.mapper_dict)
164        test_path('/people/user\.name.json', 'PUT')
165        eq_({'controller':'people', 'action':'update', 'id':'user\.name', 'format':'json'}, con.mapper_dict)
166
167    def test_resource_with_nomin(self):
168        m = Mapper()
169        m.minimization = False
170        m.resource('person', 'people')
171        m.create_regs(['people'])
172
173        con = request_config()
174        con.mapper = m
175        def test_path(path, method):
176            env = dict(HTTP_HOST='example.com', PATH_INFO=path, REQUEST_METHOD=method)
177            con.mapper_dict = {}
178            con.environ = env
179
180        test_path('/people', 'GET')
181        eq_({'controller':'people', 'action':'index'}, con.mapper_dict)
182
183        test_path('/people', 'POST')
184        eq_({'controller':'people', 'action':'create'}, con.mapper_dict)
185
186        test_path('/people/2', 'GET')
187        eq_({'controller':'people', 'action':'show', 'id':'2'}, con.mapper_dict)
188        test_path('/people/2/edit', 'GET')
189        eq_({'controller':'people', 'action':'edit', 'id':'2'}, con.mapper_dict)
190
191        test_path('/people/2', 'DELETE')
192        eq_({'controller':'people', 'action':'delete', 'id':'2'}, con.mapper_dict)
193
194        test_path('/people/2', 'PUT')
195        eq_({'controller':'people', 'action':'update', 'id':'2'}, con.mapper_dict)
196
197    def test_resource_created_with_parent_resource(self):
198        m = Mapper()
199        m.resource('location', 'locations',
200                   parent_resource=dict(member_name='region',
201                                        collection_name='regions'))
202        m.create_regs(['locations'])
203
204        con = request_config()
205        con.mapper = m
206        def test_path(path, method):
207            env = dict(HTTP_HOST='example.com', PATH_INFO=path,
208                       REQUEST_METHOD=method)
209            con.mapper_dict = {}
210            con.environ = env
211
212        test_path('/regions/13/locations', 'GET')
213        eq_(con.mapper_dict, {'region_id': '13', 'controller': 'locations',
214                                   'action': 'index'})
215        url = url_for('region_locations', region_id=13)
216        eq_(url, '/regions/13/locations')
217
218        test_path('/regions/13/locations', 'POST')
219        eq_(con.mapper_dict, {'region_id': '13', 'controller': 'locations',
220                                   'action': 'create'})
221        # new
222        url = url_for('region_new_location', region_id=13)
223        eq_(url, '/regions/13/locations/new')
224        # create
225        url = url_for('region_locations', region_id=13)
226        eq_(url, '/regions/13/locations')
227
228        test_path('/regions/13/locations/60', 'GET')
229        eq_(con.mapper_dict, {'region_id': '13', 'controller': 'locations',
230                                   'id': '60', 'action': 'show'})
231        url = url_for('region_location', region_id=13, id=60)
232        eq_(url, '/regions/13/locations/60')
233
234        test_path('/regions/13/locations/60/edit', 'GET')
235        eq_(con.mapper_dict, {'region_id': '13', 'controller': 'locations',
236                                   'id': '60', 'action': 'edit'})
237        url = url_for('region_edit_location', region_id=13, id=60)
238        eq_(url, '/regions/13/locations/60/edit')
239
240        test_path('/regions/13/locations/60', 'DELETE')
241        eq_(con.mapper_dict, {'region_id': '13', 'controller': 'locations',
242                                   'id': '60', 'action': 'delete'})
243        url = url_for('region_location', region_id=13, id=60)
244        eq_(url, '/regions/13/locations/60')
245
246        test_path('/regions/13/locations/60', 'PUT')
247        eq_(con.mapper_dict, {'region_id': '13', 'controller': 'locations',
248                                   'id': '60', 'action': 'update'})
249        url = url_for('region_location', region_id=13, id=60)
250        eq_(url, '/regions/13/locations/60')
251
252        # Make sure ``path_prefix`` overrides work
253        # empty ``path_prefix`` (though I'm not sure why someone would do this)
254        m = Mapper()
255        m.resource('location', 'locations',
256                   parent_resource=dict(member_name='region',
257                                        collection_name='regions'),
258                   path_prefix='')
259        url = url_for('region_locations')
260        eq_(url, '/locations')
261        # different ``path_prefix``
262        m = Mapper()
263        m.resource('location', 'locations',
264                   parent_resource=dict(member_name='region',
265                                        collection_name='regions'),
266                   path_prefix='areas/:area_id')
267        url = url_for('region_locations', area_id=51)
268        eq_(url, '/areas/51/locations')
269
270        # Make sure ``name_prefix`` overrides work
271        # empty ``name_prefix``
272        m = Mapper()
273        m.resource('location', 'locations',
274                   parent_resource=dict(member_name='region',
275                                        collection_name='regions'),
276                   name_prefix='')
277        url = url_for('locations', region_id=51)
278        eq_(url, '/regions/51/locations')
279        # different ``name_prefix``
280        m = Mapper()
281        m.resource('location', 'locations',
282                   parent_resource=dict(member_name='region',
283                                        collection_name='regions'),
284                   name_prefix='area_')
285        url = url_for('area_locations', region_id=51)
286        eq_(url, '/regions/51/locations')
287
288        # Make sure ``path_prefix`` and ``name_prefix`` overrides work together
289        # empty ``path_prefix``
290        m = Mapper()
291        m.resource('location', 'locations',
292                   parent_resource=dict(member_name='region',
293                                        collection_name='regions'),
294                   path_prefix='',
295                   name_prefix='place_')
296        url = url_for('place_locations')
297        eq_(url, '/locations')
298        # empty ``name_prefix``
299        m = Mapper()
300        m.resource('location', 'locations',
301                   parent_resource=dict(member_name='region',
302                                        collection_name='regions'),
303                   path_prefix='areas/:area_id',
304                   name_prefix='')
305        url = url_for('locations', area_id=51)
306        eq_(url, '/areas/51/locations')
307        # different ``path_prefix`` and ``name_prefix``
308        m = Mapper()
309        m.resource('location', 'locations',
310                   parent_resource=dict(member_name='region',
311                                        collection_name='regions'),
312                   path_prefix='areas/:area_id',
313                   name_prefix='place_')
314        url = url_for('place_locations', area_id=51)
315        eq_(url, '/areas/51/locations')
316
317    def test_resource_created_with_parent_resource_nomin(self):
318        m = Mapper()
319        m.minimization = False
320        m.resource('location', 'locations',
321                   parent_resource=dict(member_name='region',
322                                        collection_name='regions'))
323        m.create_regs(['locations'])
324
325        con = request_config()
326        con.mapper = m
327        def test_path(path, method):
328            env = dict(HTTP_HOST='example.com', PATH_INFO=path,
329                       REQUEST_METHOD=method)
330            con.mapper_dict = {}
331            con.environ = env
332
333        test_path('/regions/13/locations', 'GET')
334        eq_(con.mapper_dict, {'region_id': '13', 'controller': 'locations',
335                                   'action': 'index'})
336        url = url_for('region_locations', region_id=13)
337        eq_(url, '/regions/13/locations')
338
339        test_path('/regions/13/locations', 'POST')
340        eq_(con.mapper_dict, {'region_id': '13', 'controller': 'locations',
341                                   'action': 'create'})
342        # new
343        url = url_for('region_new_location', region_id=13)
344        eq_(url, '/regions/13/locations/new')
345        # create
346        url = url_for('region_locations', region_id=13)
347        eq_(url, '/regions/13/locations')
348
349        test_path('/regions/13/locations/60', 'GET')
350        eq_(con.mapper_dict, {'region_id': '13', 'controller': 'locations',
351                                   'id': '60', 'action': 'show'})
352        url = url_for('region_location', region_id=13, id=60)
353        eq_(url, '/regions/13/locations/60')
354
355        test_path('/regions/13/locations/60/edit', 'GET')
356        eq_(con.mapper_dict, {'region_id': '13', 'controller': 'locations',
357                                   'id': '60', 'action': 'edit'})
358        url = url_for('region_edit_location', region_id=13, id=60)
359        eq_(url, '/regions/13/locations/60/edit')
360
361        test_path('/regions/13/locations/60', 'DELETE')
362        eq_(con.mapper_dict, {'region_id': '13', 'controller': 'locations',
363                                   'id': '60', 'action': 'delete'})
364        url = url_for('region_location', region_id=13, id=60)
365        eq_(url, '/regions/13/locations/60')
366
367        test_path('/regions/13/locations/60', 'PUT')
368        eq_(con.mapper_dict, {'region_id': '13', 'controller': 'locations',
369                                   'id': '60', 'action': 'update'})
370        url = url_for('region_location', region_id=13, id=60)
371        eq_(url, '/regions/13/locations/60')
372
373        # Make sure ``path_prefix`` overrides work
374        # empty ``path_prefix`` (though I'm not sure why someone would do this)
375        m = Mapper()
376        m.resource('location', 'locations',
377                   parent_resource=dict(member_name='region',
378                                        collection_name='regions'),
379                   path_prefix='/')
380        url = url_for('region_locations')
381        eq_(url, '/locations')
382        # different ``path_prefix``
383        m = Mapper()
384        m.resource('location', 'locations',
385                   parent_resource=dict(member_name='region',
386                                        collection_name='regions'),
387                   path_prefix='areas/:area_id')
388        url = url_for('region_locations', area_id=51)
389        eq_(url, '/areas/51/locations')
390
391        # Make sure ``name_prefix`` overrides work
392        # empty ``name_prefix``
393        m = Mapper()
394        m.resource('location', 'locations',
395                   parent_resource=dict(member_name='region',
396                                        collection_name='regions'),
397                   name_prefix='')
398        url = url_for('locations', region_id=51)
399        eq_(url, '/regions/51/locations')
400        # different ``name_prefix``
401        m = Mapper()
402        m.resource('location', 'locations',
403                   parent_resource=dict(member_name='region',
404                                        collection_name='regions'),
405                   name_prefix='area_')
406        url = url_for('area_locations', region_id=51)
407        eq_(url, '/regions/51/locations')
408
409        # Make sure ``path_prefix`` and ``name_prefix`` overrides work together
410        # empty ``path_prefix``
411        m = Mapper()
412        m.resource('location', 'locations',
413                   parent_resource=dict(member_name='region',
414                                        collection_name='regions'),
415                   path_prefix='',
416                   name_prefix='place_')
417        url = url_for('place_locations')
418        eq_(url, '/locations')
419        # empty ``name_prefix``
420        m = Mapper()
421        m.resource('location', 'locations',
422                   parent_resource=dict(member_name='region',
423                                        collection_name='regions'),
424                   path_prefix='areas/:area_id',
425                   name_prefix='')
426        url = url_for('locations', area_id=51)
427        eq_(url, '/areas/51/locations')
428        # different ``path_prefix`` and ``name_prefix``
429        m = Mapper()
430        m.resource('location', 'locations',
431                   parent_resource=dict(member_name='region',
432                                        collection_name='regions'),
433                   path_prefix='areas/:area_id',
434                   name_prefix='place_')
435        url = url_for('place_locations', area_id=51)
436        eq_(url, '/areas/51/locations')
437
438
439
440if __name__ == '__main__':
441    unittest.main()
442