diff --git a/app/components/vendor_outage_alert_component.html.erb b/app/components/vendor_outage_alert_component.html.erb new file mode 100644 index 00000000000..abc68baa15f --- /dev/null +++ b/app/components/vendor_outage_alert_component.html.erb @@ -0,0 +1,6 @@ +<% if content %> + <%= render(AlertComponent.new(type: :error, class: 'margin-bottom-4')) do %> + <%= content %> + <%= new_window_link_to t('vendor_outage.get_updates'), StatusPage.base_url %> + <% end %> +<% end %> diff --git a/app/components/vendor_outage_alert_component.rb b/app/components/vendor_outage_alert_component.rb new file mode 100644 index 00000000000..dbf7a21d104 --- /dev/null +++ b/app/components/vendor_outage_alert_component.rb @@ -0,0 +1,42 @@ +class VendorOutageAlertComponent < BaseComponent + include LinkHelper + + def initialize(vendors:, only_if_all: false, context: 'default') + @vendors = vendors + @only_if_all = only_if_all + @context = context + end + + def content + case outages.sort + when [:sms, :voice] + # i18n-tasks-use t('vendor_outage.alerts.phone.default') + # i18n-tasks-use t('vendor_outage.alerts.phone.idv') + t(context, scope: 'vendor_outage.alerts.phone', default: :default) + when [:sms] + # i18n-tasks-use t('vendor_outage.alerts.sms.default') + # i18n-tasks-use t('vendor_outage.alerts.sms.idv') + t(context, scope: 'vendor_outage.alerts.sms', default: :default) + when [:voice] + # i18n-tasks-use t('vendor_outage.alerts.voice.default') + # i18n-tasks-use t('vendor_outage.alerts.voice.idv') + t(context, scope: 'vendor_outage.alerts.voice', default: :default) + end + end + + private + + attr_reader :vendors, :only_if_all, :context + + def outages + if only_if_all + vendor_status.all_vendor_outage?(vendors) ? vendors : [] + else + vendors.select { |vendor| vendor_status.vendor_outage?(vendor) } + end + end + + def vendor_status + @vendor_status ||= VendorStatus.new + end +end diff --git a/app/controllers/idv/phone_controller.rb b/app/controllers/idv/phone_controller.rb index e53ad15e7b2..dc18bbd8cef 100644 --- a/app/controllers/idv/phone_controller.rb +++ b/app/controllers/idv/phone_controller.rb @@ -49,7 +49,11 @@ def max_attempts_reached def redirect_to_next_step if phone_confirmation_required? - redirect_to idv_otp_delivery_method_url + if VendorStatus.new.all_phone_vendor_outage? + redirect_to vendor_outage_path(from: :idv_phone) + else + redirect_to idv_otp_delivery_method_url + end else redirect_to idv_review_url end diff --git a/app/controllers/users/phones_controller.rb b/app/controllers/users/phones_controller.rb index 4b83ae2b489..acf547bd741 100644 --- a/app/controllers/users/phones_controller.rb +++ b/app/controllers/users/phones_controller.rb @@ -3,6 +3,7 @@ class PhonesController < ReauthnRequiredController include PhoneConfirmation before_action :confirm_two_factor_authenticated + before_action :redirect_if_phone_vendor_outage def add user_session[:phone_id] = nil @@ -21,6 +22,11 @@ def create private + def redirect_if_phone_vendor_outage + return unless VendorStatus.new.all_phone_vendor_outage? + redirect_to vendor_outage_path(from: :users_phones) + end + def user_params params.require(:new_phone_form).permit( :phone, :international_code, diff --git a/app/controllers/users/two_factor_authentication_controller.rb b/app/controllers/users/two_factor_authentication_controller.rb index a2e9627f067..a3a991191b2 100644 --- a/app/controllers/users/two_factor_authentication_controller.rb +++ b/app/controllers/users/two_factor_authentication_controller.rb @@ -3,6 +3,7 @@ class TwoFactorAuthenticationController < ApplicationController include TwoFactorAuthenticatable before_action :check_remember_device_preference + before_action :redirect_to_vendor_outage_if_phone_only, only: [:show] def show service_provider_mfa_requirement_redirect || non_phone_redirect || phone_redirect || @@ -33,7 +34,7 @@ def non_phone_redirect end def phone_redirect - return unless phone_enabled? + return unless phone_enabled? && !VendorStatus.new.any_phone_vendor_outage? validate_otp_delivery_preference_and_send_code true end @@ -44,7 +45,15 @@ def backup_code_redirect end def redirect_on_nothing_enabled - redirect_to two_factor_options_url + # "Nothing enabled" can mean one of two things: + # 1. The user hasn't yet set up MFA, and should be redirected to setup path. + # 2. The user has set up MFA, but none of the redirect options are currently available (e.g. + # vendor outage), and they should be sent to the MFA selection path. + if MfaPolicy.new(current_user).two_factor_enabled? + redirect_to login_two_factor_options_path + else + redirect_to two_factor_options_url + end end def phone_enabled? @@ -117,6 +126,13 @@ def redirect_to_otp_verification_with_error ) end + def redirect_to_vendor_outage_if_phone_only + return unless VendorStatus.new.all_phone_vendor_outage? && + phone_enabled? && + !MfaPolicy.new(current_user).multiple_factors_enabled? + redirect_to vendor_outage_path(from: :two_factor_authentication) + end + def capture_analytics_for_exception(telephony_error) attributes = { error: telephony_error.class.to_s, diff --git a/app/controllers/vendor_outage_controller.rb b/app/controllers/vendor_outage_controller.rb index 55f20ff42ea..ab47989c85e 100644 --- a/app/controllers/vendor_outage_controller.rb +++ b/app/controllers/vendor_outage_controller.rb @@ -6,6 +6,19 @@ def show from_idv: session.delete(:vendor_outage_redirect_from_idv), ) @specific_message = vendor_status.outage_message + @show_gpo_option = from_idv_phone? && gpo_letter_available? vendor_status.track_event(analytics) end + + private + + def from_idv_phone? + params[:from] == 'idv_phone' + end + + def gpo_letter_available? + FeatureManagement.enable_gpo_verification? && + current_user && + !Idv::GpoMail.new(current_user).mail_spammed? + end end diff --git a/app/forms/new_phone_form.rb b/app/forms/new_phone_form.rb index f4789b727a7..ddfe3ac6f59 100644 --- a/app/forms/new_phone_form.rb +++ b/app/forms/new_phone_form.rb @@ -33,11 +33,11 @@ def submit(params) end def delivery_preference_sms? - true + !VendorStatus.new.vendor_outage?(:sms) end def delivery_preference_voice? - false + VendorStatus.new.vendor_outage?(:sms) end def already_has_phone? diff --git a/app/javascript/packs/form-steps-wait.jsx b/app/javascript/packs/form-steps-wait.jsx index aecfae17475..fc0f8bf404a 100644 --- a/app/javascript/packs/form-steps-wait.jsx +++ b/app/javascript/packs/form-steps-wait.jsx @@ -106,7 +106,8 @@ export class FormStepsWait { this.scheduleNextPollFetch(); } else { const message = getPageErrorMessage(dom); - if (message) { + const isSamePage = new URL(response.url).pathname === window.location.pathname; + if (message && isSamePage) { this.renderError(message); this.stopSpinner(); } else { diff --git a/app/presenters/two_factor_authentication/phone_selection_presenter.rb b/app/presenters/two_factor_authentication/phone_selection_presenter.rb index 4f581630180..c8f9dddcaa5 100644 --- a/app/presenters/two_factor_authentication/phone_selection_presenter.rb +++ b/app/presenters/two_factor_authentication/phone_selection_presenter.rb @@ -31,6 +31,10 @@ def security_level t('two_factor_authentication.two_factor_choice_options.less_secure_label') end + def disabled? + VendorStatus.new.all_phone_vendor_outage? + end + private def masked_number(number) diff --git a/app/presenters/two_factor_authentication/selection_presenter.rb b/app/presenters/two_factor_authentication/selection_presenter.rb index 4d9d1553e9d..8894bd716f5 100644 --- a/app/presenters/two_factor_authentication/selection_presenter.rb +++ b/app/presenters/two_factor_authentication/selection_presenter.rb @@ -26,6 +26,10 @@ def html_class '' end + def disabled? + false + end + private def option_mode diff --git a/app/presenters/two_factor_authentication/sms_selection_presenter.rb b/app/presenters/two_factor_authentication/sms_selection_presenter.rb index 41cdc209005..3b0c122c0f7 100644 --- a/app/presenters/two_factor_authentication/sms_selection_presenter.rb +++ b/app/presenters/two_factor_authentication/sms_selection_presenter.rb @@ -3,5 +3,9 @@ class SmsSelectionPresenter < PhoneSelectionPresenter def method :sms end + + def disabled? + VendorStatus.new.vendor_outage?(:sms) + end end end diff --git a/app/presenters/two_factor_authentication/voice_selection_presenter.rb b/app/presenters/two_factor_authentication/voice_selection_presenter.rb index d4ddb0ec883..6144f27f023 100644 --- a/app/presenters/two_factor_authentication/voice_selection_presenter.rb +++ b/app/presenters/two_factor_authentication/voice_selection_presenter.rb @@ -3,5 +3,9 @@ class VoiceSelectionPresenter < PhoneSelectionPresenter def method :voice end + + def disabled? + VendorStatus.new.vendor_outage?(:voice) + end end end diff --git a/app/presenters/two_factor_login_options_presenter.rb b/app/presenters/two_factor_login_options_presenter.rb index 35cc27d30fe..283d650bee4 100644 --- a/app/presenters/two_factor_login_options_presenter.rb +++ b/app/presenters/two_factor_login_options_presenter.rb @@ -71,6 +71,10 @@ def cancel_link end end + def first_enabled_option_index + options.find_index { |option| !option.disabled? } || 0 + end + private def account_reset_link diff --git a/app/services/vendor_status.rb b/app/services/vendor_status.rb index 7be45a7a3bb..b4ea9f07f08 100644 --- a/app/services/vendor_status.rb +++ b/app/services/vendor_status.rb @@ -1,4 +1,6 @@ class VendorStatus + include ActionView::Helpers::TranslationHelper + def initialize(from: nil, from_idv: nil, sp: nil) @from = from @from_idv = from_idv @@ -6,7 +8,8 @@ def initialize(from: nil, from_idv: nil, sp: nil) end IAL2_VENDORS = %i[acuant lexisnexis_instant_verify lexisnexis_trueid].freeze - ALL_VENDORS = (IAL2_VENDORS + %i[sms voice]).freeze + PHONE_VENDORS = %i[sms voice].freeze + ALL_VENDORS = (IAL2_VENDORS + PHONE_VENDORS).freeze def vendor_outage?(vendor) status = case vendor @@ -30,10 +33,22 @@ def any_vendor_outage?(vendors = ALL_VENDORS) vendors.any? { |vendor| vendor_outage?(vendor) } end + def all_vendor_outage?(vendors = ALL_VENDORS) + vendors.all? { |vendor| vendor_outage?(vendor) } + end + def any_ial2_vendor_outage? any_vendor_outage?(IAL2_VENDORS) end + def any_phone_vendor_outage? + any_vendor_outage?(PHONE_VENDORS) + end + + def all_phone_vendor_outage? + all_vendor_outage?(PHONE_VENDORS) + end + def from_idv? from_idv end @@ -46,16 +61,19 @@ def outage_message if any_ial2_vendor_outage? if from_idv? if sp - return I18n.t( - 'vendor_outage.idv_blocked.with_sp', - service_provider: sp.friendly_name, - ) + t('vendor_outage.blocked.idv.with_sp', service_provider: sp.friendly_name) else - return I18n.t('vendor_outage.idv_blocked.without_sp') + t('vendor_outage.blocked.idv.without_sp') end + else + t('vendor_outage.blocked.idv.generic') + end + elsif any_phone_vendor_outage? + if from_idv? + t('vendor_outage.blocked.phone.idv') + else + t('vendor_outage.blocked.phone.default') end - - return I18n.t('vendor_outage.idv_blocked.generic') end end diff --git a/app/views/idv/doc_auth/welcome.html.erb b/app/views/idv/doc_auth/welcome.html.erb index d0d1f2f28c8..5274156be89 100644 --- a/app/views/idv/doc_auth/welcome.html.erb +++ b/app/views/idv/doc_auth/welcome.html.erb @@ -1,5 +1,7 @@ <% title t('titles.doc_auth.verify') %> +<%= render(VendorOutageAlertComponent.new(vendors: [:sms, :voice], only_if_all: true, context: :idv)) %> + <% step = 0 %> <%= render 'shared/maintenance_window_alert' do %> diff --git a/app/views/idv/otp_delivery_method/new.html.erb b/app/views/idv/otp_delivery_method/new.html.erb index d052d637fb0..593e2ddc863 100644 --- a/app/views/idv/otp_delivery_method/new.html.erb +++ b/app/views/idv/otp_delivery_method/new.html.erb @@ -9,6 +9,8 @@ <% title t('titles.doc_auth.otp_delivery') %> +<%= render(VendorOutageAlertComponent.new(vendors: [:sms, :voice], context: :idv)) %> +
diff --git a/app/views/users/shared/_otp_delivery_preference_selection.html.erb b/app/views/users/shared/_otp_delivery_preference_selection.html.erb index 018ddefd050..74603902862 100644 --- a/app/views/users/shared/_otp_delivery_preference_selection.html.erb +++ b/app/views/users/shared/_otp_delivery_preference_selection.html.erb @@ -19,6 +19,7 @@ form_name_label, :sms, form_obj.delivery_preference_sms?, + disabled: VendorStatus.new.vendor_outage?(:sms), class: 'js-otp-delivery-preference usa-radio__input usa-radio__input--bordered', ) %> @@ -30,6 +31,7 @@ form_name_label, :voice, form_obj.delivery_preference_voice?, + disabled: VendorStatus.new.vendor_outage?(:voice), class: 'js-otp-delivery-preference usa-radio__input usa-radio__input--bordered', ) %> diff --git a/app/views/users/two_factor_authentication_setup/index.html.erb b/app/views/users/two_factor_authentication_setup/index.html.erb index c70c1d9fba1..9b5f5961cfe 100644 --- a/app/views/users/two_factor_authentication_setup/index.html.erb +++ b/app/views/users/two_factor_authentication_setup/index.html.erb @@ -1,5 +1,7 @@ <% title t('titles.two_factor_setup') %> +<%= render(VendorOutageAlertComponent.new(vendors: [:sms, :voice], context: :voice, only_if_all: true)) %> + <% if @presenter.icon %> <%= image_tag( asset_url(@presenter.icon), @@ -27,6 +29,7 @@ 'two_factor_options_form[selection]', option.type, false, + disabled: option.disabled?, class: 'usa-radio__input usa-radio__input--tile', ) %> <%= label_tag( @@ -37,7 +40,7 @@ <%= option.info %> <% if option.security_level && @presenter.show_security_level? %> - + <%= option.security_level %> <% end %> diff --git a/app/views/vendor_outage/show.html.erb b/app/views/vendor_outage/show.html.erb index abd63da811c..99317898f20 100644 --- a/app/views/vendor_outage/show.html.erb +++ b/app/views/vendor_outage/show.html.erb @@ -2,6 +2,10 @@ 'idv/shared/error', heading: t('vendor_outage.working'), options: [ + @show_gpo_option && { + text: t('idv.troubleshooting.options.verify_by_mail'), + url: idv_gpo_path, + }, { text: t('vendor_outage.get_updates_on_status_page'), url: StatusPage.base_url, @@ -12,11 +16,9 @@ url: MarketingSite.contact_url, new_tab: true, }, - ], + ].select(&:present?), ) do %> <%= @specific_message %> <% end %> -<%= render( - 'idv/doc_auth/back', - ) %> +<%= render('idv/doc_auth/back') %> diff --git a/config/locales/vendor_outage/en.yml b/config/locales/vendor_outage/en.yml index dbac4794573..4fa7ff9debc 100644 --- a/config/locales/vendor_outage/en.yml +++ b/config/locales/vendor_outage/en.yml @@ -1,16 +1,39 @@ --- en: vendor_outage: + alerts: + phone: + default: We cannot verify phones at this time. Please use another authentication + method if you have one, or try again later. + idv: We cannot verify phones at this time. Please try again later or verify your + address by mail instead. + sms: + default: We cannot send text messages (SMS) at this time. You can get a code by + phone call, or choose another authentication method if you have one. + idv: We cannot send text messages (SMS) at this time. You can get a code by + phone call, or verify your address by mail instead. + voice: + default: We cannot send phone calls at this time. You can get a code by text + message (SMS), or choose another authentication method if you have + one. + idv: We cannot send phone calls at this time. You can get a code by text message + (SMS), or verify your address by mail instead. + blocked: + idv: + generic: We are having technical difficulties on our end and cannot verify your + identity at this time. Please try again later. + with_sp: '%{service_provider} needs to make sure you are you — not someone + pretending to be you. Unfortunately, we are having technical + difficulties and cannot verify your identity at this time. Please try + again later.' + without_sp: The agency that you are trying to access needs to make sure you are + you — not someone pretending to be you. Unfortunately, we are having + technical difficulties and cannot verify your identity at this time. + Please try again later. + phone: + default: We cannot verify phones at this time. Please try again later. + idv: We cannot verify phones at this time. Please try again later or verify your + address by mail instead. + get_updates: Get updates get_updates_on_status_page: Get updates on our status page - idv_blocked: - generic: We are having technical difficulties on our end and cannot verify your - identity at this time. Please try again later. - with_sp: '%{service_provider} needs to make sure you are you — not someone - pretending to be you. Unfortunately, we are having technical - difficulties and cannot verify your identity at this time. Please try - again later.' - without_sp: The agency that you are trying to access needs to make sure you are - you — not someone pretending to be you. Unfortunately, we are having - technical difficulties and cannot verify your identity at this time. - Please try again later. working: We are working to resolve an error diff --git a/config/locales/vendor_outage/es.yml b/config/locales/vendor_outage/es.yml index afd5172d68a..094859a4cd5 100644 --- a/config/locales/vendor_outage/es.yml +++ b/config/locales/vendor_outage/es.yml @@ -1,17 +1,49 @@ --- es: vendor_outage: + alerts: + phone: + default: No podemos verificar teléfonos en estos momentos. Por favor, utilice + otro método de auntentificación, si cuenta con uno, o inténtelo + nuevamente más tarde. + idv: No podemos verificar teléfonos en estos momentos. Por favor, inténtelo + nuevamente más tarde o, en lugar de ello, verifique su dirección por + correo. + sms: + default: No podemos enviar mensajes de texto (SMS) en estos momentos. Puede + recibir un código por medio de una llamada telefónica o elegir otro + método de auntentificación, si cuenta con uno. + idv: No podemos enviar mensajes de texto (SMS) en estos momentos. Puede recibir + un código por medio de una llamada telefónica o, en su lugar, + verificar su dirección por correo. + voice: + default: No podemos enviar llamadas telefónicas en estos momentos. Puede recibir + un código por medio de un mensaje de texto (SMS) o elegir otro método + de auntentificación, si cuenta con uno. + idv: No podemos enviar llamadas telefónicas en estos momentos. Puede recibir un + código por medio de un mensaje de texto (SMS) o, en su lugar, + verificar su dirección por correo. + blocked: + idv: + generic: Debido a problemas técnicos por nuestra parte, no podemos verificar su + identidad en estos momentos. Por favor, inténtelo nuevamente más + tarde. + with_sp: '%{service_provider} necesita asegurarse de que es usted realmente y no + alguien que se hace pasar por usted. Lamentablemente, debido a + problemas técnicos por nuestra parte, tal vez no podamos verificar su + identidad en estos momentos. Por favor, inténtelo nuevamente más + tarde.' + without_sp: La agencia a la que está intentando acceder debe asegurarse de que + usted sea quien dice ser, y no alguien que se hace pasar por usted. + Lamentablemente, debido a problemas técnicos por nuestra parte, tal + vez no podamos verificar su identidad en estos momentos. Por favor, + inténtelo nuevamente más tarde. + phone: + default: No podemos verificar teléfonos en estos momentos. Por favor, inténtelo + nuevamente más tarde. + idv: No podemos verificar teléfonos en estos momentos. Por favor, inténtelo + nuevamente más tarde o, en lugar de ello, verifique su dirección por + correo. + get_updates: Obtenga actualizaciones get_updates_on_status_page: Reciba actualizaciones en nuestra página de estado - idv_blocked: - generic: Debido a problemas técnicos por nuestra parte, no podemos verificar su - identidad en estos momentos. Por favor, inténtelo nuevamente más tarde. - with_sp: '%{service_provider} necesita asegurarse de que es usted realmente y no - alguien que se hace pasar por usted. Lamentablemente, debido a problemas - técnicos por nuestra parte, tal vez no podamos verificar su identidad en - estos momentos. Por favor, inténtelo nuevamente más tarde.' - without_sp: La agencia a la que está intentando acceder debe asegurarse de que - usted sea quien dice ser, y no alguien que se hace pasar por usted. - Lamentablemente, debido a problemas técnicos por nuestra parte, tal vez - no podamos verificar su identidad en estos momentos. Por favor, - inténtelo nuevamente más tarde. working: Estamos trabajando para corregir un error diff --git a/config/locales/vendor_outage/fr.yml b/config/locales/vendor_outage/fr.yml index c7a8414a366..1c31082b146 100644 --- a/config/locales/vendor_outage/fr.yml +++ b/config/locales/vendor_outage/fr.yml @@ -1,17 +1,45 @@ --- fr: vendor_outage: + alerts: + phone: + default: Nous ne pouvons pas vérifier les téléphones pour le moment. Veuillez + utiliser une autre méthode d'authentification si vous en avez une, ou + réessayez plus tard. + idv: Nous ne pouvons pas vérifier les téléphones pour le moment. Veuillez + réessayer plus tard ou vérifier votre adresse par la poste. + sms: + default: Nous ne pouvons pas envoyer de messages texte (SMS) pour le moment. + Vous pouvez obtenir un code par appel téléphonique ou choisir une + autre méthode d'authentification si vous en avez un. + idv: Nous ne pouvons pas envoyer de messages texte (SMS) pour le moment. Vous + pouvez obtenir un code par téléphone ou vérifier votre adresse par la + poste. + voice: + default: Nous ne pouvons pas envoyer d'appels téléphoniques pour le moment. Vous + pouvez obtenir un code par message texte (SMS) ou choisir une autre + méthode d'authentification si vous en avez une. + idv: Nous ne pouvons pas envoyer d'appels téléphoniques pour le moment. Vous + pouvez obtenir un code par message texte (SMS), ou vérifier votre + adresse par la poste. + blocked: + idv: + generic: Nous rencontrons des difficultés techniques et ne pouvons pas vérifier + votre identité pour le moment. Veuillez réessayer plus tard. + with_sp: "%{service_provider} doit s'assurer que c'est bien vous — et non + quelqu'un qui se fait passer pour vous. Malheureusement, nous + rencontrons des difficultés techniques et ne pouvons pas vérifier + votre identité pour le moment. Veuillez réessayer plus tard." + without_sp: L’agence à laquelle vous essayez d’accéder doit s’assurer qu’il + s’agit bien de vous, et non de quelqu’un qui se fait passer pour vous. + Malheureusement, nous rencontrons des difficultés techniques et ne + pouvons pas vérifier votre identité pour le moment. Veuillez réessayer + plus tard. + phone: + default: Nous ne pouvons pas vérifier les téléphones pour le moment. Veuillez + réessayer plus tard. + idv: Nous ne pouvons pas vérifier les téléphones pour le moment. Veuillez + réessayer plus tard ou vérifier votre adresse par la poste. + get_updates: Obtenir des mises à jour get_updates_on_status_page: Obtenez des mises à jour sur notre page de statut - idv_blocked: - generic: Nous rencontrons des difficultés techniques et ne pouvons pas vérifier - votre identité pour le moment. Veuillez réessayer plus tard. - with_sp: "%{service_provider} doit s'assurer que c'est bien vous — et non - quelqu'un qui se fait passer pour vous. Malheureusement, nous - rencontrons des difficultés techniques et ne pouvons pas vérifier votre - identité pour le moment. Veuillez réessayer plus tard." - without_sp: L’agence à laquelle vous essayez d’accéder doit s’assurer qu’il - s’agit bien de vous, et non de quelqu’un qui se fait passer pour vous. - Malheureusement, nous rencontrons des difficultés techniques et ne - pouvons pas vérifier votre identité pour le moment. Veuillez réessayer - plus tard. working: "Nous travaillons à la résolution d'une erreur" diff --git a/spec/components/vendor_outage_alert_component_spec.rb b/spec/components/vendor_outage_alert_component_spec.rb new file mode 100644 index 00000000000..cc808b32bf1 --- /dev/null +++ b/spec/components/vendor_outage_alert_component_spec.rb @@ -0,0 +1,74 @@ +require 'rails_helper' + +RSpec.describe VendorOutageAlertComponent, type: :component do + let(:vendors) { [:sms, :voice] } + let(:context) { 'default' } + let(:only_if_all) { false } + + subject(:rendered) do + render_inline VendorOutageAlertComponent.new( + vendors: vendors, + context: context, + only_if_all: only_if_all, + ) + end + + context 'with no outage' do + before do + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).and_return(false) + end + + it 'renders nothing' do + expect(rendered.to_s).to be_empty + end + end + + context 'with outage' do + before do + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).with(:sms).and_return(true) + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).with(:voice).and_return(false) + end + + it 'renders error alert with status page url' do + expect(rendered).to have_content(t('vendor_outage.alerts.sms.default')) + expect(rendered).to have_link(t('vendor_outage.get_updates'), href: StatusPage.base_url) + end + + context 'with contextual message' do + subject(:context) { :idv } + + it 'renders error alert with contextualized message' do + expect(rendered).to have_content(t('vendor_outage.alerts.sms.idv')) + end + + context 'with unknown contextual message' do + subject(:context) { :unknown } + + it 'renders error alert with default message' do + expect(rendered).to have_content(t('vendor_outage.alerts.sms.default')) + end + end + end + + context 'constrained to only_if_all' do + let(:only_if_all) { true } + let(:all_outage) { false } + + before do + allow_any_instance_of(VendorStatus).to receive(:all_vendor_outage?).and_return(all_outage) + end + + it 'renders nothing' do + expect(rendered.to_s).to be_empty + end + + context 'with all outage' do + let(:all_outage) { true } + + it 'renders error alert' do + expect(rendered).to have_content(t('vendor_outage.alerts.phone.default')) + end + end + end + end +end diff --git a/spec/controllers/idv/phone_controller_spec.rb b/spec/controllers/idv/phone_controller_spec.rb index 832b8d88f97..782030ff682 100644 --- a/spec/controllers/idv/phone_controller_spec.rb +++ b/spec/controllers/idv/phone_controller_spec.rb @@ -186,14 +186,16 @@ end context 'when same as user phone' do - it 'redirects to review page and sets phone_confirmed_at' do + before do user = build( :user, :with_phone, with: { phone: good_phone, confirmed_at: Time.zone.now } ) stub_verify_steps_one_and_two(user) + end + it 'redirects to review page and sets phone_confirmed_at' do put :create, params: { idv_phone_form: { phone: good_phone } } expect(response).to redirect_to idv_phone_path @@ -211,17 +213,34 @@ expect(subject.idv_session.vendor_phone_confirmation).to eq true expect(subject.idv_session.user_phone_confirmation).to eq true end + + context 'with full vendor outage' do + before do + allow_any_instance_of(VendorStatus).to receive(:all_phone_vendor_outage?). + and_return(true) + end + + it 'redirects to review page' do + put :create, params: { idv_phone_form: { phone: good_phone } } + + expect(response).to redirect_to idv_phone_path + get :new + expect(response).to redirect_to idv_review_path + end + end end context 'when different phone from user phone' do - it 'redirects to otp page and does not set phone_confirmed_at' do + before do user = build( :user, :with_phone, with: { phone: '+1 (415) 555-0130', confirmed_at: Time.zone.now } ) stub_verify_steps_one_and_two(user) + end + it 'redirects to otp page and does not set phone_confirmed_at' do put :create, params: { idv_phone_form: { phone: good_phone } } expect(response).to redirect_to idv_phone_path @@ -231,6 +250,21 @@ expect(subject.idv_session.vendor_phone_confirmation).to eq true expect(subject.idv_session.user_phone_confirmation).to eq false end + + context 'with full vendor outage' do + before do + allow_any_instance_of(VendorStatus).to receive(:all_phone_vendor_outage?). + and_return(true) + end + + it 'redirects to vendor outage page' do + put :create, params: { idv_phone_form: { phone: good_phone } } + + expect(response).to redirect_to idv_phone_path + get :new + expect(response).to redirect_to vendor_outage_path(from: :idv_phone) + end + end end it 'tracks event with valid phone' do diff --git a/spec/controllers/users/phones_controller_spec.rb b/spec/controllers/users/phones_controller_spec.rb index 4f5457d911c..d673a85f5e4 100644 --- a/spec/controllers/users/phones_controller_spec.rb +++ b/spec/controllers/users/phones_controller_spec.rb @@ -3,19 +3,31 @@ describe Users::PhonesController do include Features::MailerHelper - context 'user adds phone' do - let(:user) { create(:user, :signed_up, with: { phone: '+1 (202) 555-1234' }) } - let(:new_phone) { '202-555-4321' } - before do - stub_sign_in(user) + let(:user) { create(:user, :signed_up, with: { phone: '+1 (202) 555-1234' }) } + before do + stub_sign_in(user) - stub_analytics - allow(@analytics).to receive(:track_event) - end + stub_analytics + allow(@analytics).to receive(:track_event) + end + context 'user adds phone' do it 'gives the user a form to enter a new phone number' do get :add + expect(response).to render_template(:add) end end + + context 'phone vendor outage' do + before do + allow_any_instance_of(VendorStatus).to receive(:all_phone_vendor_outage?).and_return(true) + end + + it 'redirects to outage page' do + get :add + + expect(response).to redirect_to vendor_outage_path(from: :users_phones) + end + end end diff --git a/spec/controllers/users/two_factor_authentication_controller_spec.rb b/spec/controllers/users/two_factor_authentication_controller_spec.rb index 77900d32631..3439a53b020 100644 --- a/spec/controllers/users/two_factor_authentication_controller_spec.rb +++ b/spec/controllers/users/two_factor_authentication_controller_spec.rb @@ -206,6 +206,20 @@ def index expect(response). to redirect_to login_two_factor_path(otp_delivery_preference: 'sms', reauthn: false) end + + context 'when no options are enabled and available for use' do + before do + allow_any_instance_of(VendorStatus).to receive(:any_phone_vendor_outage?).and_return(true) + end + + it 'redirects to mfa options page' do + stub_sign_in_before_2fa(create(:user, :with_phone, with: { phone: '+1 (703) 555-1212' })) + + get :show + + expect(response).to redirect_to login_two_factor_options_path + end + end end context 'when the user has not already set up 2FA' do @@ -217,6 +231,20 @@ def index end end + context 'when phone is sole configured mfa and full phone vendor outage' do + before do + allow_any_instance_of(VendorStatus).to receive(:all_phone_vendor_outage?).and_return(true) + end + + it 'redirects to vendor outage page' do + stub_sign_in_before_2fa(create(:user, :with_phone, with: { phone: '+1 (703) 555-1212' })) + + get :show + + expect(response).to redirect_to vendor_outage_path(from: :two_factor_authentication) + end + end + context 'when SP requires PIV/CAC' do let(:user) { create(:user, :signed_up) } diff --git a/spec/controllers/vendor_outage_controller_spec.rb b/spec/controllers/vendor_outage_controller_spec.rb index 1be584d7ae2..088b7b97af1 100644 --- a/spec/controllers/vendor_outage_controller_spec.rb +++ b/spec/controllers/vendor_outage_controller_spec.rb @@ -26,4 +26,24 @@ tracking_data, ) end + + it 'sets show_gpo_option view variable' do + get :show + + expect(assigns(:show_gpo_option)).to eq(false) + end + + context 'from idv phone' do + before { allow(controller).to receive(:from_idv_phone?).and_return(true) } + + context 'gpo letter available' do + before { allow(controller).to receive(:gpo_letter_available?).and_return(true) } + + it 'sets show_gpo_option as true' do + get :show + + expect(assigns(:show_gpo_option)).to eq(true) + end + end + end end diff --git a/spec/features/idv/vendor_outage_spec.rb b/spec/features/idv/vendor_outage_spec.rb index 189b693c1f3..853fc247011 100644 --- a/spec/features/idv/vendor_outage_spec.rb +++ b/spec/features/idv/vendor_outage_spec.rb @@ -22,7 +22,7 @@ click_submit_default expect(current_path).to eq vendor_outage_path expect(page).to have_content( - t('vendor_outage.idv_blocked.with_sp', service_provider: 'Test SP'), + t('vendor_outage.blocked.idv.with_sp', service_provider: 'Test SP'), ) end @@ -42,14 +42,14 @@ click_on t('forms.buttons.continue') expect(current_path).to eq vendor_outage_path - expect(page).to have_content(t('vendor_outage.idv_blocked.without_sp')) + expect(page).to have_content(t('vendor_outage.blocked.idv.without_sp')) end it 'prevents a user from creating an account' do visit_idp_from_sp_with_ial2(:oidc) click_link t('links.create_account') expect(current_path).to eq vendor_outage_path - expect(page).to have_content(t('vendor_outage.idv_blocked.generic')) + expect(page).to have_content(t('vendor_outage.blocked.idv.generic')) end end end diff --git a/spec/forms/new_phone_form_spec.rb b/spec/forms/new_phone_form_spec.rb index 2be9828bbb0..2f2d0b02c9f 100644 --- a/spec/forms/new_phone_form_spec.rb +++ b/spec/forms/new_phone_form_spec.rb @@ -319,6 +319,38 @@ end end + describe '#delivery_preference_sms?' do + it 'is true' do + expect(form.delivery_preference_sms?).to eq(true) + end + + context 'sms outage' do + before do + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).with(:sms).and_return(true) + end + + it 'is false' do + expect(form.delivery_preference_sms?).to eq(false) + end + end + end + + describe '#delivery_preference_voice?' do + it 'is false' do + expect(form.delivery_preference_voice?).to eq(false) + end + + context 'sms outage' do + before do + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).with(:sms).and_return(true) + end + + it 'is true' do + expect(form.delivery_preference_voice?).to eq(true) + end + end + end + describe '#redact' do it 'leaves in punctuation and spaces, but removes letters and numbers' do expect(form.send(:redact, '+11 (555) DEF-1234')).to eq('+## (###) XXX-####') diff --git a/spec/javascripts/packs/form-steps-wait-spec.js b/spec/javascripts/packs/form-steps-wait-spec.js index 3008fad1d1c..e495438ddc6 100644 --- a/spec/javascripts/packs/form-steps-wait-spec.js +++ b/spec/javascripts/packs/form-steps-wait-spec.js @@ -328,7 +328,15 @@ describe('FormStepsWait', () => { status: 200, redirected: true, url: redirect, - text: () => Promise.resolve(NON_POLL_PAGE_MARKUP), + text: () => + Promise.resolve( + `${NON_POLL_PAGE_MARKUP} + + + Error on redirected page is fine. + + `, + ), }); defineProperty(window, 'location', { value: { diff --git a/spec/presenters/two_factor_authentication/phone_selection_presenter_spec.rb b/spec/presenters/two_factor_authentication/phone_selection_presenter_spec.rb index f7f3579345c..39e97652dd2 100644 --- a/spec/presenters/two_factor_authentication/phone_selection_presenter_spec.rb +++ b/spec/presenters/two_factor_authentication/phone_selection_presenter_spec.rb @@ -36,4 +36,18 @@ end end end + + describe '#disabled?' do + let(:phone) { build(:phone_configuration, phone: '+1 888 867-5309') } + + it { expect(presenter.disabled?).to eq(false) } + + context 'all phone vendor outage' do + before do + allow_any_instance_of(VendorStatus).to receive(:all_phone_vendor_outage?).and_return(true) + end + + it { expect(presenter.disabled?).to eq(true) } + end + end end diff --git a/spec/presenters/two_factor_authentication/selection_presenter_spec.rb b/spec/presenters/two_factor_authentication/selection_presenter_spec.rb new file mode 100644 index 00000000000..076586a942d --- /dev/null +++ b/spec/presenters/two_factor_authentication/selection_presenter_spec.rb @@ -0,0 +1,9 @@ +require 'rails_helper' + +RSpec.describe TwoFactorAuthentication::SelectionPresenter do + subject(:presenter) { described_class.new } + + describe '#disabled?' do + it { expect(presenter.disabled?).to eq(false) } + end +end diff --git a/spec/presenters/two_factor_authentication/sms_selection_presenter_spec.rb b/spec/presenters/two_factor_authentication/sms_selection_presenter_spec.rb index 6fa41ca8b0d..da605f2da91 100644 --- a/spec/presenters/two_factor_authentication/sms_selection_presenter_spec.rb +++ b/spec/presenters/two_factor_authentication/sms_selection_presenter_spec.rb @@ -26,4 +26,18 @@ end end end + + describe '#disabled?' do + let(:phone) { build(:phone_configuration, phone: '+1 888 867-5309') } + + it { expect(subject.disabled?).to eq(false) } + + context 'sms vendor outage' do + before do + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).with(:sms).and_return(true) + end + + it { expect(subject.disabled?).to eq(true) } + end + end end diff --git a/spec/presenters/two_factor_authentication/voice_selection_presenter_spec.rb b/spec/presenters/two_factor_authentication/voice_selection_presenter_spec.rb index 08328ccfc7a..2d484d95635 100644 --- a/spec/presenters/two_factor_authentication/voice_selection_presenter_spec.rb +++ b/spec/presenters/two_factor_authentication/voice_selection_presenter_spec.rb @@ -26,4 +26,19 @@ end end end + + describe '#disabled?' do + let(:phone) { build(:phone_configuration, phone: '+1 888 867-5309') } + + it { expect(subject.disabled?).to eq(false) } + + context 'voice vendor outage' do + before do + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).with(:voice). + and_return(true) + end + + it { expect(subject.disabled?).to eq(true) } + end + end end diff --git a/spec/presenters/two_factor_login_options_presenter_spec.rb b/spec/presenters/two_factor_login_options_presenter_spec.rb index def9891e515..4e664fb878f 100644 --- a/spec/presenters/two_factor_login_options_presenter_spec.rb +++ b/spec/presenters/two_factor_login_options_presenter_spec.rb @@ -91,4 +91,34 @@ it { should eq account_path } end end + + describe '#first_enabled_option_index' do + subject(:index) { presenter.first_enabled_option_index } + + it 'returns first index' do + expect(index).to eq(0) + end + + context 'enabled options' do + before do + create(:phone_configuration, user: user, phone: '(202) 555-1111') + end + + it 'returns first enabled index' do + expect(index).to eq(0) + end + end + + context 'disabled options' do + before do + create(:phone_configuration, user: user, phone: '(202) 555-1111') + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).and_return(false) + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).with(:sms).and_return(true) + end + + it 'returns first enabled index' do + expect(index).to eq(1) + end + end + end end diff --git a/spec/services/vendor_status_spec.rb b/spec/services/vendor_status_spec.rb index d8ae19a2d4f..c11799cd425 100644 --- a/spec/services/vendor_status_spec.rb +++ b/spec/services/vendor_status_spec.rb @@ -56,7 +56,7 @@ let(:from) { SignUp::RegistrationsController::CREATE_ACCOUNT } it 'returns the correct message' do - expect(subject.outage_message).to eq I18n.t('vendor_outage.idv_blocked.generic') + expect(subject.outage_message).to eq I18n.t('vendor_outage.blocked.idv.generic') end end @@ -67,7 +67,7 @@ context 'no service_provider in session' do it 'returns the correct message' do expect(subject.outage_message).to eq( - I18n.t('vendor_outage.idv_blocked.without_sp'), + I18n.t('vendor_outage.blocked.idv.without_sp'), ) end end @@ -78,7 +78,7 @@ it 'returns the correct message tailored to the service provider' do expect(subject.outage_message).to eq( I18n.t( - 'vendor_outage.idv_blocked.with_sp', + 'vendor_outage.blocked.idv.with_sp', service_provider: sp.friendly_name, ), ) @@ -97,4 +97,88 @@ expect(subject.any_ial2_vendor_outage?).not_to be end end + + describe '#all_vendor_outage?' do + it { expect(subject.all_vendor_outage?).to eq(false) } + + context 'with outage on all vendors' do + before do + allow(vendor_status).to receive(:vendor_outage?).and_return(true) + end + + it { expect(subject.all_vendor_outage?).to eq(true) } + end + + context 'with parameters' do + let(:vendor) { :sms } + + it { expect(subject.all_vendor_outage?([vendor])).to eq(false) } + + context 'with outage on all vendors' do + before do + allow(vendor_status).to receive(:vendor_outage?).with(vendor).and_return(true) + end + + it { expect(subject.all_vendor_outage?([vendor])).to eq(true) } + end + end + end + + describe '#any_phone_vendor_outage?' do + it { expect(subject.any_phone_vendor_outage?).to eq(false) } + + context 'with outage on a phone vendor' do + before do + allow(vendor_status).to receive(:vendor_outage?).with(:sms).and_return(true) + end + + it { expect(subject.any_phone_vendor_outage?).to eq(true) } + end + end + + describe '#all_phone_vendor_outage?' do + it { expect(subject.all_phone_vendor_outage?).to eq(false) } + + context 'with outage on a phone vendor' do + before do + allow(vendor_status).to receive(:vendor_outage?).and_return(false) + allow(vendor_status).to receive(:vendor_outage?).with(:sms).and_return(true) + end + + it { expect(subject.all_phone_vendor_outage?).to eq(false) } + end + + context 'with outage on all phone vendors' do + before do + allow(vendor_status).to receive(:vendor_outage?).and_return(true) + end + + it { expect(subject.all_phone_vendor_outage?).to eq(true) } + end + end + + describe '#outage_message' do + subject(:outage_message) { vendor_status.outage_message } + + context 'phone vendor outage' do + before do + allow(vendor_status).to receive(:vendor_outage?).and_return(false) + VendorStatus::PHONE_VENDORS.each do |vendor| + allow(vendor_status).to receive(:vendor_outage?).with(vendor).and_return(true) + end + end + + it 'returns default phone outage message' do + expect(outage_message).to eq(t('vendor_outage.blocked.phone.default')) + end + + context 'from idv' do + let(:from_idv) { true } + + it 'returns idv phone outage message' do + expect(outage_message).to eq(t('vendor_outage.blocked.phone.idv')) + end + end + end + end end diff --git a/spec/views/idv/doc_auth/welcome.html.erb_spec.rb b/spec/views/idv/doc_auth/welcome.html.erb_spec.rb index 25093f8d471..1e01a9010c4 100644 --- a/spec/views/idv/doc_auth/welcome.html.erb_spec.rb +++ b/spec/views/idv/doc_auth/welcome.html.erb_spec.rb @@ -106,4 +106,16 @@ ) end end + + context 'phone vendor outage' do + before do + allow_any_instance_of(VendorStatus).to receive(:all_vendor_outage?).and_return(true) + end + + it 'renders alert banner' do + render template: 'idv/doc_auth/welcome' + + expect(rendered).to have_selector('.usa-alert.usa-alert--error') + end + end end diff --git a/spec/views/idv/otp_delivery_method/new.html.erb_spec.rb b/spec/views/idv/otp_delivery_method/new.html.erb_spec.rb index 17d376bba99..de831c6ec3d 100644 --- a/spec/views/idv/otp_delivery_method/new.html.erb_spec.rb +++ b/spec/views/idv/otp_delivery_method/new.html.erb_spec.rb @@ -28,4 +28,20 @@ expect(rendered).not_to have_link(t('idv.troubleshooting.options.verify_by_mail')) end end + + context 'phone vendor outage' do + before do + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).and_return(false) + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).with(:sms).and_return(true) + end + + it 'renders alert banner' do + expect(rendered).to have_selector('.usa-alert.usa-alert--error') + end + + it 'disables problematic vendor option' do + expect(rendered).to have_field('otp_delivery_preference', with: :voice, disabled: false) + expect(rendered).to have_field('otp_delivery_preference', with: :sms, disabled: true) + end + end end diff --git a/spec/views/phone_setup/index.html.erb_spec.rb b/spec/views/phone_setup/index.html.erb_spec.rb index 670727232c2..c8fd92fc000 100644 --- a/spec/views/phone_setup/index.html.erb_spec.rb +++ b/spec/views/phone_setup/index.html.erb_spec.rb @@ -52,4 +52,15 @@ end end end + + context 'phone vendor outage' do + before do + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).and_return(false) + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).with(:sms).and_return(true) + end + + it 'renders alert banner' do + expect(render).to have_selector('.usa-alert.usa-alert--error') + end + end end diff --git a/spec/views/two_factor_authentication/options/index.html.erb_spec.rb b/spec/views/two_factor_authentication/options/index.html.erb_spec.rb index 1fd851310b9..3a879654108 100644 --- a/spec/views/two_factor_authentication/options/index.html.erb_spec.rb +++ b/spec/views/two_factor_authentication/options/index.html.erb_spec.rb @@ -37,4 +37,31 @@ expect(rendered).to have_link(t('links.cancel_account_creation'), href: sign_up_cancel_path) end + + context 'phone vendor outage' do + before do + create(:phone_configuration, user: user, phone: '(202) 555-1111') + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).and_return(false) + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).with(:sms).and_return(true) + + render + end + + it 'renders alert banner' do + expect(rendered).to have_selector('.usa-alert.usa-alert--error') + end + + it 'disables problematic vendor option' do + expect(rendered).to have_checked_field( + 'two_factor_options_form[selection]', + with: :voice, + disabled: false, + ) + expect(rendered).to have_field( + 'two_factor_options_form[selection]', + with: :sms, + disabled: true, + ) + end + end end diff --git a/spec/views/users/phones/add.html.erb_spec.rb b/spec/views/users/phones/add.html.erb_spec.rb new file mode 100644 index 00000000000..aead0b19307 --- /dev/null +++ b/spec/views/users/phones/add.html.erb_spec.rb @@ -0,0 +1,23 @@ +require 'rails_helper' + +describe 'users/phones/add.html.erb' do + include Devise::Test::ControllerHelpers + + subject(:rendered) { render } + + before do + user = build_stubbed(:user) + @new_phone_form = NewPhoneForm.new(user) + end + + context 'phone vendor outage' do + before do + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).and_return(false) + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).with(:sms).and_return(true) + end + + it 'renders alert banner' do + expect(rendered).to have_selector('.usa-alert.usa-alert--error') + end + end +end diff --git a/spec/views/users/shared/_otp_delivery_preference_selection.html.erb_spec.rb b/spec/views/users/shared/_otp_delivery_preference_selection.html.erb_spec.rb new file mode 100644 index 00000000000..8bc86936219 --- /dev/null +++ b/spec/views/users/shared/_otp_delivery_preference_selection.html.erb_spec.rb @@ -0,0 +1,39 @@ +require 'rails_helper' + +describe 'users/shared/_otp_delivery_preference_selection.html.erb' do + let(:user) { build_stubbed(:user) } + + subject(:rendered) do + render 'users/shared/otp_delivery_preference_selection', form_obj: NewPhoneForm.new(user) + end + + it 'renders enabled sms option' do + expect(rendered).to have_field('new_phone_form_otp_delivery_preference_sms', disabled: false) + end + + context 'sms vendor outage' do + before do + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).and_return(false) + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).with(:sms).and_return(true) + end + + it 'renders disabled sms option' do + expect(rendered).to have_field('new_phone_form_otp_delivery_preference_sms', disabled: true) + end + end + + it 'renders enabled voice option' do + expect(rendered).to have_field('new_phone_form_otp_delivery_preference_voice', disabled: false) + end + + context 'voice vendor outage' do + before do + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).and_return(false) + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).with(:voice).and_return(true) + end + + it 'renders disabled voice option' do + expect(rendered).to have_field('new_phone_form_otp_delivery_preference_voice', disabled: true) + end + end +end diff --git a/spec/views/users/two_factor_authentication_setup/index.html.erb_spec.rb b/spec/views/users/two_factor_authentication_setup/index.html.erb_spec.rb new file mode 100644 index 00000000000..74c3d19477d --- /dev/null +++ b/spec/views/users/two_factor_authentication_setup/index.html.erb_spec.rb @@ -0,0 +1,51 @@ +require 'rails_helper' + +describe 'users/two_factor_authentication_setup/index.html.erb' do + include Devise::Test::ControllerHelpers + + subject(:rendered) { render } + + before do + user = build_stubbed(:user) + @presenter = TwoFactorOptionsPresenter.new(user_agent: '') + @two_factor_options_form = TwoFactorLoginOptionsForm.new(user) + end + + context 'all phone vendor outage' do + before do + allow_any_instance_of(VendorStatus).to receive(:all_vendor_outage?). + with(VendorStatus::PHONE_VENDORS).and_return(true) + end + + it 'renders alert banner' do + expect(rendered).to have_selector('.usa-alert.usa-alert--error') + end + + it 'disables phone option' do + expect(rendered).to have_field( + 'two_factor_options_form[selection]', + with: :phone, + disabled: true, + ) + end + end + + context 'single phone vendor outage' do + before do + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).and_return(false) + allow_any_instance_of(VendorStatus).to receive(:vendor_outage?).with(:sms).and_return(true) + end + + it 'does not render alert banner' do + expect(rendered).to_not have_selector('.usa-alert.usa-alert--error') + end + + it 'does not disable phone option' do + expect(rendered).to have_field( + 'two_factor_options_form[selection]', + with: :phone, + disabled: false, + ) + end + end +end diff --git a/spec/views/vendor_outage/show.html.erb_spec.rb b/spec/views/vendor_outage/show.html.erb_spec.rb new file mode 100644 index 00000000000..1a479a63f7e --- /dev/null +++ b/spec/views/vendor_outage/show.html.erb_spec.rb @@ -0,0 +1,23 @@ +require 'rails_helper' + +describe 'vendor_outage/show.html.erb' do + let(:show_gpo_option) { false } + + subject(:rendered) { render } + + before do + @show_gpo_option = show_gpo_option + end + + it 'does not render gpo option' do + expect(rendered).not_to have_link(t('idv.troubleshooting.options.verify_by_mail')) + end + + context 'gpo option shown' do + let(:show_gpo_option) { true } + + it 'renders gpo option' do + expect(rendered).to have_link(t('idv.troubleshooting.options.verify_by_mail')) + end + end +end
<%= @specific_message %>
Error on redirected page is fine.