Browse Source

Refs #31617 -- Added an id for helptext in admin forms.

David Smith 3 years ago
parent
commit
6991880109

+ 2 - 2
django/contrib/admin/templates/admin/auth/user/change_password.html

@@ -34,7 +34,7 @@
   {{ form.password1.errors }}
   {{ form.password1.label_tag }} {{ form.password1 }}
   {% if form.password1.help_text %}
-  <div class="help">{{ form.password1.help_text|safe }}</div>
+  <div class="help"{% if form.password1.id_for_label %} id="{{ form.password1.id_for_label }}_helptext">{% endif %}{{ form.password1.help_text|safe }}</div>
   {% endif %}
 </div>
 
@@ -42,7 +42,7 @@
   {{ form.password2.errors }}
   {{ form.password2.label_tag }} {{ form.password2 }}
   {% if form.password2.help_text %}
-  <div class="help">{{ form.password2.help_text|safe }}</div>
+  <div class="help"{% if form.password2.id_for_label %} id="{{ form.password2.id_for_label }}_helptext"{% endif %}>{{ form.password2.help_text|safe }}</div>
   {% endif %}
 </div>
 

+ 3 - 1
django/contrib/admin/templates/admin/includes/fieldset.html

@@ -20,7 +20,9 @@
                         {% endif %}
                     {% endif %}
                     {% if field.field.help_text %}
-                        <div class="help">{{ field.field.help_text|safe }}</div>
+                        <div class="help"{% if field.field.id_for_label %} id="{{ field.field.id_for_label }}_helptext"{% endif %}>
+                          {{ field.field.help_text|safe }}
+                        </div>
                     {% endif %}
                 </div>
             {% endfor %}

+ 2 - 2
django/contrib/admin/templates/admin/search_form.html

@@ -3,7 +3,7 @@
 <div id="toolbar"><form id="changelist-search" method="get">
 <div><!-- DIV needed for valid HTML -->
 <label for="searchbar"><img src="{% static "admin/img/search.svg" %}" alt="Search"></label>
-<input type="text" size="40" name="{{ search_var }}" value="{{ cl.query }}" id="searchbar" autofocus>
+<input type="text" size="40" name="{{ search_var }}" value="{{ cl.query }}" id="searchbar" autofocus{% if cl.search_help_text %} aria-describedby="searchbar_helptext"{% endif %}>
 <input type="submit" value="{% translate 'Search' %}">
 {% if show_result_count %}
     <span class="small quiet">{% blocktranslate count counter=cl.result_count %}{{ counter }} result{% plural %}{{ counter }} results{% endblocktranslate %} (<a href="?{% if cl.is_popup %}{{ is_popup_var }}=1{% endif %}">{% if cl.show_full_result_count %}{% blocktranslate with full_result_count=cl.full_result_count %}{{ full_result_count }} total{% endblocktranslate %}{% else %}{% translate "Show all" %}{% endif %}</a>)</span>
@@ -14,7 +14,7 @@
 </div>
 {% if cl.search_help_text %}
 <br class="clear">
-<div class="help">{{ cl.search_help_text }}</div>
+<div class="help" id="searchbar_helptext">{{ cl.search_help_text }}</div>
 {% endif %}
 </form></div>
 {% endif %}

+ 2 - 2
django/contrib/admin/templates/registration/password_change_form.html

@@ -39,7 +39,7 @@
     {{ form.new_password1.errors }}
     {{ form.new_password1.label_tag }} {{ form.new_password1 }}
     {% if form.new_password1.help_text %}
-    <div class="help">{{ form.new_password1.help_text|safe }}</div>
+    <div class="help"{% if form.new_password1.id_for_label %} id="{{ form.new_password1.id_for_label }}_helptext"{% endif %}>{{ form.new_password1.help_text|safe }}</div>
     {% endif %}
 </div>
 
@@ -47,7 +47,7 @@
 {{ form.new_password2.errors }}
     {{ form.new_password2.label_tag }} {{ form.new_password2 }}
     {% if form.new_password2.help_text %}
-    <div class="help">{{ form.new_password2.help_text|safe }}</div>
+    <div class="help"{% if form.new_password2.id_for_label %} id="{{ form.new_password2.id_for_label }}_helptext"{% endif %}>{{ form.new_password2.help_text|safe }}</div>
     {% endif %}
 </div>
 

+ 9 - 2
tests/admin_changelist/tests.py

@@ -1523,7 +1523,7 @@ class ChangeListTests(TestCase):
         request = self._mocked_authenticated_request("/band/", superuser)
         response = m.changelist_view(request)
         self.assertIsNone(response.context_data["cl"].search_help_text)
-        self.assertNotContains(response, '<div class="help">')
+        self.assertNotContains(response, '<div class="help id="searchbar_helptext">')
         # search_fields with search_help_text.
         m.search_help_text = "Search help text"
         request = self._mocked_authenticated_request("/band/", superuser)
@@ -1531,7 +1531,14 @@ class ChangeListTests(TestCase):
         self.assertEqual(
             response.context_data["cl"].search_help_text, "Search help text"
         )
-        self.assertContains(response, '<div class="help">Search help text</div>')
+        self.assertContains(
+            response, '<div class="help" id="searchbar_helptext">Search help text</div>'
+        )
+        self.assertContains(
+            response,
+            '<input type="text" size="40" name="q" value="" id="searchbar" '
+            'autofocus aria-describedby="searchbar_helptext">',
+        )
 
 
 class GetAdminLogTests(TestCase):

+ 1 - 3
tests/admin_inlines/tests.py

@@ -263,9 +263,7 @@ class TestInline(TestDataMixin, TestCase):
         stacked and tabular layouts.
         """
         response = self.client.get(reverse("admin:admin_inlines_holder4_add"))
-        self.assertContains(
-            response, '<div class="help">Awesome stacked help text is awesome.</div>', 4
-        )
+        self.assertContains(response, "Awesome stacked help text is awesome.", 4)
         self.assertContains(
             response,
             '<img src="/static/admin/img/icon-unknown.svg" '

+ 57 - 7
tests/admin_views/tests.py

@@ -1449,8 +1449,43 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
         with self.assertNoLogs("django.template", "DEBUG"):
             self.client.post(reverse("admin:admin_views_article_changelist"), post_data)
 
+    @override_settings(
+        AUTH_PASSWORD_VALIDATORS=[
+            {
+                "NAME": (
+                    "django.contrib.auth.password_validation."
+                    "UserAttributeSimilarityValidator"
+                )
+            },
+            {
+                "NAME": (
+                    "django.contrib.auth.password_validation."
+                    "NumericPasswordValidator"
+                )
+            },
+        ]
+    )
+    def test_password_change_helptext(self):
+        response = self.client.get(reverse("admin:password_change"))
+        self.assertContains(
+            response, '<div class="help" id="id_new_password1_helptext">'
+        )
+
 
 @override_settings(
+    AUTH_PASSWORD_VALIDATORS=[
+        {
+            "NAME": (
+                "django.contrib.auth.password_validation."
+                "UserAttributeSimilarityValidator"
+            )
+        },
+        {
+            "NAME": (
+                "django.contrib.auth.password_validation." "NumericPasswordValidator"
+            )
+        },
+    ],
     TEMPLATES=[
         {
             "BACKEND": "django.template.backends.django.DjangoTemplates",
@@ -1470,7 +1505,7 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
                 ],
             },
         }
-    ]
+    ],
 )
 class AdminCustomTemplateTests(AdminViewBasicTestCase):
     def test_custom_model_admin_templates(self):
@@ -1563,6 +1598,19 @@ class AdminCustomTemplateTests(AdminViewBasicTestCase):
             response, '<input type="text" name="username" value="super" class="hidden">'
         )
 
+        # help text for passwords has an id.
+        self.assertContains(
+            response,
+            '<div class="help" id="id_password1_helptext"><ul><li>'
+            "Your password can’t be too similar to your other personal information."
+            "</li><li>Your password can’t be entirely numeric.</li></ul></div>",
+        )
+        self.assertContains(
+            response,
+            '<div class="help" id="id_password2_helptext">'
+            "Enter the same password as before, for verification.</div>",
+        )
+
     def test_extended_bodyclass_template_index(self):
         """
         The admin/index.html template uses block.super in the bodyclass block.
@@ -6271,17 +6319,17 @@ class ReadonlyTest(AdminFieldExtractionMixin, TestCase):
         self.assertContains(response, '<div class="form-row field-posted">')
         self.assertContains(response, '<div class="form-row field-value">')
         self.assertContains(response, '<div class="form-row">')
-        self.assertContains(response, '<div class="help">', 3)
+        self.assertContains(response, '<div class="help"', 3)
         self.assertContains(
             response,
-            '<div class="help">Some help text for the title (with Unicode ŠĐĆŽćžšđ)'
-            "</div>",
+            '<div class="help" id="id_title_helptext">Some help text for the title '
+            "(with Unicode ŠĐĆŽćžšđ)</div>",
             html=True,
         )
         self.assertContains(
             response,
-            '<div class="help">Some help text for the content (with Unicode ŠĐĆŽćžšđ)'
-            "</div>",
+            '<div class="help" id="id_content_helptext">Some help text for the content '
+            "(with Unicode ŠĐĆŽćžšđ)</div>",
             html=True,
         )
         self.assertContains(
@@ -6468,7 +6516,9 @@ class ReadonlyTest(AdminFieldExtractionMixin, TestCase):
             reverse("admin:admin_views_fieldoverridepost_change", args=(p.pk,))
         )
         self.assertContains(
-            response, '<div class="help">Overridden help text for the date</div>'
+            response,
+            '<div class="help">Overridden help text for the date</div>',
+            html=True,
         )
         self.assertContains(
             response,