diff --git a/app/controllers/frontend_log_controller.rb b/app/controllers/frontend_log_controller.rb index 3cae4dc8967..9f3f53c5300 100644 --- a/app/controllers/frontend_log_controller.rb +++ b/app/controllers/frontend_log_controller.rb @@ -17,6 +17,7 @@ class FrontendLogController < ApplicationController 'IdV: Native camera forced after failed attempts' => :idv_native_camera_forced, 'Multi-Factor Authentication: download backup code' => :multi_factor_auth_backup_code_download, 'Show Password button clicked' => :show_password_button_clicked, + 'IdV: personal key acknowledgment toggled' => :idv_personal_key_acknowledgment_toggled, }.transform_values { |method| AnalyticsEvents.instance_method(method) }.freeze # rubocop:enable Layout/LineLength diff --git a/app/javascript/packs/personal-key-page-controller.js b/app/javascript/packs/personal-key-page-controller.js index 36d052bda10..e7739b55c8b 100644 --- a/app/javascript/packs/personal-key-page-controller.js +++ b/app/javascript/packs/personal-key-page-controller.js @@ -1,16 +1,8 @@ -import { encodeInput } from '@18f/identity-personal-key-input'; import { trackEvent } from '@18f/identity-analytics'; -import { t } from '@18f/identity-i18n'; - -const modalSelector = '#personal-key-confirm'; -const modal = new window.LoginGov.Modal({ el: modalSelector }); const personalKeyWords = [].slice.call(document.querySelectorAll('[data-personal-key]')); -const formEl = document.getElementById('confirm-key'); -const input = formEl.querySelector('input[type="text"]'); -const modalTrigger = document.querySelector('[data-toggle="modal"]'); -const modalDismiss = document.querySelector('[data-dismiss="personal-key-confirm"]'); const downloadLink = document.querySelector('a[download]'); +const acknowledgmentCheckbox = document.getElementById('acknowledgment'); function scrapePersonalKey() { const keywords = []; @@ -22,43 +14,6 @@ function scrapePersonalKey() { return keywords.join('-').toUpperCase(); } -const personalKey = scrapePersonalKey(); - -function resetForm() { - formEl.reset(); - input.setCustomValidity(''); -} - -function validateInput() { - let isValid = false; - try { - const value = encodeInput(input.value); - isValid = value === personalKey; - } catch {} - - input.setCustomValidity(isValid ? '' : t('users.personal_key.confirmation_error')); -} - -function show(event) { - event.preventDefault(); - - modal.on('show', function () { - input.focus(); - }); - - trackEvent('IdV: show personal key modal'); - modal.show(); -} - -function hide() { - modal.on('hide', function () { - resetForm(); - }); - - trackEvent('IdV: hide personal key modal'); - modal.hide(); -} - function downloadForIE(event) { event.preventDefault(); @@ -69,16 +24,16 @@ function downloadForIE(event) { window.navigator.msSaveBlob(blob, filename); } +function trackAcknowledgment(clickEvent) { + trackEvent('IdV: personal key acknowledgment toggled', { checked: clickEvent.target.checked }); +} + function trackDownload() { trackEvent('IdV: download personal key'); } -if (modalTrigger) { - modalTrigger.addEventListener('click', show); -} -modalDismiss.addEventListener('click', hide); -input.addEventListener('input', validateInput); downloadLink.addEventListener('click', trackDownload); +acknowledgmentCheckbox.addEventListener('click', trackAcknowledgment); if (window.navigator.msSaveBlob) { downloadLink.addEventListener('click', downloadForIE); diff --git a/app/services/analytics_events.rb b/app/services/analytics_events.rb index af08a97bb6e..c98b96037ae 100644 --- a/app/services/analytics_events.rb +++ b/app/services/analytics_events.rb @@ -2791,5 +2791,13 @@ def contact_redirect(redirect_url:, step: nil, location: nil, flow: nil, **extra def show_password_button_clicked(path:, **extra) track_event('Show Password Button Clicked', path: path, **extra) end + + # Tracks if a user clicks the 'acknowledge' checkbox during personal + # key creation + # @param [boolean] checked whether the user checked or un-checked + # the box with this click + def idv_personal_key_acknowledgment_toggled(checked:, **extra) + track_event('IdV: personal key acknowledgment toggled', checked: checked, **extra) + end end # rubocop:enable Metrics/ModuleLength diff --git a/app/views/partials/personal_key/_key.html.erb b/app/views/partials/personal_key/_key.html.erb index 3a096babaed..774205e6428 100644 --- a/app/views/partials/personal_key/_key.html.erb +++ b/app/views/partials/personal_key/_key.html.erb @@ -1,7 +1,4 @@
-

- <%= t('users.personal_key.header') %> -

<% code.split('-').each do |word| %> @@ -9,10 +6,37 @@ <% end %>
-

+

<%= t( 'users.personal_key.generated_on_html', date: content_tag(:strong, I18n.l(Time.zone.today, format: '%B %d, %Y')), ) %>

+ + <%= render ClipboardButtonComponent.new( + clipboard_text: code, + unstyled: true, + ) %> + + <%= render ButtonComponent.new( + action: ->(**tag_options, &block) do + link_to( + "data:text/plain;charset=utf-8,#{CGI.escape(code)}", + download: 'personal_key.txt', + **tag_options, + &block + ) + end, + icon: :file_download, + unstyled: true, + class: 'margin-x-2 display-inline-block', + ).with_content(t('forms.personal_key.download')) %> + + <%= render PrintButtonComponent.new( + icon: :print, + unstyled: true, + type: :button, + class: 'margin-right-2 margin-bottom-2 tablet:margin-bottom-0', + ) %> +
diff --git a/app/views/shared/_personal_key.html.erb b/app/views/shared/_personal_key.html.erb index 24e0c08288b..a1c6561859e 100644 --- a/app/views/shared/_personal_key.html.erb +++ b/app/views/shared/_personal_key.html.erb @@ -1,51 +1,43 @@ -<%= render PageHeadingComponent.new.with_content(t('headings.personal_key')) %> -

- <%= t('instructions.personal_key.info') %> -

+<%= render PageHeadingComponent.new.with_content(t('forms.personal_key_partial.header')) %>
<%= render 'partials/personal_key/key', code: code %>
-<%= render ButtonComponent.new( - action: ->(**tag_options, &block) do - link_to( - "data:text/plain;charset=utf-8,#{CGI.escape(code)}", - download: 'personal_key.txt', - **tag_options, - &block - ) - end, - icon: :file_download, - outline: true, - class: 'margin-right-2 margin-bottom-2 tablet:margin-bottom-0', - ).with_content(t('forms.backup_code.download')) %> -<%= render PrintButtonComponent.new( - icon: :print, - outline: true, - type: :button, - class: 'margin-right-2 margin-bottom-2 tablet:margin-bottom-0', - ) %> -<%= render ClipboardButtonComponent.new( - clipboard_text: code, - outline: true, - class: 'margin-bottom-2 tablet:margin-bottom-0', - ) %> -
- <%= image_tag( - asset_url('alert/icon-lock-alert-important.svg'), - alt: '', - size: '80', - class: 'float-left margin-right-2', - ) %> + +<%= render AccordionComponent.new do |c| %> + <% c.header { t('forms.personal_key_partial.explanation.header') } %> + <% t('forms.personal_key_partial.explanation.text').each do |paragraph| %> +

<%= paragraph %>

+ <% end %> +<% end %> + +<%= simple_form_for('', url: update_path) do |f| %> +

+ + <%= t('forms.personal_key_partial.acknowledgement.header') %> + +

+

- <%= t('instructions.personal_key.email_title') %> + <%= t('forms.personal_key_partial.acknowledgement.text') %>

-

<%= t('instructions.personal_key.email_body') %>

-
-<%= button_to( - t('forms.buttons.continue'), - update_path, - class: 'display-block usa-button usa-button--big usa-button--wide personal-key-continue margin-top-5', - 'data-toggle': FeatureManagement.idv_personal_key_confirmation_enabled? ? 'modal' : 'skip', - ) %> -<%= render 'shared/personal_key_confirmation_modal', code: code, update_path: update_path %> + + + + <%= render ValidatedFieldComponent.new( + form: f, + name: :acknowledgment, + as: :boolean, + label: t('forms.personal_key.required_checkbox'), + label_html: { class: 'margin-bottom-105' }, + required: true, + ) %> + + + <%= f.submit(t('forms.buttons.continue'), full_width: true, class: 'margin-top-3') %> +<% end %> + <%== javascript_packs_tag_once 'personal-key-page-controller' %> diff --git a/app/views/shared/_personal_key_confirmation_modal.html.erb b/app/views/shared/_personal_key_confirmation_modal.html.erb deleted file mode 100644 index 133f17cca26..00000000000 --- a/app/views/shared/_personal_key_confirmation_modal.html.erb +++ /dev/null @@ -1,34 +0,0 @@ - diff --git a/config/application.yml.default b/config/application.yml.default index abb8196fde2..d3f67d63095 100644 --- a/config/application.yml.default +++ b/config/application.yml.default @@ -107,7 +107,6 @@ idv_max_attempts: 5 idv_min_age_years: 13 idv_native_camera_a_b_testing_enabled: false idv_native_camera_a_b_testing_percent: 10 -idv_personal_key_confirmation_enabled: true idv_send_link_attempt_window_in_minutes: 10 idv_send_link_max_attempts: 5 idv_sp_required: false diff --git a/config/locales/components/es.yml b/config/locales/components/es.yml index 24dcb36389f..014b65732fb 100644 --- a/config/locales/components/es.yml +++ b/config/locales/components/es.yml @@ -35,7 +35,7 @@ es: phone_input: country_code_label: Código del país print_button: - label: Imprima esta página + label: Imprima troubleshooting_options: default_heading: '¿Tiene alguna dificultad? Esto es lo que puede hacer:' new_feature: Nueva función diff --git a/config/locales/components/fr.yml b/config/locales/components/fr.yml index e1be7225778..f0fc3a76998 100644 --- a/config/locales/components/fr.yml +++ b/config/locales/components/fr.yml @@ -35,7 +35,7 @@ fr: phone_input: country_code_label: Code pays print_button: - label: Imprimer cette page + label: Imprimer troubleshooting_options: default_heading: 'Des difficultés? Voici ce que vous pouvez faire:' new_feature: Nouvelle fonction diff --git a/config/locales/forms/en.yml b/config/locales/forms/en.yml index 4478278956a..58f19630556 100644 --- a/config/locales/forms/en.yml +++ b/config/locales/forms/en.yml @@ -66,8 +66,27 @@ en: personal_key: alternative: Don’t have your personal key? confirmation_label: Personal key + download: Download (text file) instructions: Please confirm you have a copy of your personal key by entering it below. + required_checkbox: Please check this box to continue. title: Enter your personal key + personal_key_partial: + acknowledgement: + bullets: + - You’ll lose access to your account + - You’ll need to verify your identity again + header: You need your personal key if you forget your password. Keep it safe and + don’t share it with anyone. + text: 'If you reset your password without your personal key:' + explanation: + header: What is a personal key? + text: + - A personal key “locks” your personal information with your account. + It’s the only way to unlock your information if you lose or forget + your password. + - When you reset your password, Login.gov will ask for your personal + key to make sure you are you - not someone pretending to be you. + header: Save your personal key phone: buttons: delete: Remove phone diff --git a/config/locales/forms/es.yml b/config/locales/forms/es.yml index 4d449c235a5..10027a2e992 100644 --- a/config/locales/forms/es.yml +++ b/config/locales/forms/es.yml @@ -71,9 +71,29 @@ es: personal_key: alternative: '¿No tiene su clave personal?' confirmation_label: Clave personal + download: Descargar (archivo de texto) instructions: Confirme que tiene una copia de su clave personal ingresándola a continuación. + required_checkbox: Marque esta casilla para continuar. title: Ingrese su clave personal + personal_key_partial: + acknowledgement: + bullets: + - Perderás el acceso a tu cuenta + - Tendrás que verificar tu identidad nuevamente + header: Necesitarás tu clave personal si olvidas tu contraseña. Mantenla en un + lugar seguro y no la compartas con nadie. + text: 'Si restableces tu contraseña sin tu clave personal:' + explanation: + header: ¿Qué es una clave personal? + text: + - Una clave personal “bloquea” la información personal de tu cuenta. + Es la única manera de desbloquear tu información si pierdes u + olvidas tu contraseña. + - Si restableces tu contraseña, Login.gov te pedirá tu clave personal + para asegurarse de que se trata de ti, y no de alguien que quiere + hacerse pasar por ti. + header: Guarda tu clave personal phone: buttons: delete: Eliminar el teléfono diff --git a/config/locales/forms/fr.yml b/config/locales/forms/fr.yml index 97cb4bd26ff..8035ab42d0b 100644 --- a/config/locales/forms/fr.yml +++ b/config/locales/forms/fr.yml @@ -72,9 +72,29 @@ fr: personal_key: alternative: Vous n’avez pas votre clé personnelle? confirmation_label: Clé personnelle + download: Télécharger (fichier texte) instructions: Veuillez confirmer que vous avez une copie de votre clé personnelle en l’entrant ci-dessous. + required_checkbox: Veuillez cocher cette case pour continuer. title: Entrez votre clé personnelle + personal_key_partial: + acknowledgement: + bullets: + - Vous perdrez l’accès à votre compte + - Vous allez devoir vérifier à nouveau votre identité + header: En cas d’oubli de votre mot de passe, vous aurez besoin de votre clé + personnelle. Gardez-la en sécurité et ne la partagez avec personne. + text: 'Si vous réinitialisez votre mot de passe sans votre clé personnelle:' + explanation: + header: Qu’est-ce qu’une clé personnelle? + text: + - Une clé personnelle « verrouille » vos informations personnelles + avec votre compte. C’est le seul moyen de déverrouiller vos + informations si vous perdez ou oubliez votre mot de passe. + - Lors de la réinitialisation de votre mot de passe, Login.gov vous + demandera votre clé personnelle pour s’assurer que vous êtes bien + vous, et non quelqu’un qui se fait passer pour vous. + header: Sauvegardez votre clé personnelle phone: buttons: delete: Supprimer le numéro de teléfono diff --git a/config/locales/headings/en.yml b/config/locales/headings/en.yml index c19a456178e..aca5a659bc6 100644 --- a/config/locales/headings/en.yml +++ b/config/locales/headings/en.yml @@ -34,7 +34,6 @@ en: confirm: Confirm your current password to continue confirm_for_personal_key: Enter password and get a new personal key forgot: Forgot your password? - personal_key: Save your personal key piv_cac: certificate: bad: The PIV/CAC certificate you selected is invalid diff --git a/config/locales/headings/es.yml b/config/locales/headings/es.yml index 01449e023fc..c8fc13dd168 100644 --- a/config/locales/headings/es.yml +++ b/config/locales/headings/es.yml @@ -34,7 +34,6 @@ es: confirm: Confirme la contraseña actual para continuar confirm_for_personal_key: Introduzca la contraseña y obtenga una nueva clave personal forgot: '¿Olvidó su contraseña?' - personal_key: Guarda tu clave personal piv_cac: certificate: bad: El certificado PIV/CAC que seleccionaste no es válido. diff --git a/config/locales/headings/fr.yml b/config/locales/headings/fr.yml index de2c4e53066..c70bd3f926c 100644 --- a/config/locales/headings/fr.yml +++ b/config/locales/headings/fr.yml @@ -34,7 +34,6 @@ fr: confirm: Confirmez votre mot de passe actuel pour continuer confirm_for_personal_key: Entrez le mot de passe et obtenez une nouvelle clé personnelle forgot: Vous avez oublié votre mot de passe? - personal_key: Enregistrez votre clé personnelle piv_cac: certificate: bad: Le certificat PIV/CAC que vous avez sélectionné n’est pas valide. diff --git a/config/locales/instructions/en.yml b/config/locales/instructions/en.yml index 9d3eae94ca6..abdf7e0763b 100644 --- a/config/locales/instructions/en.yml +++ b/config/locales/instructions/en.yml @@ -102,13 +102,6 @@ en: intro: 'Password strength: ' iv: Good v: Great! - personal_key: - email_body: Don’t lose your personal key or share it with others. We’ll ask for - it if you reset your password. - email_title: Save it. Keep it safe. - info: You’ll need this personal key if you forget your password. If you reset - your password and don’t have this key, you’ll have to verify your - identity again. sp_handoff_bounced: Your sign in was successful, but %{sp_name} sent you back to %{app_name}. Please contact %{sp_link} for help. sp_handoff_bounced_with_no_sp: your service provider diff --git a/config/locales/instructions/es.yml b/config/locales/instructions/es.yml index 9b1cfc800bb..bc2023c54a5 100644 --- a/config/locales/instructions/es.yml +++ b/config/locales/instructions/es.yml @@ -109,13 +109,6 @@ es: intro: 'Seguridad de la contraseña:' iv: Buena v: '¡Muy buena!' - personal_key: - email_body: No pierdas tu clave personal ni la compartas con otros. La pediremos - si restableces tu contraseña. - email_title: Guárdala. Manténla segura. - info: Necesitarás esta clave personal si olvidas tu contraseña. Si restableces - tu contraseña y no tienes esta clave, deberás verificar tu identidad - nuevamente. sp_handoff_bounced: Su inicio de sesión fue exitoso, pero %{sp_name} lo envió de regreso a %{app_name}. Póngase en contacto con %{sp_link} para obtener ayuda. diff --git a/config/locales/instructions/fr.yml b/config/locales/instructions/fr.yml index 6cd6ae02317..71174ab25f4 100644 --- a/config/locales/instructions/fr.yml +++ b/config/locales/instructions/fr.yml @@ -119,14 +119,6 @@ fr: intro: 'Force du mot de passe : ' iv: Bonne v: Excellente! - personal_key: - email_body: Ne perdez pas votre clé personnelle et ne la partagez pas avec - d’autres. Nous vous le demanderons si vous réinitialisez votre mot de - passe. - email_title: Sauvegarde le. Garde-le en sécurité. - info: Vous aurez besoin de cette clé personnelle si vous oubliez votre mot de - passe. Si vous réinitialisez votre mot de passe et que vous ne possédez - pas cette clé, vous devrez vérifier votre identité à nouveau. sp_handoff_bounced: Votre connexion a réussi, mais %{sp_name} vous a renvoyé à %{app_name}. Veuillez contacter %{sp_link} pour obtenir de l’aide. sp_handoff_bounced_with_no_sp: votre fournisseur de service diff --git a/config/locales/users/en.yml b/config/locales/users/en.yml index 378d09f4a02..316a6db802e 100644 --- a/config/locales/users/en.yml +++ b/config/locales/users/en.yml @@ -21,8 +21,7 @@ en: personal_key: close: Close confirmation_error: You’ve entered an incorrect personal key. - generated_on_html: Generated on %{date} - header: Your personal key + generated_on_html: Your personal key was generated on %{date} phones: error_message: You’ve added the maximum number of phone numbers. rules_of_use: diff --git a/config/locales/users/es.yml b/config/locales/users/es.yml index f1e8262854a..a883204cc8f 100644 --- a/config/locales/users/es.yml +++ b/config/locales/users/es.yml @@ -22,8 +22,7 @@ es: personal_key: close: Cerrar confirmation_error: Ha ingresado una clave personal incorrecta. - generated_on_html: Generado el %{date} - header: Su clave personal + generated_on_html: Tu clave personal fue generada el %{date} phones: error_message: Agregó el número máximo de números de teléfono. rules_of_use: diff --git a/config/locales/users/fr.yml b/config/locales/users/fr.yml index 1c17d049ae1..bbef10bd0f0 100644 --- a/config/locales/users/fr.yml +++ b/config/locales/users/fr.yml @@ -24,8 +24,7 @@ fr: personal_key: close: Fermer confirmation_error: Vous avez entré un clé personnelle erronée. - generated_on_html: Générée le %{date} - header: Votre clé personnelle + generated_on_html: Votre clé personnelle a été générée le %{date} phones: error_message: Vous avez ajouté le nombre maximum de numéros de téléphone. rules_of_use: diff --git a/lib/feature_management.rb b/lib/feature_management.rb index 4275487568b..a26e92bbe38 100644 --- a/lib/feature_management.rb +++ b/lib/feature_management.rb @@ -112,10 +112,6 @@ def self.log_to_stdout? !Rails.env.test? && IdentityConfig.store.log_to_stdout end - def self.idv_personal_key_confirmation_enabled? - IdentityConfig.store.idv_personal_key_confirmation_enabled - end - # Manual allowlist for VOIPs, should only include known VOIPs that we use for smoke tests # @return [Set] set of phone numbers normalized to e164 def self.voip_allowed_phones diff --git a/lib/identity_config.rb b/lib/identity_config.rb index 8f7ec34b0ea..d20424275c7 100644 --- a/lib/identity_config.rb +++ b/lib/identity_config.rb @@ -186,7 +186,6 @@ def self.build_store(config_map) config.add(:idv_min_age_years, type: :integer) config.add(:idv_native_camera_a_b_testing_enabled, type: :boolean) config.add(:idv_native_camera_a_b_testing_percent, type: :integer) - config.add(:idv_personal_key_confirmation_enabled, type: :boolean) config.add(:idv_send_link_attempt_window_in_minutes, type: :integer) config.add(:idv_send_link_max_attempts, type: :integer) config.add(:idv_sp_required, type: :boolean) diff --git a/spec/features/idv/analytics_spec.rb b/spec/features/idv/analytics_spec.rb index 59f6413ab7d..573bb134ce1 100644 --- a/spec/features/idv/analytics_spec.rb +++ b/spec/features/idv/analytics_spec.rb @@ -39,7 +39,7 @@ 'IdV: final resolution' => { success: true }, 'IdV: personal key visited' => {}, 'IdV: personal key submitted' => {}, - 'Frontend: IdV: show personal key modal' => {}, + 'IdV: personal key acknowledgment toggled' => { checked: true }, } end let(:gpo_path_events) do @@ -73,7 +73,6 @@ 'IdV: review complete' => { success: true }, 'IdV: final resolution' => { success: true }, 'IdV: personal key visited' => {}, - 'Frontend: IdV: show personal key modal' => {}, 'IdV: personal key submitted' => {}, 'IdV: come back later visited' => {}, } @@ -121,7 +120,6 @@ 'IdV: review complete' => { success: true }, 'IdV: final resolution' => { success: true }, 'IdV: personal key visited' => {}, - 'Frontend: IdV: show personal key modal' => {}, 'IdV: personal key submitted' => {}, 'IdV: in person ready to verify visited' => {}, } diff --git a/spec/features/idv/steps/confirmation_step_spec.rb b/spec/features/idv/steps/confirmation_step_spec.rb index 9dd13ed6c6a..0052d2d5733 100644 --- a/spec/features/idv/steps/confirmation_step_spec.rb +++ b/spec/features/idv/steps/confirmation_step_spec.rb @@ -3,19 +3,14 @@ feature 'idv confirmation step', js: true do include IdvStepHelper - let(:idv_personal_key_confirmation_enabled) { true } let(:sp) { nil } let(:address_verification_mechanism) { :phone } before do - allow(IdentityConfig.store).to receive(:idv_personal_key_confirmation_enabled). - and_return(idv_personal_key_confirmation_enabled) start_idv_from_sp(sp) complete_idv_steps_before_confirmation_step(address_verification_mechanism) end - it_behaves_like 'personal key page' - it 'shows status content for phone verification progress' do expect(page).to have_content(t('idv.messages.confirm')) expect_step_indicator_current_step(t('step_indicator.flows.idv.secure_account')) @@ -29,7 +24,7 @@ it 'allows the user to refresh and still displays the personal key' do # Visit the current path is the same as refreshing visit current_path - expect(page).to have_content(t('headings.personal_key')) + expect(page).to have_content(t('forms.personal_key_partial.acknowledgement.header')) end context 'verifying by gpo' do @@ -41,13 +36,21 @@ expect(page).to have_content(t('step_indicator.flows.idv.get_a_letter')) expect(page).not_to have_content(t('step_indicator.flows.idv.verify_phone_or_address')) end - - it_behaves_like 'personal key page', :gpo end context 'with associated sp' do let(:sp) { :oidc } + it "forces the user to click the 'acknowledge' checkbox before proceeding" do + click_continue + + expect(page).to have_content(t('forms.validation.required_checkbox')) + expect(current_path).to eq(idv_personal_key_path) + + acknowledge_and_confirm_personal_key + expect(page).to have_current_path(sign_up_completed_path) + end + it 'redirects to the completions page and then to the SP' do acknowledge_and_confirm_personal_key @@ -57,19 +60,5 @@ expect(current_url).to start_with('http://localhost:7654/auth/result') end - - context 'with personal key confirmation disabled' do - let(:idv_personal_key_confirmation_enabled) { false } - - it 'redirects to the completions page and then to the SP' do - click_acknowledge_personal_key - - expect(page).to have_current_path(sign_up_completed_path) - - click_agree_and_continue - - expect(current_url).to start_with('http://localhost:7654/auth/result') - end - end end end diff --git a/spec/features/idv/steps/review_step_spec.rb b/spec/features/idv/steps/review_step_spec.rb index 652aabde783..3b90bd99784 100644 --- a/spec/features/idv/steps/review_step_spec.rb +++ b/spec/features/idv/steps/review_step_spec.rb @@ -32,7 +32,7 @@ fill_in 'Password', with: user_password click_idv_continue - expect(page).to have_content(t('headings.personal_key')) + expect(page).to have_content(t('forms.personal_key_partial.acknowledgement.header')) expect(current_path).to eq idv_personal_key_path end diff --git a/spec/features/users/regenerate_personal_key_spec.rb b/spec/features/users/regenerate_personal_key_spec.rb index 5a595988db2..135e09fd650 100644 --- a/spec/features/users/regenerate_personal_key_spec.rb +++ b/spec/features/users/regenerate_personal_key_spec.rb @@ -52,22 +52,11 @@ expect(page).to have_content(t('account.personal_key.get_new')) click_continue - expect(page).to have_content(t('headings.personal_key')) + expect(page).to have_content(t('forms.personal_key_partial.acknowledgement.header')) acknowledge_and_confirm_personal_key expect(user.reload.encrypted_recovery_code_digest).to_not eq old_digest end end - - describe 'personal key actions and information' do - before do - sign_in_and_2fa_user(user) - visit account_two_factor_authentication_path - click_on(t('account.links.regenerate_personal_key'), match: :prefer_exact) - click_continue - end - - it_behaves_like 'personal key page' - end end end diff --git a/spec/support/features/session_helper.rb b/spec/support/features/session_helper.rb index d98d38b7a89..dc517a6b51c 100644 --- a/spec/support/features/session_helper.rb +++ b/spec/support/features/session_helper.rb @@ -318,12 +318,11 @@ def sign_in_with_totp_enabled_user def acknowledge_and_confirm_personal_key click_acknowledge_personal_key - - page.find(':focus').fill_in with: scrape_personal_key - within('[role=dialog]') { click_continue } end def click_acknowledge_personal_key + checkbox_header = t('forms.validation.required_checkbox') + find('label', text: /#{checkbox_header}/).click click_continue end diff --git a/spec/support/shared_examples_for_personal_keys.rb b/spec/support/shared_examples_for_personal_keys.rb deleted file mode 100644 index c271dbdc0ed..00000000000 --- a/spec/support/shared_examples_for_personal_keys.rb +++ /dev/null @@ -1,85 +0,0 @@ -require 'rbconfig' - -shared_examples_for 'personal key page' do |address_verification_mechanism| - include PersonalKeyHelper - include JavascriptDriverHelper - - describe 'confirmation modal' do - before do - click_continue if javascript_enabled? - end - - it 'displays modal content' do - expect(page).to have_content t('forms.personal_key.title') - expect(page).to have_content t('forms.personal_key.instructions') - end - end - - context 'with javascript enabled', js: true do - before do - page.driver.browser.execute_cdp( - 'Browser.grantPermissions', - origin: page.server_url, - permissions: ['clipboardReadWrite', 'clipboardSanitizedWrite'], - ) - end - - after do - page.driver.browser.execute_cdp('Browser.resetPermissions') - end - - it 'allows a user to copy the code into the confirmation modal' do - click_on t('components.clipboard_button.label') - 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 - code_segments = scrape_personal_key.split('-') - - click_acknowledge_personal_key - input = page.find(':focus') - - # Validate as incorrect - input.fill_in with: 'wrong!' - within('[role=dialog]') { click_on t('forms.buttons.continue') } - expect(page).to have_content(t('users.personal_key.confirmation_error')) - - # Validate as correct, with formatting variations... - - # Include dash between some segments and not others - code = code_segments[0..1].join('-') + code_segments[2..3].join - - # Randomize case - code = code.chars.map { |c| (rand 2) == 0 ? c.downcase : c.upcase }.join - - # De-normalize Crockford encoding - code = code.sub('1', 'l').sub('0', 'O') - - # Add extra characters - code += 'abc123qwerty' - - input.fill_in with: code - - within('[role=dialog]') { click_on t('forms.buttons.continue') } - if address_verification_mechanism == :gpo - expect(current_path).to eq idv_come_back_later_path - else - expect(current_path).to eq account_path - end - end - end - - def mac? - RbConfig::CONFIG['host_os'].match? 'darwin' - end -end diff --git a/spec/views/shared/_personal_key.html.erb_spec.rb b/spec/views/shared/_personal_key.html.erb_spec.rb index 594c9060d64..1d23828ceb4 100644 --- a/spec/views/shared/_personal_key.html.erb_spec.rb +++ b/spec/views/shared/_personal_key.html.erb_spec.rb @@ -29,29 +29,4 @@ def self.decode(value) expect(data_uri.data).to eq(personal_key) end end - - describe 'continue button' do - let(:idv_personal_key_confirmation_enabled) { nil } - - before do - allow(FeatureManagement).to receive(:idv_personal_key_confirmation_enabled?). - and_return(idv_personal_key_confirmation_enabled) - end - - context 'without idv personal key confirmation' do - let(:idv_personal_key_confirmation_enabled) { false } - - it 'renders button with [data-toggle="skip"]' do - expect(rendered).to have_css('[data-toggle="skip"]') - end - end - - context 'with idv personal key confirmation' do - let(:idv_personal_key_confirmation_enabled) { true } - - it 'renders button with [data-toggle="modal"]' do - expect(rendered).to have_css('[data-toggle="modal"]') - end - end - end end