Enable numeric keypad for text message code

If you’re signing in on a phone, it’s easier to type the two factor code
with a numeric keypad. The most reliable way to get the numeric keypad
to show up on multiple devices is:
- `type='tel'` (not `type='number'` because that’s only meant for
  numbers, not string of digits, ie `01234` is not a number)
- `pattern='[0-9]*'`, without which it doesn’t work on iOS

Based on the guidance here:
- https://github.com/alphagov/govuk-design-system-backlog/issues/74
- https://docs.google.com/document/d/1wozIhOdt6wvlgqVReauUnlsJI-3fqUlNuQFwUI7tqAA/edit
This commit is contained in:
Chris Hill-Scott
2018-05-07 22:26:24 +01:00
parent 4d678aec93
commit 063f9cc081
3 changed files with 15 additions and 3 deletions

View File

@@ -160,8 +160,15 @@ def password(label='Password'):
Blacklist(message='Choose a password thats harder to guess')])
class SMSCode(StringField):
def __call__(self, **kwargs):
return super().__call__(
type='tel', pattern='[0-9]*', **kwargs
)
def sms_code():
return StringField('Text message code', validators=[
return SMSCode('Text message code', validators=[
DataRequired(message='Cant be empty'),
Regexp(regex='^\d+$', message='Numbers only'),
Length(min=5, message='Not enough numbers'),

View File

@@ -15,7 +15,7 @@
<p>Weve sent you a text message with a security code.</p>
<form autocomplete="off" method="post" class="extra-tracking">
<form autocomplete="off" method="post" class="extra-tracking" novalidate>
{{ textbox(
form.sms_code,
width='5em',

View File

@@ -17,7 +17,12 @@ def test_should_render_two_factor_page(
'email': api_user_active.email_address}
response = client.get(url_for('main.two_factor'))
assert response.status_code == 200
assert '''Weve sent you a text message with a security code.''' in response.get_data(as_text=True)
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
assert page.select_one('main p').text.strip() == (
'Weve sent you a text message with a security code.'
)
assert page.select_one('input')['type'] == 'tel'
assert page.select_one('input')['pattern'] == '[0-9]*'
def test_should_login_user_and_should_redirect_to_next_url(