mirror of
https://github.com/django/django.git
synced 2025-05-01 04:34:40 +00:00
Fixed #32820 -- Added aria-invalid="true" to fields with errors.
Co-authored-by: Demetris Stavrou <demestav@gmail.com> Co-authored-by: David Smith <smithdc@gmail.com>
This commit is contained in:
parent
fff14736f1
commit
10725a3187
@ -287,6 +287,8 @@ class BoundField(RenderableFieldMixin):
|
||||
attrs["required"] = True
|
||||
if self.field.disabled:
|
||||
attrs["disabled"] = True
|
||||
if not widget.is_hidden and self.errors:
|
||||
attrs["aria-invalid"] = "true"
|
||||
# If a custom aria-describedby attribute is given (either via the attrs
|
||||
# argument or widget.attrs) and help_text is used, the custom
|
||||
# aria-described by is preserved so user can set the desired order.
|
||||
|
@ -992,10 +992,20 @@ method you're using:
|
||||
... }
|
||||
>>> f = ContactForm(data, auto_id=False)
|
||||
>>> print(f)
|
||||
<div>Subject:<ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="subject" maxlength="100" required></div>
|
||||
<div>Message:<textarea name="message" cols="40" rows="10" required>Hi there</textarea></div>
|
||||
<div>Sender:<ul class="errorlist"><li>Enter a valid email address.</li></ul><input type="email" name="sender" value="invalid email address" required></div>
|
||||
<div>Cc myself:<input type="checkbox" name="cc_myself" checked></div>
|
||||
<div>Subject:
|
||||
<ul class="errorlist"><li>This field is required.</li></ul>
|
||||
<input type="text" name="subject" maxlength="100" required aria-invalid="true">
|
||||
</div>
|
||||
<div>Message:
|
||||
<textarea name="message" cols="40" rows="10" required>Hi there</textarea>
|
||||
</div>
|
||||
<div>Sender:
|
||||
<ul class="errorlist"><li>Enter a valid email address.</li></ul>
|
||||
<input type="email" name="sender" value="invalid email address" required aria-invalid="true">
|
||||
</div>
|
||||
<div>Cc myself:
|
||||
<input type="checkbox" name="cc_myself" checked>
|
||||
</div>
|
||||
|
||||
.. _ref-forms-error-list-format:
|
||||
|
||||
@ -1154,7 +1164,7 @@ Attributes of ``BoundField``
|
||||
>>> data = {"subject": "hi", "message": "", "sender": "", "cc_myself": ""}
|
||||
>>> f = ContactForm(data, auto_id=False)
|
||||
>>> print(f["message"])
|
||||
<input type="text" name="message" required>
|
||||
<input type="text" name="message" required aria-invalid="true">
|
||||
>>> f["message"].errors
|
||||
['This field is required.']
|
||||
>>> print(f["message"].errors)
|
||||
@ -1166,6 +1176,13 @@ Attributes of ``BoundField``
|
||||
>>> str(f["subject"].errors)
|
||||
''
|
||||
|
||||
When rendering a field with errors, ``aria-invalid="true"`` will be set on
|
||||
the field's widget to indicate there is an error to screen reader users.
|
||||
|
||||
.. versionchanged:: 5.0
|
||||
|
||||
The ``aria-invalid="true"`` was added when a field has errors.
|
||||
|
||||
.. attribute:: BoundField.field
|
||||
|
||||
The form :class:`~django.forms.Field` instance from the form class that
|
||||
|
@ -196,9 +196,17 @@ and the HTML output will include any validation errors:
|
||||
>>> default_data = {"name": "Your name", "url": "http://"}
|
||||
>>> f = CommentForm(default_data, auto_id=False)
|
||||
>>> print(f)
|
||||
<div>Name:<input type="text" name="name" value="Your name" required></div>
|
||||
<div>Url:<ul class="errorlist"><li>Enter a valid URL.</li></ul><input type="url" name="url" value="http://" required></div>
|
||||
<div>Comment:<ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="comment" required></div>
|
||||
<div>Name:
|
||||
<input type="text" name="name" value="Your name" required>
|
||||
</div>
|
||||
<div>Url:
|
||||
<ul class="errorlist"><li>Enter a valid URL.</li></ul>
|
||||
<input type="url" name="url" value="http://" required aria-invalid="true">
|
||||
</div>
|
||||
<div>Comment:
|
||||
<ul class="errorlist"><li>This field is required.</li></ul>
|
||||
<input type="text" name="comment" required aria-invalid="true">
|
||||
</div>
|
||||
|
||||
This is why ``initial`` values are only displayed for unbound forms. For bound
|
||||
forms, the HTML output will use the bound data.
|
||||
|
@ -310,6 +310,9 @@ Forms
|
||||
fields with their help text, the form field now includes the
|
||||
``aria-describedby`` HTML attribute.
|
||||
|
||||
* In order to improve accessibility, the invalid form field now includes the
|
||||
``aria-invalid="true"`` HTML attribute.
|
||||
|
||||
Generic Views
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
@ -182,61 +182,70 @@ class FormsTestCase(SimpleTestCase):
|
||||
str(p),
|
||||
'<div><label for="id_first_name">First name:</label>'
|
||||
'<ul class="errorlist"><li>This field is required.</li></ul>'
|
||||
'<input type="text" name="first_name" required id="id_first_name"></div>'
|
||||
'<input type="text" name="first_name" aria-invalid="true" required '
|
||||
'id="id_first_name"></div>'
|
||||
'<div><label for="id_last_name">Last name:</label>'
|
||||
'<ul class="errorlist"><li>This field is required.</li></ul>'
|
||||
'<input type="text" name="last_name" required id="id_last_name"></div><div>'
|
||||
'<input type="text" name="last_name" aria-invalid="true" required '
|
||||
'id="id_last_name"></div><div>'
|
||||
'<label for="id_birthday">Birthday:</label>'
|
||||
'<ul class="errorlist"><li>This field is required.</li></ul>'
|
||||
'<input type="text" name="birthday" required id="id_birthday"></div>',
|
||||
'<input type="text" name="birthday" aria-invalid="true" required '
|
||||
'id="id_birthday"></div>',
|
||||
)
|
||||
self.assertHTMLEqual(
|
||||
p.as_table(),
|
||||
"""<tr><th><label for="id_first_name">First name:</label></th><td>
|
||||
<ul class="errorlist"><li>This field is required.</li></ul>
|
||||
<input type="text" name="first_name" id="id_first_name" required></td></tr>
|
||||
<tr><th><label for="id_last_name">Last name:</label></th>
|
||||
<input type="text" name="first_name" id="id_first_name" aria-invalid="true" required>
|
||||
</td></tr><tr><th><label for="id_last_name">Last name:</label></th>
|
||||
<td><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
<input type="text" name="last_name" id="id_last_name" required></td></tr>
|
||||
<tr><th><label for="id_birthday">Birthday:</label></th>
|
||||
<input type="text" name="last_name" id="id_last_name" aria-invalid="true" required>
|
||||
</td></tr><tr><th><label for="id_birthday">Birthday:</label></th>
|
||||
<td><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
<input type="text" name="birthday" id="id_birthday" required></td></tr>""",
|
||||
<input type="text" name="birthday" id="id_birthday" aria-invalid="true" required>
|
||||
</td></tr>""",
|
||||
)
|
||||
self.assertHTMLEqual(
|
||||
p.as_ul(),
|
||||
"""<li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
<label for="id_first_name">First name:</label>
|
||||
<input type="text" name="first_name" id="id_first_name" required></li>
|
||||
<li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
<input type="text" name="first_name" id="id_first_name" aria-invalid="true" required>
|
||||
</li><li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
<label for="id_last_name">Last name:</label>
|
||||
<input type="text" name="last_name" id="id_last_name" required></li>
|
||||
<li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
<input type="text" name="last_name" id="id_last_name" aria-invalid="true" required>
|
||||
</li><li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
<label for="id_birthday">Birthday:</label>
|
||||
<input type="text" name="birthday" id="id_birthday" required></li>""",
|
||||
<input type="text" name="birthday" id="id_birthday" aria-invalid="true" required>
|
||||
</li>""",
|
||||
)
|
||||
self.assertHTMLEqual(
|
||||
p.as_p(),
|
||||
"""<ul class="errorlist"><li>This field is required.</li></ul>
|
||||
<p><label for="id_first_name">First name:</label>
|
||||
<input type="text" name="first_name" id="id_first_name" required></p>
|
||||
<ul class="errorlist"><li>This field is required.</li></ul>
|
||||
<input type="text" name="first_name" id="id_first_name" aria-invalid="true" required>
|
||||
</p><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
<p><label for="id_last_name">Last name:</label>
|
||||
<input type="text" name="last_name" id="id_last_name" required></p>
|
||||
<ul class="errorlist"><li>This field is required.</li></ul>
|
||||
<input type="text" name="last_name" id="id_last_name" aria-invalid="true" required>
|
||||
</p><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
<p><label for="id_birthday">Birthday:</label>
|
||||
<input type="text" name="birthday" id="id_birthday" required></p>""",
|
||||
<input type="text" name="birthday" id="id_birthday" aria-invalid="true" required>
|
||||
</p>""",
|
||||
)
|
||||
self.assertHTMLEqual(
|
||||
p.as_div(),
|
||||
'<div><label for="id_first_name">First name:</label>'
|
||||
'<ul class="errorlist"><li>This field is required.</li></ul>'
|
||||
'<input type="text" name="first_name" required id="id_first_name"></div>'
|
||||
'<input type="text" name="first_name" aria-invalid="true" required '
|
||||
'id="id_first_name"></div>'
|
||||
'<div><label for="id_last_name">Last name:</label>'
|
||||
'<ul class="errorlist"><li>This field is required.</li></ul>'
|
||||
'<input type="text" name="last_name" required id="id_last_name"></div><div>'
|
||||
'<input type="text" name="last_name" aria-invalid="true" required '
|
||||
'id="id_last_name"></div><div>'
|
||||
'<label for="id_birthday">Birthday:</label>'
|
||||
'<ul class="errorlist"><li>This field is required.</li></ul>'
|
||||
'<input type="text" name="birthday" required id="id_birthday"></div>',
|
||||
'<input type="text" name="birthday" aria-invalid="true" required '
|
||||
'id="id_birthday"></div>',
|
||||
)
|
||||
|
||||
def test_empty_querydict_args(self):
|
||||
@ -582,14 +591,16 @@ class FormsTestCase(SimpleTestCase):
|
||||
{"email": "test@example.com", "get_spam": "False"}, auto_id=False
|
||||
)
|
||||
self.assertHTMLEqual(
|
||||
str(f["get_spam"]), '<input type="checkbox" name="get_spam" required>'
|
||||
str(f["get_spam"]),
|
||||
'<input type="checkbox" name="get_spam" aria-invalid="true" required>',
|
||||
)
|
||||
|
||||
f = SignupForm(
|
||||
{"email": "test@example.com", "get_spam": "false"}, auto_id=False
|
||||
)
|
||||
self.assertHTMLEqual(
|
||||
str(f["get_spam"]), '<input type="checkbox" name="get_spam" required>'
|
||||
str(f["get_spam"]),
|
||||
'<input type="checkbox" name="get_spam" aria-invalid="true" required>',
|
||||
)
|
||||
|
||||
# A value of '0' should be interpreted as a True value (#16820)
|
||||
@ -1406,13 +1417,13 @@ class FormsTestCase(SimpleTestCase):
|
||||
<tr><th><em>Special</em> Field:</th><td>
|
||||
<ul class="errorlist">
|
||||
<li>Something's wrong with 'Nothing to escape'</li></ul>
|
||||
<input type="text" name="special_name" value="Nothing to escape" required>
|
||||
</td></tr>
|
||||
<input type="text" name="special_name" value="Nothing to escape"
|
||||
aria-invalid="true" required></td></tr>
|
||||
<tr><th><em>Special</em> Field:</th><td>
|
||||
<ul class="errorlist">
|
||||
<li>'<b>Nothing to escape</b>' is a safe string</li></ul>
|
||||
<input type="text" name="special_safe_name" value="Nothing to escape"
|
||||
required></td></tr>
|
||||
aria-invalid="true" required></td></tr>
|
||||
""",
|
||||
)
|
||||
f = EscapingForm(
|
||||
@ -1429,13 +1440,14 @@ class FormsTestCase(SimpleTestCase):
|
||||
"Something's wrong with 'Should escape < & > and "
|
||||
"<script>alert('xss')</script>'</li></ul>"
|
||||
'<input type="text" name="special_name" value="Should escape < & '
|
||||
'> and <script>alert('xss')</script>" required>'
|
||||
"</td></tr>"
|
||||
'> and <script>alert('xss')</script>" '
|
||||
'aria-invalid="true" required></td></tr>'
|
||||
"<tr><th><em>Special</em> Field:</th><td>"
|
||||
'<ul class="errorlist">'
|
||||
"<li>'<b><i>Do not escape</i></b>' is a safe string</li></ul>"
|
||||
'<input type="text" name="special_safe_name" '
|
||||
'value="<i>Do not escape</i>" required></td></tr>',
|
||||
'value="<i>Do not escape</i>" aria-invalid="true" required>'
|
||||
"</td></tr>",
|
||||
)
|
||||
|
||||
def test_validating_multiple_fields(self):
|
||||
@ -1537,11 +1549,12 @@ class FormsTestCase(SimpleTestCase):
|
||||
f.as_table(),
|
||||
"""<tr><th>Username:</th><td>
|
||||
<ul class="errorlist"><li>This field is required.</li></ul>
|
||||
<input type="text" name="username" maxlength="10" required></td></tr>
|
||||
<input type="text" name="username" maxlength="10" aria-invalid="true" required>
|
||||
</td></tr>
|
||||
<tr><th>Password1:</th><td><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
<input type="password" name="password1" required></td></tr>
|
||||
<input type="password" name="password1" aria-invalid="true" required></td></tr>
|
||||
<tr><th>Password2:</th><td><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
<input type="password" name="password2" required></td></tr>""",
|
||||
<input type="password" name="password2" aria-invalid="true" required></td></tr>""",
|
||||
)
|
||||
self.assertEqual(f.errors["username"], ["This field is required."])
|
||||
self.assertEqual(f.errors["password1"], ["This field is required."])
|
||||
@ -2412,17 +2425,17 @@ class FormsTestCase(SimpleTestCase):
|
||||
self.assertHTMLEqual(
|
||||
p.as_ul(),
|
||||
"""<li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Username: <input type="text" name="username" maxlength="10" required></li>
|
||||
<li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Password: <input type="password" name="password" required></li>""",
|
||||
Username: <input type="text" name="username" maxlength="10" aria-invalid="true"
|
||||
required></li><li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Password: <input type="password" name="password" aria-invalid="true" required></li>""",
|
||||
)
|
||||
p = UserRegistration({"username": ""}, auto_id=False)
|
||||
self.assertHTMLEqual(
|
||||
p.as_ul(),
|
||||
"""<li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Username: <input type="text" name="username" maxlength="10" required></li>
|
||||
<li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Password: <input type="password" name="password" required></li>""",
|
||||
Username: <input type="text" name="username" maxlength="10" aria-invalid="true"
|
||||
required></li><li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Password: <input type="password" name="password" aria-invalid="true" required></li>""",
|
||||
)
|
||||
p = UserRegistration({"username": "foo"}, auto_id=False)
|
||||
self.assertHTMLEqual(
|
||||
@ -2431,7 +2444,8 @@ Password: <input type="password" name="password" required></li>""",
|
||||
<li>Username: <input type="text" name="username" value="foo" maxlength="10"
|
||||
required></li>
|
||||
<li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Password: <input type="password" name="password" required></li>
|
||||
Password: <input type="password" name="password" aria-invalid="true"
|
||||
required></li>
|
||||
""",
|
||||
)
|
||||
|
||||
@ -2478,9 +2492,9 @@ Password: <input type="password" name="password" required></li>""",
|
||||
self.assertHTMLEqual(
|
||||
p.as_ul(),
|
||||
"""<li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Username: <input type="text" name="username" maxlength="10" required></li>
|
||||
<li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Password: <input type="password" name="password" required></li>""",
|
||||
Username: <input type="text" name="username" maxlength="10" aria-invalid="true"
|
||||
required></li><li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Password: <input type="password" name="password" aria-invalid="true" required></li>""",
|
||||
)
|
||||
p = UserRegistration(
|
||||
{"username": ""}, initial={"username": "django"}, auto_id=False
|
||||
@ -2488,9 +2502,9 @@ Password: <input type="password" name="password" required></li>""",
|
||||
self.assertHTMLEqual(
|
||||
p.as_ul(),
|
||||
"""<li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Username: <input type="text" name="username" maxlength="10" required></li>
|
||||
<li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Password: <input type="password" name="password" required></li>""",
|
||||
Username: <input type="text" name="username" maxlength="10" aria-invalid="true"
|
||||
required></li><li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Password: <input type="password" name="password" aria-invalid="true" required></li>""",
|
||||
)
|
||||
p = UserRegistration(
|
||||
{"username": "foo"}, initial={"username": "django"}, auto_id=False
|
||||
@ -2501,7 +2515,8 @@ Password: <input type="password" name="password" required></li>""",
|
||||
<li>Username: <input type="text" name="username" value="foo" maxlength="10"
|
||||
required></li>
|
||||
<li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Password: <input type="password" name="password" required></li>
|
||||
Password: <input type="password" name="password" aria-invalid="true"
|
||||
required></li>
|
||||
""",
|
||||
)
|
||||
|
||||
@ -2580,11 +2595,11 @@ Password: <input type="password" name="password" required></li>""",
|
||||
self.assertHTMLEqual(
|
||||
p.as_ul(),
|
||||
"""<li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Username: <input type="text" name="username" maxlength="10" required></li>
|
||||
<li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Password: <input type="password" name="password" required></li>
|
||||
<li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Options: <select multiple name="options" required>
|
||||
Username: <input type="text" name="username" maxlength="10" aria-invalid="true"
|
||||
required></li><li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Password: <input type="password" name="password" aria-invalid="true"
|
||||
required></li><li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Options: <select multiple name="options" aria-invalid="true" required>
|
||||
<option value="f">foo</option>
|
||||
<option value="b">bar</option>
|
||||
<option value="w">whiz</option>
|
||||
@ -2596,11 +2611,11 @@ Options: <select multiple name="options" required>
|
||||
self.assertHTMLEqual(
|
||||
p.as_ul(),
|
||||
"""<li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Username: <input type="text" name="username" maxlength="10" required></li>
|
||||
Username: <input type="text" name="username" maxlength="10" aria-invalid="true"
|
||||
required></li><li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Password: <input type="password" name="password" aria-invalid="true" required></li>
|
||||
<li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Password: <input type="password" name="password" required></li>
|
||||
<li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Options: <select multiple name="options" required>
|
||||
Options: <select multiple name="options" aria-invalid="true" required>
|
||||
<option value="f">foo</option>
|
||||
<option value="b">bar</option>
|
||||
<option value="w">whiz</option>
|
||||
@ -2617,8 +2632,8 @@ Options: <select multiple name="options" required>
|
||||
<li>Username: <input type="text" name="username" value="foo" maxlength="10"
|
||||
required></li>
|
||||
<li><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
Password: <input type="password" name="password" required></li>
|
||||
<li>Options: <select multiple name="options" required>
|
||||
Password: <input type="password" name="password" aria-invalid="true"
|
||||
required></li><li>Options: <select multiple name="options" required>
|
||||
<option value="f" selected>foo</option>
|
||||
<option value="b" selected>bar</option>
|
||||
<option value="w">whiz</option>
|
||||
@ -2958,8 +2973,8 @@ Options: <select multiple name="options" required>
|
||||
'maxlength="10" required>'
|
||||
'<span class="helptext">e.g., user@example.com</span></li>'
|
||||
'<li><ul class="errorlist"><li>This field is required.</li></ul>'
|
||||
'Password: <input type="password" name="password" required>'
|
||||
'<span class="helptext">Wählen Sie mit Bedacht.</span></li>',
|
||||
'Password: <input type="password" name="password" aria-invalid="true" '
|
||||
'required><span class="helptext">Wählen Sie mit Bedacht.</span></li>',
|
||||
)
|
||||
|
||||
# help_text is not displayed for hidden fields. It can be used for documentation
|
||||
@ -3405,7 +3420,7 @@ Options: <select multiple name="options" required>
|
||||
f.as_table(),
|
||||
"<tr><th>File1:</th><td>"
|
||||
'<ul class="errorlist"><li>This field is required.</li></ul>'
|
||||
'<input type="file" name="file1" required></td></tr>',
|
||||
'<input type="file" name="file1" aria-invalid="true" required></td></tr>',
|
||||
)
|
||||
|
||||
f = FileForm(
|
||||
@ -3415,7 +3430,7 @@ Options: <select multiple name="options" required>
|
||||
f.as_table(),
|
||||
"<tr><th>File1:</th><td>"
|
||||
'<ul class="errorlist"><li>The submitted file is empty.</li></ul>'
|
||||
'<input type="file" name="file1" required></td></tr>',
|
||||
'<input type="file" name="file1" aria-invalid="true" required></td></tr>',
|
||||
)
|
||||
|
||||
f = FileForm(
|
||||
@ -3426,7 +3441,7 @@ Options: <select multiple name="options" required>
|
||||
"<tr><th>File1:</th><td>"
|
||||
'<ul class="errorlist"><li>No file was submitted. Check the '
|
||||
"encoding type on the form.</li></ul>"
|
||||
'<input type="file" name="file1" required></td></tr>',
|
||||
'<input type="file" name="file1" aria-invalid="true" required></td></tr>',
|
||||
)
|
||||
|
||||
f = FileForm(
|
||||
@ -3591,8 +3606,8 @@ Options: <select multiple name="options" required>
|
||||
<li class="required error"><ul class="errorlist">
|
||||
<li>This field is required.</li></ul>
|
||||
<label class="required" for="id_name">Name:</label>
|
||||
<input type="text" name="name" id="id_name" required></li>
|
||||
<li class="required">
|
||||
<input type="text" name="name" id="id_name" aria-invalid="true" required>
|
||||
</li><li class="required">
|
||||
<label class="required" for="id_is_cool">Is cool:</label>
|
||||
<select name="is_cool" id="id_is_cool">
|
||||
<option value="unknown" selected>Unknown</option>
|
||||
@ -3604,7 +3619,8 @@ Options: <select multiple name="options" required>
|
||||
<li class="required error"><ul class="errorlist">
|
||||
<li>This field is required.</li></ul>
|
||||
<label class="required" for="id_age">Age:</label>
|
||||
<input type="number" name="age" id="id_age" required></li>""",
|
||||
<input type="number" name="age" id="id_age" aria-invalid="true" required>
|
||||
</li>""",
|
||||
)
|
||||
|
||||
self.assertHTMLEqual(
|
||||
@ -3613,8 +3629,8 @@ Options: <select multiple name="options" required>
|
||||
<ul class="errorlist"><li>This field is required.</li></ul>
|
||||
<p class="required error">
|
||||
<label class="required" for="id_name">Name:</label>
|
||||
<input type="text" name="name" id="id_name" required></p>
|
||||
<p class="required">
|
||||
<input type="text" name="name" id="id_name" aria-invalid="true" required>
|
||||
</p><p class="required">
|
||||
<label class="required" for="id_is_cool">Is cool:</label>
|
||||
<select name="is_cool" id="id_is_cool">
|
||||
<option value="unknown" selected>Unknown</option>
|
||||
@ -3625,8 +3641,8 @@ Options: <select multiple name="options" required>
|
||||
<input type="email" name="email" id="id_email" maxlength="320"></p>
|
||||
<ul class="errorlist"><li>This field is required.</li></ul>
|
||||
<p class="required error"><label class="required" for="id_age">Age:</label>
|
||||
<input type="number" name="age" id="id_age" required></p>
|
||||
""",
|
||||
<input type="number" name="age" id="id_age" aria-invalid="true" required>
|
||||
</p>""",
|
||||
)
|
||||
|
||||
self.assertHTMLEqual(
|
||||
@ -3634,7 +3650,7 @@ Options: <select multiple name="options" required>
|
||||
"""<tr class="required error">
|
||||
<th><label class="required" for="id_name">Name:</label></th>
|
||||
<td><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
<input type="text" name="name" id="id_name" required></td></tr>
|
||||
<input type="text" name="name" id="id_name" aria-invalid="true" required></td></tr>
|
||||
<tr class="required"><th><label class="required" for="id_is_cool">Is cool:</label></th>
|
||||
<td><select name="is_cool" id="id_is_cool">
|
||||
<option value="unknown" selected>Unknown</option>
|
||||
@ -3645,13 +3661,14 @@ Options: <select multiple name="options" required>
|
||||
<input type="email" name="email" id="id_email" maxlength="320"></td></tr>
|
||||
<tr class="required error"><th><label class="required" for="id_age">Age:</label></th>
|
||||
<td><ul class="errorlist"><li>This field is required.</li></ul>
|
||||
<input type="number" name="age" id="id_age" required></td></tr>""",
|
||||
<input type="number" name="age" id="id_age" aria-invalid="true" required></td></tr>""",
|
||||
)
|
||||
self.assertHTMLEqual(
|
||||
p.as_div(),
|
||||
'<div class="required error"><label for="id_name" class="required">Name:'
|
||||
'</label><ul class="errorlist"><li>This field is required.</li></ul>'
|
||||
'<input type="text" name="name" required id="id_name" /></div>'
|
||||
'<input type="text" name="name" required id="id_name" '
|
||||
'aria-invalid="true" /></div>'
|
||||
'<div class="required"><label for="id_is_cool" class="required">Is cool:'
|
||||
'</label><select name="is_cool" id="id_is_cool">'
|
||||
'<option value="unknown" selected>Unknown</option>'
|
||||
@ -3660,7 +3677,8 @@ Options: <select multiple name="options" required>
|
||||
'<input type="email" name="email" id="id_email" maxlength="320"/></div>'
|
||||
'<div class="required error"><label for="id_age" class="required">Age:'
|
||||
'</label><ul class="errorlist"><li>This field is required.</li></ul>'
|
||||
'<input type="number" name="age" required id="id_age" /></div>',
|
||||
'<input type="number" name="age" required id="id_age" '
|
||||
'aria-invalid="true" /></div>',
|
||||
)
|
||||
|
||||
def test_label_has_required_css_class(self):
|
||||
@ -4342,7 +4360,8 @@ Options: <select multiple name="options" required>
|
||||
"<li>(Hidden field hidden) Foo & "bar"!</li></ul></li>"
|
||||
'<li><ul class="errorlist"><li>Foo & "bar"!</li></ul>'
|
||||
'<label for="id_visible">Visible:</label> '
|
||||
'<input type="text" name="visible" value="b" id="id_visible" required>'
|
||||
'<input type="text" name="visible" aria-invalid="true" value="b" '
|
||||
'id="id_visible" required>'
|
||||
'<input type="hidden" name="hidden" value="a" id="id_hidden"></li>',
|
||||
)
|
||||
|
||||
@ -4813,10 +4832,12 @@ class TemplateTests(SimpleTestCase):
|
||||
"</label></p>"
|
||||
'<ul class="errorlist"><li>This field is required.</li></ul><p>'
|
||||
"<label>Password: "
|
||||
'<input type="password" name="password1" required></label></p>'
|
||||
'<input type="password" name="password1" aria-invalid="true" required>'
|
||||
"</label></p>"
|
||||
'<ul class="errorlist"><li>This field is required.</li></ul>'
|
||||
"<p><label>Password (again): "
|
||||
'<input type="password" name="password2" required></label></p>'
|
||||
'<input type="password" name="password2" aria-invalid="true" required>'
|
||||
"</label></p>"
|
||||
'<input type="submit" required>'
|
||||
"</form>",
|
||||
)
|
||||
@ -4851,7 +4872,10 @@ class TemplateTests(SimpleTestCase):
|
||||
# Form gives each field an "id" attribute.
|
||||
t = Template(
|
||||
"<form>"
|
||||
"<p>{{ form.username.label_tag }} {{ form.username }}</p>"
|
||||
"<p>{{ form.username.label_tag }} {{ form.username }}"
|
||||
'<span {% if form.username.id_for_label %}id="'
|
||||
'{{ form.username.id_for_label }}_helptext"{% endif %}>'
|
||||
"{{ form.username.help_text}}</span></p>"
|
||||
"<p>{{ form.password1.label_tag }} {{ form.password1 }}</p>"
|
||||
"<p>{{ form.password2.label_tag }} {{ form.password2 }}</p>"
|
||||
'<input type="submit" required>'
|
||||
@ -4861,7 +4885,8 @@ class TemplateTests(SimpleTestCase):
|
||||
t.render(Context({"form": f})),
|
||||
"<form>"
|
||||
"<p>Username: "
|
||||
'<input type="text" name="username" maxlength="10" required></p>'
|
||||
'<input type="text" name="username" maxlength="10" required>'
|
||||
"<span>Good luck picking a username that doesn't already exist.</span></p>"
|
||||
'<p>Password1: <input type="password" name="password1" required></p>'
|
||||
'<p>Password2: <input type="password" name="password2" required></p>'
|
||||
'<input type="submit" required>'
|
||||
@ -4873,7 +4898,9 @@ class TemplateTests(SimpleTestCase):
|
||||
"<form>"
|
||||
'<p><label for="id_username">Username:</label>'
|
||||
'<input id="id_username" type="text" name="username" maxlength="10" '
|
||||
'aria-describedby="id_username_helptext" required></p>'
|
||||
'aria-describedby="id_username_helptext" required>'
|
||||
'<span id="id_username_helptext">'
|
||||
"Good luck picking a username that doesn't already exist.</span></p>"
|
||||
'<p><label for="id_password1">Password1:</label>'
|
||||
'<input type="password" name="password1" id="id_password1" required></p>'
|
||||
'<p><label for="id_password2">Password2:</label>'
|
||||
@ -5066,7 +5093,7 @@ class TemplateTests(SimpleTestCase):
|
||||
"<li>Please make sure your passwords match.</li></ul>"
|
||||
'<div>Username:<ul class="errorlist">'
|
||||
"<li>Ensure this value has at most 10 characters (it has 23).</li></ul>"
|
||||
'<input type="text" name="username" '
|
||||
'<input type="text" name="username" aria-invalid="true" '
|
||||
'value="this-is-a-long-username" maxlength="10" required></div>'
|
||||
"<div>Password1:"
|
||||
'<input type="password" name="password1" required></div>'
|
||||
@ -5174,10 +5201,11 @@ class OverrideTests(SimpleTestCase):
|
||||
'<div class="errorlist">'
|
||||
'<div class="error">Enter a valid email address.</div></div>'
|
||||
"<p>Email: "
|
||||
'<input type="email" name="email" value="invalid" maxlength="320" required>'
|
||||
'</p><div class="errorlist">'
|
||||
'<input type="email" name="email" value="invalid" maxlength="320" '
|
||||
'aria-invalid="true" required></p><div class="errorlist">'
|
||||
'<div class="error">This field is required.</div></div>'
|
||||
'<p>Comment: <input type="text" name="comment" required></p>',
|
||||
'<p>Comment: <input type="text" name="comment" aria-invalid="true" '
|
||||
"required></p>",
|
||||
)
|
||||
|
||||
def test_cyclic_context_boundfield_render(self):
|
||||
|
@ -103,13 +103,16 @@ class FormsI18nTests(SimpleTestCase):
|
||||
"<p><label>\xc5\xf8\xdf:</label>"
|
||||
' <div id="id_somechoice">\n<div><label for="id_somechoice_0">'
|
||||
'<input type="radio" id="id_somechoice_0" value="\xc5" '
|
||||
'name="somechoice" required> En tied\xe4</label></div>\n'
|
||||
'name="somechoice" aria-invalid="true" required>'
|
||||
"En tied\xe4</label></div>\n"
|
||||
'<div><label for="id_somechoice_1">'
|
||||
'<input type="radio" id="id_somechoice_1" value="\xf8" '
|
||||
'name="somechoice" required> Mies</label></div>\n<div>'
|
||||
'name="somechoice" aria-invalid="true" required>'
|
||||
"Mies</label></div>\n<div>"
|
||||
'<label for="id_somechoice_2">'
|
||||
'<input type="radio" id="id_somechoice_2" value="\xdf" '
|
||||
'name="somechoice" required> Nainen</label></div>\n</div></p>',
|
||||
'name="somechoice" aria-invalid="true" required>'
|
||||
"Nainen</label></div>\n</div></p>",
|
||||
)
|
||||
|
||||
def test_select_translated_text(self):
|
||||
|
@ -30,7 +30,7 @@ class GeoAdminTest(SimpleTestCase):
|
||||
' rows="10" name="point" hidden></textarea>',
|
||||
output,
|
||||
)
|
||||
self.assertEqual(len(cm.records), 1)
|
||||
self.assertEqual(len(cm.records), 2)
|
||||
self.assertEqual(
|
||||
cm.records[0].getMessage(),
|
||||
"Error creating geometry from value 'INVALID()' (String input "
|
||||
|
Loading…
x
Reference in New Issue
Block a user