diff --git a/app/javascript/packs/state-guidance.ts b/app/javascript/packs/state-guidance.ts index b3a3d443467..a317fd668da 100644 --- a/app/javascript/packs/state-guidance.ts +++ b/app/javascript/packs/state-guidance.ts @@ -1,17 +1,13 @@ -import { t } from '@18f/identity-i18n'; - -function jurisdictionExtrasHintText(jurisdiction) { - switch (jurisdiction) { - case 'TX': - return t('in_person_proofing.form.state_id.state_id_number_texas_hint'); - default: - return t('in_person_proofing.form.state_id.state_id_number_hint'); - } -} - export function showOrHideJurisdictionExtras(jurisdictionCode) { - document.querySelectorAll('.jurisdiction-extras').forEach((element) => { - element.textContent = jurisdictionExtrasHintText(jurisdictionCode); + const hasJurisdictionSpecificHint = + jurisdictionCode && + document.querySelectorAll(`.jurisdiction-extras [data-state=${jurisdictionCode}]`).length > 0; + + document.querySelectorAll(`.jurisdiction-extras [data-state]`).forEach((element) => { + const shouldShow = + element.dataset.state === jurisdictionCode || + (!hasJurisdictionSpecificHint && element.dataset.state === 'default'); + element.classList.toggle('display-none', !shouldShow); }); } diff --git a/app/views/idv/in_person/state_id.html.erb b/app/views/idv/in_person/state_id.html.erb index d704468ed63..a22d2a03829 100644 --- a/app/views/idv/in_person/state_id.html.erb +++ b/app/views/idv/in_person/state_id.html.erb @@ -111,10 +111,37 @@ ) %>
+ <% state_id_number_hint_default = capture do %> + <%= t('in_person_proofing.form.state_id.state_id_number_hint') %> + <% [ + [t('in_person_proofing.form.state_id.state_id_number_hint_spaces'), ' '], + [t('in_person_proofing.form.state_id.state_id_number_hint_forward_slashes'), '/'], + [t('in_person_proofing.form.state_id.state_id_number_hint_asterisks'), '*'], + [t('in_person_proofing.form.state_id.state_id_number_hint_dashes'), '-', true], + ].each do |text, symbol, last| %> + <%= text %><%= ',' if !last %> + + <% end %> + <% end %> + + <% state_id_number_hint = capture do %> + <% [ + [:default, state_id_number_hint_default], + ['TX', t('in_person_proofing.form.state_id.state_id_number_texas_hint')], + ].each do |state, hint| %> + <%= content_tag( + :span, + hint, + class: state == :default ? nil : 'display-none', + data: { state: }, + ) %> + <% end %> + <% end %> + <%= render ValidatedFieldComponent.new( name: :state_id_number, form: f, - hint: t('in_person_proofing.form.state_id.state_id_number_hint'), + hint: state_id_number_hint, hint_html: { class: ['tablet:grid-col-10', 'jurisdiction-extras'] }, input_html: { value: pii[:state_id_number] }, label: t('in_person_proofing.form.state_id.state_id_number'), diff --git a/config/locales/in_person_proofing/en.yml b/config/locales/in_person_proofing/en.yml index 7c5107054d2..a0044835ed7 100644 --- a/config/locales/in_person_proofing/en.yml +++ b/config/locales/in_person_proofing/en.yml @@ -131,7 +131,11 @@ en: state_id_jurisdiction_hint: This is the state that issued your ID state_id_jurisdiction_prompt: '- Select -' state_id_number: ID number - state_id_number_hint: 'May include letters, numbers, and the following symbols: / *-' + state_id_number_hint: 'May include letters, numbers, and the following symbols:' + state_id_number_hint_asterisks: asterisks + state_id_number_hint_dashes: dashes + state_id_number_hint_forward_slashes: forward slashes + state_id_number_hint_spaces: spaces state_id_number_texas_hint: This is the 8-digit number on your ID. Enter only numbers in this field. zipcode: ZIP Code diff --git a/config/locales/in_person_proofing/es.yml b/config/locales/in_person_proofing/es.yml index 2b7ceb846cb..fbd23201e29 100644 --- a/config/locales/in_person_proofing/es.yml +++ b/config/locales/in_person_proofing/es.yml @@ -143,7 +143,11 @@ es: state_id_jurisdiction_hint: Este es el estado que emitió su identificación state_id_jurisdiction_prompt: '- Seleccione -' state_id_number: Número de identidad - state_id_number_hint: 'Puede incluir letras, números y los siguientes símbolos: / *-' + state_id_number_hint: 'Puede incluir letras, números y los siguientes símbolos:' + state_id_number_hint_asterisks: 'asteriscos' + state_id_number_hint_dashes: guiones + state_id_number_hint_forward_slashes: 'barras diagonal' + state_id_number_hint_spaces: 'espacios' state_id_number_texas_hint: Este es el número de 8 dígitos de su ID. Introduzca sólo números en este campo. zipcode: Código postal diff --git a/config/locales/in_person_proofing/fr.yml b/config/locales/in_person_proofing/fr.yml index 11d0aa04b77..d73e40a2ef3 100644 --- a/config/locales/in_person_proofing/fr.yml +++ b/config/locales/in_person_proofing/fr.yml @@ -143,8 +143,11 @@ fr: state_id_jurisdiction_hint: Il s’agit de l’État qui a émis votre pièce d’identité state_id_jurisdiction_prompt: '- Sélectionnez -' state_id_number: Numéro d’identification - state_id_number_hint: 'Il peut s’agir de lettres, de chiffres et des symboles - suivants: / *-' + state_id_number_hint: 'Il peut s’agir de lettres, de chiffres et des symboles suivants:' + state_id_number_hint_asterisks: 'des astérisques' + state_id_number_hint_dashes: 'des tirets' + state_id_number_hint_forward_slashes: 'des barres obliques' + state_id_number_hint_spaces: 'des espaces' state_id_number_texas_hint: Il s’agit du numéro à huit chiffres figurant sur votre carte d’identité. Entrez uniquement des chiffres dans ce champ. zipcode: Code postal diff --git a/spec/javascript/packs/state-guidance-spec.js b/spec/javascript/packs/state-guidance-spec.js index df2405a2a48..6314f2a7f3d 100644 --- a/spec/javascript/packs/state-guidance-spec.js +++ b/spec/javascript/packs/state-guidance-spec.js @@ -41,7 +41,11 @@ describe('state-guidance', () => {
-
+
+ Default help text + + +
`; }); @@ -49,25 +53,49 @@ describe('state-guidance', () => { it('includes Texas specific hint text when Texas is selected', () => { const jurisdictionCode = 'TX'; showOrHideJurisdictionExtras(jurisdictionCode); - const elementInnerHtml = document.querySelector('.jurisdiction-extras')?.textContent; - expect(elementInnerHtml).to.eq('in_person_proofing.form.state_id.state_id_number_texas_hint'); + const allHintTexts = document.querySelectorAll('.jurisdiction-extras [data-state]'); + const texasText = document.querySelectorAll('.jurisdiction-extras [data-state=TX]'); + const nonTexasText = document.querySelectorAll( + '.jurisdiction-extras [data-state].display-none', + ); + + expect(texasText.length).to.eq(1); + expect(texasText[0].classList.contains('display-none')).to.eq(false); + + expect(nonTexasText.length + texasText.length).to.eq(allHintTexts.length); }); it('includes default hint text when no state is selected', () => { - const jurisdictionCode = ' '; + const jurisdictionCode = ''; showOrHideJurisdictionExtras(jurisdictionCode); - const elementInnerHtml = document.querySelector('.jurisdiction-extras')?.textContent; - expect(elementInnerHtml).to.eq('in_person_proofing.form.state_id.state_id_number_hint'); + const allHintTexts = document.querySelectorAll('.jurisdiction-extras [data-state]'); + const defaultText = document.querySelectorAll('.jurisdiction-extras [data-state=default]'); + const nonDefaultText = document.querySelectorAll( + '.jurisdiction-extras [data-state].display-none', + ); + + expect(defaultText.length).to.eq(1); + expect(defaultText[0].classList.contains('display-none')).to.eq(false); + + expect(nonDefaultText.length + defaultText.length).to.eq(allHintTexts.length); }); it('includes default hint text when a state without a state specific hint is selected', () => { const jurisdictionCode = 'NY'; showOrHideJurisdictionExtras(jurisdictionCode); - const elementInnerHtml = document.querySelector('.jurisdiction-extras')?.textContent; - expect(elementInnerHtml).to.eq('in_person_proofing.form.state_id.state_id_number_hint'); + const allHintTexts = document.querySelectorAll('.jurisdiction-extras [data-state]'); + const defaultText = document.querySelectorAll('.jurisdiction-extras [data-state=default]'); + const nonDefaultText = document.querySelectorAll( + '.jurisdiction-extras [data-state].display-none', + ); + + expect(defaultText.length).to.eq(1); + expect(defaultText[0].classList.contains('display-none')).to.eq(false); + + expect(nonDefaultText.length + defaultText.length).to.eq(allHintTexts.length); }); }); }); diff --git a/spec/views/idv/in_person/state_id.html.erb_spec.rb b/spec/views/idv/in_person/state_id.html.erb_spec.rb new file mode 100644 index 00000000000..f9be82b9844 --- /dev/null +++ b/spec/views/idv/in_person/state_id.html.erb_spec.rb @@ -0,0 +1,37 @@ +require 'rails_helper' + +RSpec.describe 'idv/in_person/state_id.html.erb' do + let(:pii) { {} } + let(:form) { Idv::StateIdForm.new(pii) } + let(:parsed_dob) { Date.new(1970, 1, 1) } + + before do + allow(view).to receive(:url_for).and_return('https://example.com/') + end + + subject(:render_template) do + render template: 'idv/in_person/state_id', + locals: { updating_state_id: true, form: form, pii: pii, parsed_dob: parsed_dob } + end + + it 'renders state ID hint text with correct screenreader tags', aggregate_failures: true do + render_template + + doc = Nokogiri::HTML(rendered) + + jurisdiction_extras = doc.at_css('.jurisdiction-extras') + + all_hints = jurisdiction_extras.css('[data-state]') + shown = jurisdiction_extras.css('[data-state]:not(.display-none)') + hidden = jurisdiction_extras.css('[data-state].display-none') + + expect(shown.size).to eq(1), 'only shows one hint' + expect(shown.size + hidden.size).to eq(all_hints.size) + + default_hint = jurisdiction_extras.at_css('[data-state=default]') + default_hint_screenreader_tags = default_hint.css('.usa-sr-only') + *first, last = default_hint_screenreader_tags.map(&:text) + expect(first).to all end_with(',') + expect(last).to_not end_with(',') + end +end