diff --git a/app/javascript/packs/form-validation.ts b/app/javascript/packs/form-validation.ts index 518285b0bda..b78faedfc04 100644 --- a/app/javascript/packs/form-validation.ts +++ b/app/javascript/packs/form-validation.ts @@ -1,5 +1,3 @@ -import { t } from '@18f/identity-i18n'; - /** * Given a submit event, disables all submit buttons within the target form. * @@ -16,49 +14,12 @@ function disableFormSubmit(event: Event) { ); } -function resetInput(input) { - if (input.hasAttribute('data-form-validation-message')) { - input.setCustomValidity(''); - input.removeAttribute('data-form-validation-message'); - } - input.setAttribute('aria-invalid', 'false'); - input.classList.remove('usa-input--error'); -} - -/** - * Given an `input` or `invalid` event, updates custom validity of the given input. - * - * @param event Input or invalid event. - */ - -function checkInputValidity(event: Event) { - const input = event.target as HTMLInputElement; - resetInput(input); - - if (input.validity.valueMissing) { - input.setCustomValidity(t('simple_form.required.text')); - input.setAttribute('data-form-validation-message', ''); - } -} - -/** - * Binds validation to a given input. - * - * @param input Input element. - */ -function validateInput(input: HTMLInputElement) { - input.addEventListener('input', checkInputValidity); - input.addEventListener('invalid', checkInputValidity); -} - /** * Initializes validation on a form element. * * @param form Form to initialize. */ export function initialize(form: HTMLFormElement) { - const fields: HTMLInputElement[] = Array.from(form.querySelectorAll('[required]')); - fields.forEach(validateInput); form.addEventListener('submit', disableFormSubmit); } diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb index a15034192f6..9980ab90443 100644 --- a/app/views/devise/sessions/new.html.erb +++ b/app/views/devise/sessions/new.html.erb @@ -20,13 +20,18 @@ html: { autocomplete: 'off' }, ) do |f| %> - <%= f.input :email, - label: t('account.index.email'), - required: true, - input_html: { class: 'margin-bottom-6', - autocorrect: 'off', - aria: { invalid: false } } %> - <%= render PasswordToggleComponent.new(form: f, required: true) %> + <%= render ValidatedFieldComponent.new( + form: f, + name: :email, + label: t('account.index.email'), + required: true, + input_html: { autocorrect: 'off' }, + ) %> + <%= render PasswordToggleComponent.new( + form: f, + required: true, + wrapper_html: { class: 'margin-top-6' }, + ) %> <%= f.input :request_id, as: :hidden, input_html: { value: @request_id } %>
<%= submit_tag t('links.next'), class: 'usa-button usa-button--primary usa-button--full-width margin-bottom-2' %> diff --git a/spec/javascripts/packs/form-validation-spec.js b/spec/javascripts/packs/form-validation-spec.js index acb6805ab23..68a99ab87d7 100644 --- a/spec/javascripts/packs/form-validation-spec.js +++ b/spec/javascripts/packs/form-validation-spec.js @@ -1,5 +1,4 @@ import { screen } from '@testing-library/dom'; -import userEvent from '@testing-library/user-event'; import { initialize } from '../../../app/javascript/packs/form-validation'; describe('form-validation', () => { @@ -44,63 +43,4 @@ describe('form-validation', () => { expect(input1.disabled).to.be.false(); expect(input1.classList.contains('usa-button--active')).to.be.false(); }); - - it('checks validity of inputs', async () => { - document.body.innerHTML = ` -
- - -
`; - - initialize(document.querySelector('form')); - - const notRequiredField = screen.getByLabelText('not required field'); - await userEvent.type(notRequiredField, 'a{Backspace}'); - expect(notRequiredField.validationMessage).to.be.empty(); - - const requiredField = screen.getByLabelText('required field'); - await userEvent.type(requiredField, 'a{Backspace}'); - expect(requiredField.validationMessage).to.equal('simple_form.required.text'); - await userEvent.type(requiredField, 'a'); - expect(notRequiredField.validationMessage).to.be.empty(); - }); - - it('resets its own custom validity message on input', async () => { - document.body.innerHTML = ` -
- - -
`; - - const form = document.querySelector('form'); - initialize(form); - - form.checkValidity(); - - const input = screen.getByLabelText('required field'); - await userEvent.type(input, 'a'); - - expect(input.validity.customError).to.be.false(); - }); - - it('does not reset external custom validity message on input', async () => { - document.body.innerHTML = ` -
- - -
`; - - const form = document.querySelector('form'); - initialize(form); - - form.checkValidity(); - - /** @type {HTMLInputElement} */ - const input = screen.getByLabelText('field'); - input.setCustomValidity('custom error'); - - await userEvent.type(input, 'a'); - - expect(input.validity.customError).to.be.true(); - }); });