diff --git a/app/javascript/packages/verify-flow/steps/personal-key-confirm/personal-key-input.spec.tsx b/app/javascript/packages/verify-flow/steps/personal-key-confirm/personal-key-input.spec.tsx index 828de0d5291..67616a4a328 100644 --- a/app/javascript/packages/verify-flow/steps/personal-key-confirm/personal-key-input.spec.tsx +++ b/app/javascript/packages/verify-flow/steps/personal-key-confirm/personal-key-input.spec.tsx @@ -49,6 +49,17 @@ describe('PersonalKeyInput', () => { expect(input.value).to.equal('1234-1234-1234-1234'); }); + it('allows the user to paste the personal key from their clipboard', async () => { + const { getByRole } = render(); + + const input = getByRole('textbox') as HTMLInputElement; + + input.focus(); + await userEvent.paste('1234-1234-1234-1234'); + + expect(input.value).to.equal('1234-1234-1234-1234'); + }); + it('validates the input value against the expected value (case-insensitive, crockford)', async () => { const { getByRole } = render(); diff --git a/app/javascript/packages/verify-flow/steps/personal-key-confirm/personal-key-input.tsx b/app/javascript/packages/verify-flow/steps/personal-key-confirm/personal-key-input.tsx index 03d2a835c3f..21b7bde05a0 100644 --- a/app/javascript/packages/verify-flow/steps/personal-key-confirm/personal-key-input.tsx +++ b/app/javascript/packages/verify-flow/steps/personal-key-confirm/personal-key-input.tsx @@ -1,10 +1,18 @@ import { forwardRef, useCallback } from 'react'; import type { ForwardedRef } from 'react'; import Cleave from 'cleave.js/react'; +import type { ReactInstanceWithCleave } from 'cleave.js/react/props'; import { t } from '@18f/identity-i18n'; import { ValidatedField } from '@18f/identity-validated-field'; import type { ValidatedFieldValidator } from '@18f/identity-validated-field'; +/** + * Internal Cleave.js React instance API methods. + */ +interface CleaveInstanceInternalAPI { + updateValueState: () => void; +} + interface PersonalKeyInputProps { /** * The correct personal key to validate against. @@ -42,6 +50,9 @@ function PersonalKeyInput( return ( { + (owner as ReactInstanceWithCleave & CleaveInstanceInternalAPI).updateValueState(); + }} options={{ blocks: [4, 4, 4, 4], delimiter: '-', diff --git a/spec/support/shared_examples_for_personal_keys.rb b/spec/support/shared_examples_for_personal_keys.rb index 67c32ad0010..fbaa47105a5 100644 --- a/spec/support/shared_examples_for_personal_keys.rb +++ b/spec/support/shared_examples_for_personal_keys.rb @@ -1,3 +1,5 @@ +require 'rbconfig' + shared_examples_for 'personal key page' do include PersonalKeyHelper include JavascriptDriverHelper @@ -36,6 +38,14 @@ copied_text = page.evaluate_async_script('navigator.clipboard.readText().then(arguments[0])') expect(copied_text).to eq(scrape_personal_key) + + click_continue + mod = mac? ? :meta : :control + page.find(':focus').send_keys [mod, 'v'] + + path_before_submit = current_path + within('[role=dialog]') { click_on t('forms.buttons.continue') } + expect(current_path).not_to eq path_before_submit end it 'validates as case-insensitive, crockford-normalized, length-limited, dash-flexible' do @@ -61,4 +71,8 @@ expect(current_path).not_to eq path_before_submit end end + + def mac? + RbConfig::CONFIG['host_os'].match? 'darwin' + end end