2
2
Unit tests for reverse URL lookups.
4
from __future__ import absolute_import
4
from __future__ import absolute_import, unicode_literals
6
6
from django.conf import settings
7
from django.contrib.auth.models import User
7
8
from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist
8
from django.core.urlresolvers import (reverse, resolve, NoReverseMatch,
9
Resolver404, ResolverMatch, RegexURLResolver, RegexURLPattern)
9
from django.core.urlresolvers import (reverse, resolve, get_callable,
10
get_resolver, NoReverseMatch, Resolver404, ResolverMatch, RegexURLResolver,
10
12
from django.http import HttpResponseRedirect, HttpResponsePermanentRedirect
11
13
from django.shortcuts import redirect
12
14
from django.test import TestCase
13
from django.utils import unittest
14
from django.contrib.auth.models import User
15
from django.utils import unittest, six
16
from . import urlconf_outer, urlconf_inner, middleware, views
17
from . import urlconf_outer, middleware, views
19
20
resolve_test_data = (
161
162
for name, expected, args, kwargs in test_data:
163
164
got = reverse(name, args=args, kwargs=kwargs)
164
except NoReverseMatch, e:
165
except NoReverseMatch:
165
166
self.assertEqual(expected, NoReverseMatch)
167
168
self.assertEqual(got, expected)
170
171
# Reversing None should raise an error, not return the last un-named view.
171
172
self.assertRaises(NoReverseMatch, reverse, None)
174
def test_prefix_braces(self):
175
self.assertEqual('/%7B%7Binvalid%7D%7D/includes/non_path_include/',
176
reverse('non_path_include', prefix='/{{invalid}}/'))
178
def test_prefix_parenthesis(self):
179
self.assertEqual('/bogus%29/includes/non_path_include/',
180
reverse('non_path_include', prefix='/bogus)/'))
182
def test_prefix_format_char(self):
183
self.assertEqual('/bump%2520map/includes/non_path_include/',
184
reverse('non_path_include', prefix='/bump%20map/'))
173
186
class ResolverTests(unittest.TestCase):
187
def test_resolver_repr(self):
189
Test repr of RegexURLResolver, especially when urlconf_name is a list
192
# Pick a resolver from a namespaced urlconf
193
resolver = get_resolver('regressiontests.urlpatterns_reverse.namespace_urls')
194
sub_resolver = resolver.namespace_dict['test-ns1'][1]
195
self.assertIn('<RegexURLPattern list>', repr(sub_resolver))
174
197
def test_non_regex(self):
176
199
Verifies that we raise a Resolver404 if what we are resolving doesn't
208
231
resolve('/included/non-existent-url', urlconf=urls)
209
232
self.fail('resolve did not raise a 404')
210
except Resolver404, e:
233
except Resolver404 as e:
211
234
# make sure we at least matched the root ('/') url resolver:
212
235
self.assertTrue('tried' in e.args[0])
213
236
tried = e.args[0]['tried']
214
237
self.assertEqual(len(e.args[0]['tried']), len(url_types_names), 'Wrong number of tried URLs returned. Expected %s, got %s.' % (len(url_types_names), len(e.args[0]['tried'])))
215
238
for tried, expected in zip(e.args[0]['tried'], url_types_names):
216
239
for t, e in zip(tried, expected):
217
self.assertTrue(isinstance(t, e['type']), '%s is not an instance of %s' % (t, e['type']))
240
self.assertTrue(isinstance(t, e['type']), str('%s is not an instance of %s') % (t, e['type']))
219
242
if not e['name']:
220
243
self.assertTrue(t.name is None, 'Expected no URL name but found %s.' % t.name)
405
428
def test_urlconf(self):
406
429
response = self.client.get('/test/me/')
407
430
self.assertEqual(response.status_code, 200)
408
self.assertEqual(response.content, 'outer:/test/me/,'
409
'inner:/inner_urlconf/second_test/')
431
self.assertEqual(response.content, b'outer:/test/me/,'
432
b'inner:/inner_urlconf/second_test/')
410
433
response = self.client.get('/inner_urlconf/second_test/')
411
434
self.assertEqual(response.status_code, 200)
412
435
response = self.client.get('/second_test/')
422
445
self.assertEqual(response.status_code, 404)
423
446
response = self.client.get('/second_test/')
424
447
self.assertEqual(response.status_code, 200)
425
self.assertEqual(response.content, 'outer:,inner:/second_test/')
448
self.assertEqual(response.content, b'outer:,inner:/second_test/')
427
450
def test_urlconf_overridden_with_null(self):
428
451
settings.MIDDLEWARE_CLASSES += (
501
524
self.assertEqual(match[1], args)
502
525
self.assertEqual(match[2], kwargs)
527
def test_resolver_match_on_request(self):
528
response = self.client.get('/resolver_match/')
529
resolver_match = response.resolver_match
530
self.assertEqual(resolver_match.url_name, 'test-resolver-match')
504
532
class ErroneousViewTests(TestCase):
505
533
urls = 'regressiontests.urlpatterns_reverse.erroneous_urls'
511
539
self.assertRaises(ViewDoesNotExist, self.client.get, '/missing_outer/')
512
540
self.assertRaises(ViewDoesNotExist, self.client.get, '/uncallable/')
542
def test_erroneous_reverse(self):
544
Ensure that a useful exception is raised when a regex is invalid in the
548
# The regex error will be hit before NoReverseMatch can be raised
549
self.assertRaises(ImproperlyConfigured, reverse, 'whatever blah blah')
551
class ViewLoadingTests(TestCase):
552
def test_view_loading(self):
553
# A missing view (identified by an AttributeError) should raise
554
# ViewDoesNotExist, ...
555
six.assertRaisesRegex(self, ViewDoesNotExist, ".*View does not exist in.*",
557
'regressiontests.urlpatterns_reverse.views.i_should_not_exist')
558
# ... but if the AttributeError is caused by something else don't
560
self.assertRaises(AttributeError, get_callable,
561
'regressiontests.urlpatterns_reverse.views_broken.i_am_broken')