diff --git a/app/controllers/concerns/mfa_setup_concern.rb b/app/controllers/concerns/mfa_setup_concern.rb index d22df51a6c0..12b3f345465 100644 --- a/app/controllers/concerns/mfa_setup_concern.rb +++ b/app/controllers/concerns/mfa_setup_concern.rb @@ -1,8 +1,26 @@ module MfaSetupConcern extend ActiveSupport::Concern - def user_next_authentication_setup_path!(final_path = nil) - case user_session[:selected_mfa_options]&.shift + def user_next_authentication_setup_path(next_setup_choice) + if user_session.dig(:selected_mfa_options, determine_next_mfa_selection).present? && + IdentityConfig.store.select_multiple_mfa_options + auth_method_confirmation_url(next_setup_choice: next_setup_choice) + else + user_session.delete(:selected_mfa_options) + nil + end + end + + def determine_next_mfa_selection + return unless user_session[:selected_mfa_options] + current_session = user_session[:next_mfa_selection_choice] + current_index = user_session[:selected_mfa_options].find_index(current_session) || 0 + current_index + 1 + end + + def confirmation_path(next_mfa_selection_choice) + user_session[:next_mfa_selection_choice] = next_mfa_selection_choice + case next_mfa_selection_choice when 'voice', 'sms', 'phone' phone_setup_url when 'auth_app' @@ -15,8 +33,6 @@ def user_next_authentication_setup_path!(final_path = nil) webauthn_setup_url(platform: true) when 'backup_code' backup_code_setup_url - else - final_path end end diff --git a/app/controllers/mfa_confirmation_controller.rb b/app/controllers/mfa_confirmation_controller.rb index c53ae468bb0..e27ff2316e6 100644 --- a/app/controllers/mfa_confirmation_controller.rb +++ b/app/controllers/mfa_confirmation_controller.rb @@ -1,5 +1,20 @@ class MfaConfirmationController < ApplicationController - before_action :confirm_two_factor_authenticated + include MfaSetupConcern + before_action :confirm_two_factor_authenticated, except: [:show] + + def show + @presenter = MfaConfirmationShowPresenter.new( + current_user: current_user, + next_path: next_path, + final_path: after_mfa_setup_path, + ) + end + + def skip + user_session.delete(:selected_mfa_options) + user_session.delete(:next_mfa_selection_choice) + redirect_to after_mfa_setup_path + end def new session[:password_attempts] ||= 0 @@ -19,6 +34,15 @@ def password params.require(:user)[:password] end + def next_mfa_selection_choice + params[:next_setup_choice] || + user_session[:next_mfa_selection_choice] + end + + def next_path + confirmation_path(next_mfa_selection_choice) + end + def handle_valid_password if current_user.auth_app_configurations.any? redirect_to login_two_factor_authenticator_url(reauthn: true) diff --git a/app/controllers/two_factor_authentication/otp_verification_controller.rb b/app/controllers/two_factor_authentication/otp_verification_controller.rb index 6c170fc3d3e..e304a39c3a2 100644 --- a/app/controllers/two_factor_authentication/otp_verification_controller.rb +++ b/app/controllers/two_factor_authentication/otp_verification_controller.rb @@ -19,7 +19,13 @@ def create if result.success? next_url = nil if UserSessionContext.confirmation_context?(context) - next_url = user_next_authentication_setup_path! + next_mfa_setup_for_user = user_session.dig( + :selected_mfa_options, + determine_next_mfa_selection, + ) + next_url = user_next_authentication_setup_path( + next_mfa_setup_for_user, + ) end handle_valid_otp(next_url) else diff --git a/app/controllers/users/backup_code_setup_controller.rb b/app/controllers/users/backup_code_setup_controller.rb index d844d6d1157..2d226d26d52 100644 --- a/app/controllers/users/backup_code_setup_controller.rb +++ b/app/controllers/users/backup_code_setup_controller.rb @@ -25,7 +25,12 @@ def edit; end def continue flash[:success] = t('notices.backup_codes_configured') - redirect_to user_next_authentication_setup_path!(after_mfa_setup_path) + next_mfa_setup_for_user = user_session.dig( + :selected_mfa_options, + determine_next_mfa_selection, + ) + redirect_to user_next_authentication_setup_path(next_mfa_setup_for_user) || + after_mfa_setup_path end def download diff --git a/app/controllers/users/piv_cac_authentication_setup_controller.rb b/app/controllers/users/piv_cac_authentication_setup_controller.rb index ee21c20ff7d..f8a8560d6d1 100644 --- a/app/controllers/users/piv_cac_authentication_setup_controller.rb +++ b/app/controllers/users/piv_cac_authentication_setup_controller.rb @@ -104,7 +104,12 @@ def process_valid_submission Funnel::Registration::AddMfa.call(current_user.id, 'piv_cac') session[:needs_to_setup_piv_cac_after_sign_in] = false final_path = after_sign_in_path_for(current_user) - redirect_to user_next_authentication_setup_path!(final_path) + next_mfa_setup_for_user = user_session.dig( + :selected_mfa_options, + determine_next_mfa_selection, + ) + redirect_to user_next_authentication_setup_path(next_mfa_setup_for_user) || + final_path end def piv_cac_enabled? diff --git a/app/controllers/users/totp_setup_controller.rb b/app/controllers/users/totp_setup_controller.rb index 1790e3de945..d49cdcc9897 100644 --- a/app/controllers/users/totp_setup_controller.rb +++ b/app/controllers/users/totp_setup_controller.rb @@ -79,7 +79,12 @@ def process_valid_code handle_remember_device flash[:success] = t('notices.totp_configured') user_session.delete(:new_totp_secret) - redirect_to user_next_authentication_setup_path!(after_mfa_setup_path) + next_mfa_setup_for_user = user_session.dig( + :selected_mfa_options, + determine_next_mfa_selection, + ) + redirect_to user_next_authentication_setup_path(next_mfa_setup_for_user) || + after_mfa_setup_path end def handle_remember_device diff --git a/app/controllers/users/two_factor_authentication_setup_controller.rb b/app/controllers/users/two_factor_authentication_setup_controller.rb index c1067d4ad30..9543960b3cd 100644 --- a/app/controllers/users/two_factor_authentication_setup_controller.rb +++ b/app/controllers/users/two_factor_authentication_setup_controller.rb @@ -44,7 +44,7 @@ def two_factor_options_presenter def process_valid_form user_session[:selected_mfa_options] = @two_factor_options_form.selection - redirect_to user_next_authentication_setup_path!(user_session[:selected_mfa_options].first) + redirect_to confirmation_path(user_session[:selected_mfa_options].first) end def handle_empty_selection diff --git a/app/controllers/users/webauthn_setup_controller.rb b/app/controllers/users/webauthn_setup_controller.rb index 1fd64e6a13c..6f4a6e985d3 100644 --- a/app/controllers/users/webauthn_setup_controller.rb +++ b/app/controllers/users/webauthn_setup_controller.rb @@ -139,7 +139,12 @@ def process_valid_webauthn(form) end user_session[:auth_method] = 'webauthn' - redirect_to user_next_authentication_setup_path!(after_mfa_setup_path) + next_mfa_setup_for_user = user_session.dig( + :selected_mfa_options, + determine_next_mfa_selection, + ) + redirect_to user_next_authentication_setup_path(next_mfa_setup_for_user) || + after_mfa_setup_path end def handle_remember_device diff --git a/app/presenters/mfa_confirmation_show_presenter.rb b/app/presenters/mfa_confirmation_show_presenter.rb new file mode 100644 index 00000000000..b574ad63f29 --- /dev/null +++ b/app/presenters/mfa_confirmation_show_presenter.rb @@ -0,0 +1,34 @@ +class MfaConfirmationShowPresenter + include ActionView::Helpers::TranslationHelper + attr_reader :mfa_context, :final_path, :next_path + def initialize(current_user:, next_path:, final_path:) + @mfa_context = MfaContext.new(current_user) + @final_path = final_path + @next_path = next_path + end + + def title + if enabled_method_count > 1 + t( + 'titles.mfa_setup.multiple_authentication_methods_setup', + method_count: method_count_text, + ) + else + t('titles.mfa_setup.first_authentication_method') + end + end + + def info + t('mfa.account_info', count: enabled_method_count) + end + + private + + def enabled_method_count + mfa_context.enabled_mfa_methods_count + end + + def method_count_text + t('mfa.current_method_count')[enabled_method_count - 1] + end +end diff --git a/app/views/mfa_confirmation/index.html.erb b/app/views/mfa_confirmation/index.html.erb deleted file mode 100644 index d46e018e7f7..00000000000 --- a/app/views/mfa_confirmation/index.html.erb +++ /dev/null @@ -1,21 +0,0 @@ -<%# All content on this page is currently set up for MFA user testing. - Once ready to ship to prod, translate all text content in Gengo %> - -<% title t('titles.mfa_setup.first_authentication_method') %> - -<%= render AlertComponent.new(type: :success, class: 'margin-bottom-4') do %> - <%= t('mfa.method_confirmation.face_id') %> -<% end %> - -<%= image_tag asset_url('user-signup-ial1.svg'), width: 107, height: 119, alt: '', class: 'margin-bottom-4' %> - -<%= render PageHeadingComponent.new.with_content(t('headings.mfa_setup.first_authentication_method')) %> - -

<%= t('mfa.cta') %>

- -<%= button_to( - account_reset_pending_cancel_path, - class: 'usa-button usa-button--wide usa-button--big margin-bottom-3', - ) { t('mfa.add') } %> - -<%= link_to t('mfa.skip'), root_url %> \ No newline at end of file diff --git a/app/views/mfa_confirmation/show.html.erb b/app/views/mfa_confirmation/show.html.erb new file mode 100644 index 00000000000..6eb1477d6bd --- /dev/null +++ b/app/views/mfa_confirmation/show.html.erb @@ -0,0 +1,22 @@ +<% title @presenter.title %> + +<%= image_tag asset_url('user-signup-ial1.svg'), width: 107, height: 119, alt: '', class: 'margin-bottom-4' %> + +<%= render PageHeadingComponent.new.with_content(@presenter.title) %> + +

<%= @presenter.info %>

+ +
+ <%= link_to( + @presenter.next_path, + class: 'usa-button usa-button--wide usa-button--big margin-bottom-3', + ) { t('mfa.add') } %> +
+ +<%= button_to( + auth_method_confirmation_skip_path, + method: :post, + class: 'usa-button usa-button--unstyled', + ) do %> + <%= t('mfa.skip') %> +<% end %> \ No newline at end of file diff --git a/config/locales/headings/en.yml b/config/locales/headings/en.yml index 99f2d903461..1746afd5dc8 100644 --- a/config/locales/headings/en.yml +++ b/config/locales/headings/en.yml @@ -29,8 +29,6 @@ en: edit_info: password: Change your password phone: Manage your phone settings - mfa_setup: - first_authentication_method: You’ve added your first authentication method! passwords: change: Change your password confirm: Confirm your current password to continue diff --git a/config/locales/headings/es.yml b/config/locales/headings/es.yml index fc06eeabe1e..6315c930147 100644 --- a/config/locales/headings/es.yml +++ b/config/locales/headings/es.yml @@ -29,8 +29,6 @@ es: edit_info: password: Cambie su contraseña phone: Administrar la configuración de su teléfono - mfa_setup: - first_authentication_method: ¡Has agregado tu primer método de autenticación! passwords: change: Cambie su contraseña confirm: Confirme la contraseña actual para continuar diff --git a/config/locales/headings/fr.yml b/config/locales/headings/fr.yml index 536cec98c0a..c00f6e3cfb8 100644 --- a/config/locales/headings/fr.yml +++ b/config/locales/headings/fr.yml @@ -29,8 +29,6 @@ fr: edit_info: password: Changez votre mot de passe phone: Administrer les paramètres de votre téléphone - mfa_setup: - first_authentication_method: Vous avez ajouté votre première méthode d’authentification! passwords: change: Changez votre mot de passe confirm: Confirmez votre mot de passe actuel pour continuer diff --git a/config/locales/mfa/en.yml b/config/locales/mfa/en.yml index 16ac718e808..3fdb5378c28 100644 --- a/config/locales/mfa/en.yml +++ b/config/locales/mfa/en.yml @@ -1,13 +1,23 @@ --- en: mfa: + account_info: + one: Adding another authentication method prevents you from getting locked out + of your account if you lose one of your methods. + other: Congratulations! You are doing very well to keep your account secure. Add + new devices to stay up to date. add: Add another method - cta: Adding another authentication method prevents you from getting locked out - of your account if you lose one of your methods. + current_method_count: + - first + - second + - third + - fourth + - fifth + - sixth + - seventh + - eighth info: We recommend you select at least (2) two different methods so you have a backup if you lose one of your chosen authentication devices. - method_confirmation: - face_id: Face ID has been added to your account second_method_warning: link: Add a second authentication method. text: You will have to delete your account and start over if you lose your only diff --git a/config/locales/mfa/es.yml b/config/locales/mfa/es.yml index 448026c1e8a..b07e4a02585 100644 --- a/config/locales/mfa/es.yml +++ b/config/locales/mfa/es.yml @@ -1,14 +1,24 @@ --- es: mfa: + account_info: + one: Agregar otro método de autenticación evita que se le bloquee el acceso a su + cuenta si pierde uno de sus métodos. + other: ¡Felicitaciones! Está haciendo muy bien en mantener su cuenta segura. + Añada nuevos dispositivos para mantenerse al día. add: Agregar otro método - cta: Agregar otro método de autenticación evita que se le bloquee el acceso a su - cuenta si pierde uno de sus métodos. + current_method_count: + - primero + - segundo + - tercero + - cuarto + - quinto + - sexto + - séptimo + - octavo info: Le recomendamos que seleccione al menos (2) dos métodos diferentes para tener una copia de seguridad si pierde uno de los dispositivos de autenticación elegidos. - method_confirmation: - face_id: Se ha agregado Face ID a su cuenta second_method_warning: link: Agregue un segundo método de autenticación. text: Deberá eliminar su cuenta y comenzar de nuevo si pierde su único método de diff --git a/config/locales/mfa/fr.yml b/config/locales/mfa/fr.yml index 19f604c2033..b26f1b14b94 100644 --- a/config/locales/mfa/fr.yml +++ b/config/locales/mfa/fr.yml @@ -1,14 +1,24 @@ --- fr: mfa: + account_info: + one: L’ajout d’une autre méthode d’authentification vous empêche d’être bloqué + sur votre compte si vous perdez l’une de vos méthodes. + other: Félicitations! Vous faites très bien d’assurer la sécurité de votre + compte. Ajoutez de nouveaux appareils pour rester à jour. add: Agregar otro método - cta: L’ajout d’une autre méthode d’authentification vous empêche d’être bloqué - sur votre compte si vous perdez l’une de vos méthodes. + current_method_count: + - premiere + - deuxième + - troisième + - quatrième + - cinquième + - sixième + - septième + - huitième info: Nous vous recommandons de sélectionner au moins (2) deux méthodes différentes afin d’avoir une sauvegarde si vous perdez l’un de vos dispositifs d’authentification choisis. - method_confirmation: - face_id: Face ID a été ajouté à votre compte second_method_warning: link: Ajoutez une deuxième méthode d’authentification. text: Vous devrez supprimer votre compte et recommencer si vous perdez votre diff --git a/config/locales/titles/en.yml b/config/locales/titles/en.yml index f4aa00f3803..e952eac35be 100644 --- a/config/locales/titles/en.yml +++ b/config/locales/titles/en.yml @@ -42,6 +42,7 @@ en: review: Re-enter your password mfa_setup: first_authentication_method: You’ve added your first authentication method! + multiple_authentication_methods_setup: You’ve added a %{method_count} authentication method! no_auth_option: No sign-in method found openid_connect: authorization: OpenID Connect Authorization diff --git a/config/locales/titles/es.yml b/config/locales/titles/es.yml index b43247e20ca..37a73435e53 100644 --- a/config/locales/titles/es.yml +++ b/config/locales/titles/es.yml @@ -42,6 +42,7 @@ es: review: Vuelve a ingresar tu contraseña mfa_setup: first_authentication_method: ¡Has agregado tu primer método de autenticación! + multiple_authentication_methods_setup: ¡Se ha agregado un %{method_count} código de autenticación! no_auth_option: No se encontró mensaje de inicio de sesión openid_connect: authorization: Autorización de OpenID Connect diff --git a/config/locales/titles/fr.yml b/config/locales/titles/fr.yml index dd4c6d205fc..768bba9c639 100644 --- a/config/locales/titles/fr.yml +++ b/config/locales/titles/fr.yml @@ -42,6 +42,7 @@ fr: review: Saisissez à nouveau votre mot de passe mfa_setup: first_authentication_method: Vous avez ajouté votre première méthode d’authentification! + multiple_authentication_methods_setup: Vous avez ajouté une %{method_count} méthode d’authentification! no_auth_option: Aucun message de connexion trouvé openid_connect: authorization: Autorisation OpenID Connect diff --git a/config/routes.rb b/config/routes.rb index 44feb832dca..47f926bc0bb 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -140,9 +140,8 @@ end end - if IdentityConfig.store.select_multiple_mfa_options - get '/auth_method_confirmation' => 'mfa_confirmation#show' - end + get '/auth_method_confirmation' => 'mfa_confirmation#show' + post '/auth_method_confirmation/skip' => 'mfa_confirmation#skip' # Non-devise-controller routes. Alphabetically sorted. get '/.well-known/openid-configuration' => 'openid_connect/configuration#index', diff --git a/spec/controllers/mfa_confirmation_controller_spec.rb b/spec/controllers/mfa_confirmation_controller_spec.rb index c064ae8acc1..22453bfc17d 100644 --- a/spec/controllers/mfa_confirmation_controller_spec.rb +++ b/spec/controllers/mfa_confirmation_controller_spec.rb @@ -1,6 +1,16 @@ require 'rails_helper' describe MfaConfirmationController do + describe '#show' do + it 'presents the mfa confirmation page.' do + stub_sign_in + + get :show, params: { final_path: account_url } + + expect(response.status).to eq 200 + end + end + describe '#new' do it 'presents the password confirmation form' do stub_sign_in diff --git a/spec/controllers/users/backup_code_setup_controller_spec.rb b/spec/controllers/users/backup_code_setup_controller_spec.rb index 0c0b15daf30..1c80a71329a 100644 --- a/spec/controllers/users/backup_code_setup_controller_spec.rb +++ b/spec/controllers/users/backup_code_setup_controller_spec.rb @@ -35,16 +35,20 @@ end context 'when user selects multiple mfas on account creation' do - it 'redirects to phone setup page' do + before do + allow(IdentityConfig.store).to receive(:select_multiple_mfa_options).and_return true + end + + it 'redirects to MFA confirmation page' do user = build(:user, :signed_up) stub_sign_in(user) codes = BackupCodeGenerator.new(user).create controller.user_session[:backup_codes] = codes - controller.user_session[:selected_mfa_options] = ['voice'] + controller.user_session[:selected_mfa_options] = ['backup_code', 'voice'] post :continue - expect(response).to redirect_to(phone_setup_url) + expect(response).to redirect_to(auth_method_confirmation_url(next_setup_choice: 'voice')) end end diff --git a/spec/controllers/users/piv_cac_authentication_setup_controller_spec.rb b/spec/controllers/users/piv_cac_authentication_setup_controller_spec.rb index 55d89d59d44..2d45e41621d 100644 --- a/spec/controllers/users/piv_cac_authentication_setup_controller_spec.rb +++ b/spec/controllers/users/piv_cac_authentication_setup_controller_spec.rb @@ -120,11 +120,16 @@ context 'with additional MFAs leftover' do before do - subject.user_session[:selected_mfa_options] = ['voice'] + subject.user_session[:selected_mfa_options] = ['piv_cac', 'voice'] + allow(IdentityConfig.store).to receive(:select_multiple_mfa_options).and_return true end - it 'redirects to phone setup page' do + it 'redirects to Mfa Confirmation page' do get :new, params: { token: good_token } - expect(response).to redirect_to(phone_setup_url) + expect(response).to redirect_to( + auth_method_confirmation_url( + next_setup_choice: 'voice', + ), + ) end it 'sets the piv/cac session information' do diff --git a/spec/controllers/users/totp_setup_controller_spec.rb b/spec/controllers/users/totp_setup_controller_spec.rb index fe3764b300c..5437d138d56 100644 --- a/spec/controllers/users/totp_setup_controller_spec.rb +++ b/spec/controllers/users/totp_setup_controller_spec.rb @@ -235,6 +235,7 @@ allow(@analytics).to receive(:track_event) subject.user_session[:new_totp_secret] = secret subject.user_session[:selected_mfa_options] = selected_mfa_options + allow(IdentityConfig.store).to receive(:select_multiple_mfa_options).and_return true patch :confirm, params: { name: name, code: generate_totp_code(secret) } end @@ -257,9 +258,14 @@ end context 'when user has multiple MFA methods left in user session' do - let(:selected_mfa_options) { ['voice'] } - it 'redirects to phone_setup_path with a success message and still logs analytics' do - expect(response).to redirect_to(phone_setup_path) + let(:selected_mfa_options) { ['auth_app', 'voice'] } + + it 'redirects to mfa confirmation path with a success message and still logs analytics' do + expect(response).to redirect_to( + auth_method_confirmation_url( + next_setup_choice: 'voice', + ), + ) result = { success: true, diff --git a/spec/controllers/users/webauthn_setup_controller_spec.rb b/spec/controllers/users/webauthn_setup_controller_spec.rb index 75fe4ef17dc..c43dd0b8a5c 100644 --- a/spec/controllers/users/webauthn_setup_controller_spec.rb +++ b/spec/controllers/users/webauthn_setup_controller_spec.rb @@ -154,13 +154,14 @@ context 'with multiple MFA methods chosen on account creation' do before do - controller.user_session[:selected_mfa_options] = ['voice'] + controller.user_session[:selected_mfa_options] = ['webauthn_platform', 'voice'] + allow(IdentityConfig.store).to receive(:select_multiple_mfa_options).and_return true end it 'should direct user to phone page' do patch :confirm, params: params - expect(response).to redirect_to(phone_setup_url) + expect(response).to redirect_to(auth_method_confirmation_url(next_setup_choice: 'voice')) end end diff --git a/spec/features/multi_factor_authentication/mfa_cta_spec.rb b/spec/features/multi_factor_authentication/mfa_cta_spec.rb index d214ab970f9..317bd6a32d2 100644 --- a/spec/features/multi_factor_authentication/mfa_cta_spec.rb +++ b/spec/features/multi_factor_authentication/mfa_cta_spec.rb @@ -42,6 +42,11 @@ expect(page).to have_current_path(phone_setup_path) set_up_mfa_with_valid_phone + + expect(page).to have_current_path( + auth_method_confirmation_path(next_setup_choice: 'backup_code'), + ) + click_link t('mfa.add') expect(page).to have_current_path(backup_code_setup_path) set_up_mfa_with_backup_codes expect(page).to have_current_path(sign_up_completed_path) diff --git a/spec/features/two_factor_authentication/multiple_mfa_sign_up_spec.rb b/spec/features/two_factor_authentication/multiple_mfa_sign_up_spec.rb new file mode 100644 index 00000000000..921d5f03681 --- /dev/null +++ b/spec/features/two_factor_authentication/multiple_mfa_sign_up_spec.rb @@ -0,0 +1,82 @@ +require 'rails_helper' + +feature 'Multi Two Factor Authentication' do + before do + allow(IdentityConfig.store).to receive(:select_multiple_mfa_options).and_return(true) + end + + describe 'When the user has not set up 2FA' do + scenario 'user can set up 2 MFA methods properly' do + sign_in_before_2fa + + expect(current_path).to eq two_factor_options_path + + click_2fa_option('phone') + click_2fa_option('backup_code') + + click_continue + + expect(page). + to have_content t('titles.phone_setup') + + expect(current_path).to eq phone_setup_path + + fill_in 'new_phone_form_phone', with: '703-555-1212' + click_send_security_code + + fill_in_code_with_last_phone_otp + click_submit_default + + expect(page).to have_current_path( + auth_method_confirmation_path(next_setup_choice: 'backup_code'), + ) + + click_link t('mfa.add') + + expect(current_path).to eq backup_code_setup_path + + click_continue + + expect(page).to have_link(t('forms.backup_code.download')) + + click_continue + + expect(page).to have_content(t('notices.backup_codes_configured')) + expect(current_path).to eq account_path + end + + scenario 'user can select 2 MFA methods and complete 1 and skip one' do + sign_in_before_2fa + + expect(current_path).to eq two_factor_options_path + + click_2fa_option('phone') + click_2fa_option('backup_code') + + click_continue + + expect(page). + to have_content t('titles.phone_setup') + + expect(current_path).to eq phone_setup_path + + fill_in 'new_phone_form_phone', with: '703-555-1212' + click_send_security_code + + fill_in_code_with_last_phone_otp + click_submit_default + + expect(page).to have_current_path( + auth_method_confirmation_path(next_setup_choice: 'backup_code'), + ) + + click_button t('mfa.skip') + + expect(current_path).to eq account_path + end + end + + def click_2fa_option(option) + find("label[for='two_factor_options_form_selection_#{option}']").click + end +end diff --git a/spec/views/mfa_confirmation/index.html.erb_spec.rb b/spec/views/mfa_confirmation/index.html.erb_spec.rb deleted file mode 100644 index 701fdbbc128..00000000000 --- a/spec/views/mfa_confirmation/index.html.erb_spec.rb +++ /dev/null @@ -1,27 +0,0 @@ -require 'rails_helper' - -describe 'mfa_confirmation/index.html.erb' do - it 'has a localized title' do - expect(view).to receive(:title).with(t('titles.mfa_setup.first_authentication_method')) - - render - end - - it 'has a localized header' do - render - - expect(rendered).to have_content(t('headings.mfa_setup.first_authentication_method')) - end - - it 'provides a call to action to add another MFA method' do - render - - expect(rendered).to have_selector('p', text: t('mfa.cta')) - end - - it 'has a button with the next step' do - render - - expect(rendered).to have_selector('button', text: t('mfa.add')) - end -end diff --git a/spec/views/mfa_confirmation/show.html.erb_spec.rb b/spec/views/mfa_confirmation/show.html.erb_spec.rb new file mode 100644 index 00000000000..7deccdb1827 --- /dev/null +++ b/spec/views/mfa_confirmation/show.html.erb_spec.rb @@ -0,0 +1,45 @@ +require 'rails_helper' + +describe 'mfa_confirmation/show.html.erb' do + let(:user) { create(:user, :signed_up, :with_personal_key) } + let(:decorated_user) { user.decorate } + + before do + allow(view).to receive(:current_user).and_return(user) + assign( + :presenter, + MfaConfirmationShowPresenter.new( + current_user: user, + next_path: phone_setup_url, + final_path: account_url, + ), + ) + end + + it 'has a localized title' do + expect(view).to receive(:title).with(t('titles.mfa_setup.first_authentication_method')) + + render + end + + it 'has a localized header' do + render + + expect(rendered).to have_content(t('titles.mfa_setup.first_authentication_method')) + end + + it 'provides a call to action to add another MFA method' do + render + + expect(rendered).to have_selector( + 'p', + text: t('mfa.account_info', count: 1), + ) + end + + it 'has a button with the ability to skip step' do + render + + expect(rendered).to have_selector('button', text: t('mfa.skip')) + end +end