summaryrefslogtreecommitdiff
path: root/tests/admin_views
diff options
context:
space:
mode:
authorSiHyunLee <antoliny0919@gmail.com>2026-02-20 23:43:41 +0900
committerGitHub <noreply@github.com>2026-02-20 09:43:41 -0500
commit283ea9e9e014adf0013c18700c36b98efa2f0aac (patch)
treeb8725eb30bae3e1f3e81d9538f74db419f07432e /tests/admin_views
parent96984b9b0f1d88f096985a908ee67dc6f2b9a682 (diff)
Fixed #36127 -- Applied default empty display value to links otherwise containing only whitespace in admin.
Diffstat (limited to 'tests/admin_views')
-rw-r--r--tests/admin_views/admin.py2
-rw-r--r--tests/admin_views/tests.py184
2 files changed, 183 insertions, 3 deletions
diff --git a/tests/admin_views/admin.py b/tests/admin_views/admin.py
index 8e8f7a32cc..6f7cd79e50 100644
--- a/tests/admin_views/admin.py
+++ b/tests/admin_views/admin.py
@@ -709,6 +709,8 @@ class CoverLetterAdmin(admin.ModelAdmin):
For testing fix for ticket #14529.
"""
+ formfield_overrides = {models.CharField: {"strip": False}}
+
def get_queryset(self, request):
return super().get_queryset(request).defer("date_written")
diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py
index fa9d9a2dc6..ea657fbf9f 100644
--- a/tests/admin_views/tests.py
+++ b/tests/admin_views/tests.py
@@ -2862,7 +2862,9 @@ class AdminViewPermissionsTest(TestCase):
self.assertContains(response, "<h1>Select article to view</h1>")
self.assertEqual(response.context["title"], "Select article to view")
response = self.client.get(article_change_url)
- self.assertContains(response, "<title>View article | Django site admin</title>")
+ self.assertContains(
+ response, "<title>- | View article | Django site admin</title>"
+ )
self.assertContains(response, "<h1>View article</h1>")
self.assertContains(response, "<label>Extra form field:</label>")
self.assertContains(
@@ -2891,7 +2893,7 @@ class AdminViewPermissionsTest(TestCase):
self.assertEqual(response.context["title"], "Change article")
self.assertContains(
response,
- "<title>Change article | Django site admin</title>",
+ "<title>- | Change article | Django site admin</title>",
)
self.assertContains(response, "<h1>Change article</h1>")
post = self.client.post(article_change_url, change_dict)
@@ -3016,7 +3018,9 @@ class AdminViewPermissionsTest(TestCase):
self.client.force_login(self.viewuser)
response = self.client.get(change_url)
self.assertEqual(response.context["title"], "View article")
- self.assertContains(response, "<title>View article | Django site admin</title>")
+ self.assertContains(
+ response, "<title>- | View article | Django site admin</title>"
+ )
self.assertContains(response, "<h1>View article</h1>")
self.assertContains(
response,
@@ -3608,6 +3612,180 @@ class AdminViewPermissionsTest(TestCase):
)
+@override_settings(ROOT_URLCONF="admin_views.urls")
+class AdminConsecutiveWhiteSpaceObjectDisplayTest(TestCase):
+ @classmethod
+ def setUpTestData(cls):
+ cls.user = User.objects.create_superuser(
+ username=" ", password="secret", email="super@example.com"
+ )
+ cls.obj = CoverLetter.objects.create(author=" ")
+ cls.change_link = reverse(
+ "admin:admin_views_coverletter_change", args=(cls.obj.pk,)
+ )
+
+ def setUp(self):
+ self.client.force_login(self.user)
+
+ def test_display_consecutive_whitespace_object_in_breadcrumbs(self):
+ user_change_link = reverse("admin:auth_user_change", args=(self.user.pk,))
+ cases = [
+ (
+ self.change_link,
+ '<li><a href="/test_admin/admin/admin_views/coverletter/">'
+ 'Cover letters</a></li><li aria-current="page">-</li>',
+ ),
+ (
+ reverse("admin:admin_views_coverletter_delete", args=(self.obj.pk,)),
+ f'<li><a href="{self.change_link}">-</a></li><li aria-current="page">'
+ "Delete</li>",
+ ),
+ (
+ reverse("admin:admin_views_coverletter_history", args=(self.obj.pk,)),
+ f'<li><a href="{self.change_link}">-</a></li><li aria-current="page">'
+ "History</li>",
+ ),
+ (
+ reverse("admin:auth_user_password_change", args=(self.user.pk,)),
+ f'<li><a href="{user_change_link}">-</a></li><li aria-current="page">'
+ "Change password</li>",
+ ),
+ ]
+ for url, expected_breadcrumbs in cases:
+ with self.subTest(url=url, expected_breadcrumbs=expected_breadcrumbs):
+ response = self.client.get(url)
+ self.assertContains(response, expected_breadcrumbs, html=True)
+
+ def test_display_consecutive_whitespace_object_in_delete_confirmation_page(self):
+ response = self.client.get(
+ reverse("admin:admin_views_coverletter_delete", args=(self.obj.pk,))
+ )
+ self.assertContains(
+ response,
+ "Are you sure you want to delete the cover letter “-”?",
+ )
+
+ # delete protected case
+ q = Question.objects.create(question=" ")
+ Answer.objects.create(question=q, answer="Because.")
+ response = self.client.get(
+ reverse("admin:admin_views_question_delete", args=(q.pk,))
+ )
+ self.assertContains(
+ response,
+ "Deleting the question “-” would require deleting the following protected "
+ "related objects",
+ )
+
+ # delete forbidden case
+ no_perms_user = User.objects.create_user(
+ username="no-perm", password="secret", is_staff=True
+ )
+ no_perms_user.user_permissions.add(
+ get_perm(Question, get_permission_codename("view", Question._meta))
+ )
+ no_perms_user.user_permissions.add(
+ get_perm(Question, get_permission_codename("delete", Question._meta))
+ )
+ self.client.force_login(no_perms_user)
+ response = self.client.get(
+ reverse("admin:admin_views_question_delete", args=(q.pk,))
+ )
+ self.assertContains(
+ response,
+ "Deleting the question “-” would result in deleting related objects, "
+ "but your account doesn't have permission to delete "
+ "the following types of objects",
+ )
+
+ def test_display_consecutive_whitespace_object_in_changelist(self):
+ response = self.client.get(reverse("admin:admin_views_coverletter_changelist"))
+ self.assertContains(response, f'<a href="{self.change_link}">-</a>')
+
+ def test_display_consecutive_whitespace_object_in_deleted_object(self):
+ response = self.client.get(
+ reverse("admin:admin_views_coverletter_delete", args=(self.obj.pk,))
+ )
+ self.assertContains(
+ response,
+ '<ul id="deleted-objects">'
+ f'<li>Cover letter: <a href="{self.change_link}">-</a></li></ul>',
+ html=True,
+ )
+
+ def test_display_consecutive_whitespace_object_in_recent_action(self):
+ for action in [ADDITION, DELETION]:
+ LogEntry.objects.log_actions(
+ user_id=self.user.pk,
+ queryset=[self.obj],
+ action_flag=action,
+ change_message=[],
+ single_object=True,
+ )
+
+ response = self.client.get(reverse("admin:index"))
+ self.assertContains(
+ response,
+ '<li class="addlink"><span class="visually-hidden">Added:</span>'
+ f'<a href="{self.change_link}">-</a><br><span class="mini quiet">'
+ "Cover letter</span></li>",
+ html=True,
+ )
+ self.assertContains(
+ response,
+ '<li class="deletelink">'
+ '<span class="visually-hidden">Deleted:</span>-'
+ '<br><span class="mini quiet">Cover letter</span></li>',
+ html=True,
+ )
+
+ def test_display_consecutive_whitespace_object_in_messages(self):
+ buttons = ["_save", "_continue", "_addanother"]
+ for button in buttons:
+ body = {"author": self.obj.author, button: "1"}
+ with self.subTest(obj=self.obj, button=button):
+ response = self.client.post(
+ reverse("admin:admin_views_coverletter_add"), body, follow=True
+ )
+ latest_cl = CoverLetter.objects.latest("id")
+ change_link = reverse(
+ "admin:admin_views_coverletter_change", args=(latest_cl.pk,)
+ )
+ self.assertContains(
+ response,
+ f'The cover letter “<a href="{change_link}">-</a>” '
+ "was added successfully.",
+ )
+ response = self.client.post(
+ reverse(
+ "admin:admin_views_coverletter_change", args=(latest_cl.pk,)
+ ),
+ {**body, "author": " "},
+ follow=True,
+ )
+ self.assertContains(
+ response,
+ f'The cover letter “<a href="{change_link}">-</a>” '
+ "was changed successfully.",
+ )
+
+ new_obj = CoverLetter.objects.create(author=self.obj.author)
+ response = self.client.post(
+ reverse("admin:admin_views_coverletter_delete", args=(new_obj.pk,)),
+ {"post": "yes"},
+ follow=True,
+ )
+ self.assertContains(response, "The cover letter “-” was deleted successfully.")
+
+ def test_display_consecutive_whitespace_object_in_sub_title(self):
+ response = self.client.get(self.change_link)
+ self.assertContains(response, "<h2>-</h2>")
+ response = self.client.get(
+ reverse("admin:admin_views_coverletter_history", args=(self.obj.pk,))
+ )
+ self.assertContains(response, "<h1>Change history: -</h1>")
+
+
@override_settings(
ROOT_URLCONF="admin_views.urls",
TEMPLATES=[