Skip to content

Commit 4296208

Browse files
committed
fix(fxa-settings): Restrict FormVerifyCode input to digits only on desktop
inputMode="numeric" only affects mobile keyboards — desktop browsers still allow typing letters. Add onChange filtering that strips non-digit characters when inputMode is numeric, matching the existing pattern in FormVerifyTotp. Also add ensure-glean-venv step to playwright-functional-tests CI job.
1 parent 807c636 commit 4296208

3 files changed

Lines changed: 50 additions & 6 deletions

File tree

.circleci/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,7 @@ jobs:
876876
sudo tee -a /etc/hosts \<<<'127.0.0.1 localhost'
877877
sudo cat /etc/hosts
878878
- wait-for-infrastructure
879+
- ensure-glean-venv
879880
- run:
880881
name: Start services for playwright tests
881882
command: ./packages/functional-tests/scripts/start-services.sh

packages/fxa-settings/src/components/FormVerifyCode/index.test.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { screen } from '@testing-library/react';
77
import { renderWithLocalizationProvider } from 'fxa-react/lib/test-utils/localizationProvider'; // import { getFtlBundle, testAllL10n } from 'fxa-react/lib/test-utils';
88
// import { FluentBundle } from '@fluent/bundle';
99
import { Subject } from './mocks';
10+
import { InputModeEnum } from '.';
1011
import userEvent from '@testing-library/user-event';
1112

1213
jest.mock('../../lib/metrics', () => ({
@@ -200,5 +201,41 @@ describe('FormVerifyCode component', () => {
200201
});
201202
});
202203

204+
describe('Numeric input filtering', () => {
205+
it('strips non-numeric characters when inputMode is numeric (default)', async () => {
206+
const user = userEvent.setup();
207+
renderWithLocalizationProvider(<Subject />);
208+
const input = screen.getByRole('textbox', {
209+
name: 'Enter your 4-digit code',
210+
});
211+
212+
await user.type(input, 'ab12cd34');
213+
expect(input).toHaveValue('1234');
214+
});
215+
216+
it('allows alphanumeric characters when inputMode is text', async () => {
217+
const user = userEvent.setup();
218+
const alphanumericFormAttributes = {
219+
inputFtlId: 'demo-input-label-id',
220+
inputLabelText: 'Enter backup code',
221+
inputMode: InputModeEnum.text,
222+
pattern: '[a-zA-Z0-9]',
223+
maxLength: 10,
224+
submitButtonFtlId: 'demo-submit-button-id',
225+
submitButtonText: 'Check that code',
226+
};
227+
228+
renderWithLocalizationProvider(
229+
<Subject formAttributes={alphanumericFormAttributes} />
230+
);
231+
const input = screen.getByRole('textbox', {
232+
name: 'Enter backup code',
233+
});
234+
235+
await user.type(input, 'abc123');
236+
expect(input).toHaveValue('abc123');
237+
});
238+
});
239+
203240
// TODO Add tests for (engage, success, etc.) metrics events once submit button enabled
204241
});

packages/fxa-settings/src/components/FormVerifyCode/index.tsx

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ const FormVerifyCode = ({
6969
const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
7070
const [isDisabled, setIsDisabled] = useState<boolean>(true);
7171

72+
const inputMode = formAttributes.inputMode || InputModeEnum.numeric;
7273
const ftlMsgResolver = useFtlMsgResolver();
7374
const localizedLabel = ftlMsgResolver.getMsg(
7475
formAttributes.inputFtlId,
@@ -145,13 +146,18 @@ const FormVerifyCode = ({
145146
<InputText
146147
name="code"
147148
type="text"
148-
inputMode={formAttributes.inputMode || InputModeEnum.numeric}
149+
inputMode={inputMode}
149150
label={localizedLabel}
150-
onChange={
151-
setClearMessages
152-
? () => setClearMessages(true)
153-
: () => setCodeErrorMessage('')
154-
}
151+
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
152+
if (inputMode === InputModeEnum.numeric) {
153+
e.target.value = e.target.value.replace(/[^0-9]/g, '');
154+
}
155+
if (setClearMessages) {
156+
setClearMessages(true);
157+
} else {
158+
setCodeErrorMessage('');
159+
}
160+
}}
155161
onFocusCb={viewName ? onFocus : undefined}
156162
onPaste={submitFormOnPaste ? onPaste : undefined}
157163
errorText={codeErrorMessage}

0 commit comments

Comments
 (0)