diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py index cb44981a45..bd20afa92f 100644 --- a/tests/admin_views/tests.py +++ b/tests/admin_views/tests.py @@ -35,10 +35,10 @@ from django.test import override_settings from django.utils import formats from django.utils import translation from django.utils.cache import get_max_age -from django.utils.encoding import iri_to_uri, force_bytes +from django.utils.encoding import iri_to_uri, force_bytes, force_text from django.utils.html import escape from django.utils.http import urlencode, urlquote -from django.utils.six.moves.urllib.parse import urljoin +from django.utils.six.moves.urllib.parse import parse_qsl, urljoin, urlparse from django.utils._os import upath from django.utils import six @@ -4442,6 +4442,60 @@ class AdminKeepChangeListFiltersTests(TestCase): def tearDown(self): self.client.logout() + def assertURLEqual(self, url1, url2): + """ + Assert that two URLs are equal despite the ordering + of their querystring. Refs #22360. + """ + parsed_url1 = urlparse(url1) + path1 = parsed_url1.path + parsed_qs1 = dict(parse_qsl(parsed_url1.query)) + + parsed_url2 = urlparse(url2) + path2 = parsed_url2.path + parsed_qs2 = dict(parse_qsl(parsed_url2.query)) + + for parsed_qs in [parsed_qs1, parsed_qs2]: + if '_changelist_filters' in parsed_qs: + changelist_filters = parsed_qs['_changelist_filters'] + parsed_filters = dict(parse_qsl(changelist_filters)) + parsed_qs['_changelist_filters'] = parsed_filters + + self.assertEqual(path1, path2) + self.assertEqual(parsed_qs1, parsed_qs2) + + def test_assert_url_equal(self): + # Test equality. + self.assertURLEqual( + 'http://testserver/test_admin/admin/auth/user/105/?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0', + 'http://testserver/test_admin/admin/auth/user/105/?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0' + ) + + # Test inequality. + with self.assertRaises(AssertionError): + self.assertURLEqual( + 'http://testserver/test_admin/admin/auth/user/105/?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0', + 'http://testserver/test_admin/admin/auth/user/105/?_changelist_filters=is_staff__exact%3D1%26is_superuser__exact%3D1' + ) + + # Ignore scheme and host. + self.assertURLEqual( + 'http://testserver/test_admin/admin/auth/user/105/?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0', + '/test_admin/admin/auth/user/105/?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0' + ) + + # Ignore ordering of querystring. + self.assertURLEqual( + '/test_admin/admin/auth/user/?is_staff__exact=0&is_superuser__exact=0', + '/test_admin/admin/auth/user/?is_superuser__exact=0&is_staff__exact=0' + ) + + # Ignore ordering of _changelist_filters. + self.assertURLEqual( + '/test_admin/admin/auth/user/105/?_changelist_filters=is_staff__exact%3D0%26is_superuser__exact%3D0', + '/test_admin/admin/auth/user/105/?_changelist_filters=is_superuser__exact%3D0%26is_staff__exact%3D0' + ) + def get_changelist_filters(self): return { 'is_superuser__exact': 0, @@ -4505,8 +4559,11 @@ class AdminKeepChangeListFiltersTests(TestCase): self.assertEqual(response.status_code, 200) # Check the `change_view` link has the correct querystring. - detail_link = """joepublic""" % self.get_change_url() - self.assertContains(response, detail_link, count=1) + detail_link = re.search( + 'joepublic', + force_text(response.content) + ) + self.assertURLEqual(detail_link.group(1), self.get_change_url()) def test_change_view(self): # Get the `change_view`. @@ -4514,16 +4571,25 @@ class AdminKeepChangeListFiltersTests(TestCase): self.assertEqual(response.status_code, 200) # Check the form action. - form_action = """