Repository: wagtail/wagtail

Issue:
Potential conflict between invalid autocomplete attributes and screen readers
As part of #5136, the date / datetime fields now use invalid `autocomplete` attributes to disable autocompletion in Chrome. This causes Axe to raise the following issue:

> autocomplete attribute must be used correctly (https://dequeuniversity.com/rules/axe/3.2/autocomplete-valid?application=axeAPI)

> Failure to provide autocomplete values in form fields results in inaccessible content. Screen readers do not read identified autocomplete form fields if the appropriate autocomplete attribute values are missing. Users cannot correctly navigate forms when screen readers cannot provide adequate information to the user regarding form field interaction requirements.

> The purpose for each common input field that collects an individual's personal data is programmatically defined based on the list of 53 Input Purposes for User Interface Components. The autocomplete attribute values must be valid and correctly applied for screen readers to function correctly.

According to the spec (https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute), `autocomplete` must either be `off`, `on`, or any of the predefined autofill values.

I'm not entirely sure what the consequences of using invalid values are for screen readers, this needs further investigation.


Discussion:

Resolving patch:
diff --git a/wagtail/admin/widgets.py b/wagtail/admin/widgets.py
--- a/wagtail/admin/widgets.py
+++ b/wagtail/admin/widgets.py
@@ -41,7 +41,7 @@ class AdminDateInput(widgets.DateInput):
     template_name = 'wagtailadmin/widgets/date_input.html'
 
     def __init__(self, attrs=None, format=None):
-        default_attrs = {'autocomplete': 'new-date'}
+        default_attrs = {'autocomplete': 'off'}
         fmt = format
         if attrs:
             default_attrs.update(attrs)
@@ -72,7 +72,7 @@ class AdminTimeInput(widgets.TimeInput):
     template_name = 'wagtailadmin/widgets/time_input.html'
 
     def __init__(self, attrs=None, format='%H:%M'):
-        default_attrs = {'autocomplete': 'new-time'}
+        default_attrs = {'autocomplete': 'off'}
         if attrs:
             default_attrs.update(attrs)
         super().__init__(attrs=default_attrs, format=format)
@@ -88,7 +88,7 @@ class AdminDateTimeInput(widgets.DateTimeInput):
     template_name = 'wagtailadmin/widgets/datetime_input.html'
 
     def __init__(self, attrs=None, format=None):
-        default_attrs = {'autocomplete': 'new-date-time'}
+        default_attrs = {'autocomplete': 'off'}
         fmt = format
         if attrs:
             default_attrs.update(attrs)


Test patch:
diff --git a/wagtail/admin/tests/pages/test_edit_page.py b/wagtail/admin/tests/pages/test_edit_page.py
--- a/wagtail/admin/tests/pages/test_edit_page.py
+++ b/wagtail/admin/tests/pages/test_edit_page.py
@@ -1674,7 +1674,7 @@ def test_get_edit_form(self):
         # date field should use AdminDatePicker
         self.assertContains(
             response,
-            """<input type="text" name="speakers-0-awards-0-date_awarded" value="1997-12-25" autocomplete="new-date" id="id_speakers-0-awards-0-date_awarded">""",
+            """<input type="text" name="speakers-0-awards-0-date_awarded" value="1997-12-25" autocomplete="off" id="id_speakers-0-awards-0-date_awarded">""",
             count=1, html=True
         )
 
diff --git a/wagtail/admin/tests/test_widgets.py b/wagtail/admin/tests/test_widgets.py
--- a/wagtail/admin/tests/test_widgets.py
+++ b/wagtail/admin/tests/test_widgets.py
@@ -99,7 +99,7 @@ def test_render_js_init(self):
 
         html = widget.render('test', None, attrs={'id': 'test-id'})
 
-        self.assertInHTML('<input type="text" name="test" autocomplete="new-date" id="test-id" />', html)
+        self.assertInHTML('<input type="text" name="test" autocomplete="off" id="test-id" />', html)
 
         # we should see the JS initialiser code:
         # initDateChooser("test-id", {"dayOfWeekStart": 0, "format": "Y-m-d"});
@@ -145,7 +145,7 @@ def test_render_js_init(self):
 
         html = widget.render('test', None, attrs={'id': 'test-id'})
 
-        self.assertInHTML('<input type="text" name="test" autocomplete="new-date-time" id="test-id" />', html)
+        self.assertInHTML('<input type="text" name="test" autocomplete="off" id="test-id" />', html)
 
         # we should see the JS initialiser code:
         # initDateTimeChooser("test-id", {"dayOfWeekStart": 0, "format": "Y-m-d H:i"});
diff --git a/wagtail/core/tests/test_blocks.py b/wagtail/core/tests/test_blocks.py
--- a/wagtail/core/tests/test_blocks.py
+++ b/wagtail/core/tests/test_blocks.py
@@ -3383,7 +3383,7 @@ def test_render_form(self):
         self.assertIn('"format": "Y-m-d"', result)
 
         self.assertInHTML(
-            '<input id="dateblock" name="dateblock" placeholder="" type="text" value="2015-08-13" autocomplete="new-date" />',
+            '<input id="dateblock" name="dateblock" placeholder="" type="text" value="2015-08-13" autocomplete="off" />',
             result
         )
 
@@ -3396,7 +3396,7 @@ def test_render_form_with_format(self):
         self.assertIn('"dayOfWeekStart": 0', result)
         self.assertIn('"format": "d.m.Y"', result)
         self.assertInHTML(
-            '<input id="dateblock" name="dateblock" placeholder="" type="text" value="13.08.2015" autocomplete="new-date" />',
+            '<input id="dateblock" name="dateblock" placeholder="" type="text" value="13.08.2015" autocomplete="off" />',
             result
         )
 
@@ -3412,7 +3412,7 @@ def test_render_form_with_format(self):
             result
         )
         self.assertInHTML(
-            '<input id="datetimeblock" name="datetimeblock" placeholder="" type="text" value="13.08.2015 10:00" autocomplete="new-date-time" />',
+            '<input id="datetimeblock" name="datetimeblock" placeholder="" type="text" value="13.08.2015 10:00" autocomplete="off" />',
             result
         )