From 03bc4418d1b8516874833e78f6b2055d36322432 Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Thu, 2 Jun 2022 15:00:47 -0400 Subject: [PATCH 1/2] Fix paste for personal key confirmation (IdV app) **Why**: Because the primary user interaction we expect here is for the user to paste the personal key after clicking the "Copy" button on the personal key display page. changelog: Upcoming Features, Identity Verification, Add personal key step screen --- .../personal-key-input.spec.tsx | 11 +++++++++++ .../personal-key-confirm/personal-key-input.tsx | 11 +++++++++++ spec/support/shared_examples_for_personal_keys.rb | 13 +++++++++++++ 3 files changed, 35 insertions(+) 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..50a8174ac42 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,13 @@ copied_text = page.evaluate_async_script('navigator.clipboard.readText().then(arguments[0])') expect(copied_text).to eq(scrape_personal_key) + + click_continue + page.find(':focus').send_keys [mac? ? :meta : :control, '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 +70,8 @@ expect(current_path).not_to eq path_before_submit end end + + def mac? + RbConfig::CONFIG['host_os'].match? 'darwin' + end end From 56d479636feb9440a38dbc572f39cb7287c04db2 Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Thu, 2 Jun 2022 20:07:42 -0400 Subject: [PATCH 2/2] Create separate variable for modifier Improve clarity See: https://github.com/18F/identity-idp/pull/6443#discussion_r888356715 --- spec/support/shared_examples_for_personal_keys.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/support/shared_examples_for_personal_keys.rb b/spec/support/shared_examples_for_personal_keys.rb index 50a8174ac42..fbaa47105a5 100644 --- a/spec/support/shared_examples_for_personal_keys.rb +++ b/spec/support/shared_examples_for_personal_keys.rb @@ -40,7 +40,8 @@ expect(copied_text).to eq(scrape_personal_key) click_continue - page.find(':focus').send_keys [mac? ? :meta : :control, 'v'] + 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') }