From 390d185e4c574d22761d3e2bfcb0ae75cf5b0dfc Mon Sep 17 00:00:00 2001 From: David Corwin Date: Thu, 14 Jun 2018 13:24:32 -0700 Subject: [PATCH 01/26] Make the generic failure template a partial --- .../concerns/two_factor_authenticatable.rb | 2 +- app/controllers/users/sessions_controller.rb | 2 +- app/views/shared/failure.html.slim | 19 ------------------- 3 files changed, 2 insertions(+), 21 deletions(-) delete mode 100644 app/views/shared/failure.html.slim diff --git a/app/controllers/concerns/two_factor_authenticatable.rb b/app/controllers/concerns/two_factor_authenticatable.rb index c25a03acf6d..e57a3e28be9 100644 --- a/app/controllers/concerns/two_factor_authenticatable.rb +++ b/app/controllers/concerns/two_factor_authenticatable.rb @@ -40,7 +40,7 @@ def handle_max_attempts(type) decorated_user ) sign_out - render_full_width('shared/failure', locals: { presenter: presenter }) + render_full_width('shared/_failure', locals: { presenter: presenter }) end def require_current_password diff --git a/app/controllers/users/sessions_controller.rb b/app/controllers/users/sessions_controller.rb index 05557de1914..c288fd96554 100644 --- a/app/controllers/users/sessions_controller.rb +++ b/app/controllers/users/sessions_controller.rb @@ -74,7 +74,7 @@ def process_locked_out_user current_user.decorate ) sign_out - render_full_width('shared/failure', locals: { presenter: presenter }) + render_full_width('shared/_failure', locals: { presenter: presenter }) end def handle_valid_authentication diff --git a/app/views/shared/failure.html.slim b/app/views/shared/failure.html.slim deleted file mode 100644 index 5031207322d..00000000000 --- a/app/views/shared/failure.html.slim +++ /dev/null @@ -1,19 +0,0 @@ -- title presenter.title - -= image_tag(asset_url(presenter.state_icon), - alt: presenter.state_alt_text, width: 54) - -h1.h3.mb1.mt3.my0 = presenter.header - -p = presenter.description - -.col-2 - hr class="mt3 mb2 bw4 rounded border-#{presenter.state_color}" - -h2.h4.mb2.mt3.my0 = presenter.message - -- presenter.next_steps.each do |step| - p == step - -- if presenter.js - = nonced_javascript_tag presenter.js From 22c58622b5ccbf67f56bd6fcf22b9d734fc4e5bc Mon Sep 17 00:00:00 2001 From: David Corwin Date: Thu, 14 Jun 2018 15:02:45 -0700 Subject: [PATCH 02/26] Update jurisdiction fail screens --- .../idv/jurisdiction_controller.rb | 7 ++- .../idv/jurisdiction_failure_presenter.rb | 63 +++++++++++++++++++ app/views/idv/jurisdiction/show.html.slim | 22 ------- app/views/shared/_failure.html.slim | 19 ++++++ config/locales/idv/en.yml | 14 +++-- config/locales/idv/es.yml | 13 ++-- config/locales/idv/fr.yml | 13 ++-- .../idv/jurisdiction_controller_spec.rb | 16 +---- 8 files changed, 113 insertions(+), 54 deletions(-) create mode 100644 app/presenters/idv/jurisdiction_failure_presenter.rb delete mode 100644 app/views/idv/jurisdiction/show.html.slim create mode 100644 app/views/shared/_failure.html.slim diff --git a/app/controllers/idv/jurisdiction_controller.rb b/app/controllers/idv/jurisdiction_controller.rb index a1b515f0128..89f1b31e157 100644 --- a/app/controllers/idv/jurisdiction_controller.rb +++ b/app/controllers/idv/jurisdiction_controller.rb @@ -27,8 +27,11 @@ def create end def show - @state = user_session[:idv_jurisdiction] - @reason = params[:reason] + presenter = JurisdictionFailurePresenter.new( + reason: params[:reason], + jurisdiction: user_session[:idv_jurisdiction], + view_context: view_context) + render_full_width('shared/_failure', locals: { presenter: presenter }) end def jurisdiction_params diff --git a/app/presenters/idv/jurisdiction_failure_presenter.rb b/app/presenters/idv/jurisdiction_failure_presenter.rb new file mode 100644 index 00000000000..9e76dbf8a86 --- /dev/null +++ b/app/presenters/idv/jurisdiction_failure_presenter.rb @@ -0,0 +1,63 @@ +module Idv + class JurisdictionFailurePresenter < FailurePresenter + + attr_reader :jurisdiction, :reason, :view_context + + delegate :account_path, + :decorated_session, + :idv_jurisdiction_path, + :link_to, + :state_name_for_abbrev, + :t, + to: :view_context + + def initialize(jurisdiction:, reason:, view_context:) + super(:failure) + @jurisdiction = jurisdiction + @reason = reason + @view_context = view_context + end + + def title + t("idv.titles.#{reason}", **i18n_args) + end + + def header + t("idv.titles.#{reason}", **i18n_args) + end + + def description + t("idv.messages.jurisdiction.#{reason}", **i18n_args) + end + + def message + t('headings.lock_failure') + end + + def next_steps + [try_again_step, sp_step, profile_step].compact + end + + private + + def i18n_args + jurisdiction ? { state: state_name_for_abbrev(jurisdiction) } : {} + end + + def try_again_step + try_again_link = link_to(t('idv.messages.jurisdiction.try_again_link'), idv_jurisdiction_path) + t('idv.messages.jurisdiction.try_again', link: try_again_link) + end + + def sp_step + return unless decorated_session.sp_name + support_link = link_to(decorated_session.sp_name, decorated_session.sp_alert_learn_more) + t('idv.messages.jurisdiction.sp_support', link: support_link) + end + + def profile_step + profile_link = link_to(t('idv.messages.jurisdiction.profile_link'), account_path) + t('idv.messages.jurisdiction.profile', link: profile_link) + end + end +end diff --git a/app/views/idv/jurisdiction/show.html.slim b/app/views/idv/jurisdiction/show.html.slim deleted file mode 100644 index e884d0a42df..00000000000 --- a/app/views/idv/jurisdiction/show.html.slim +++ /dev/null @@ -1,22 +0,0 @@ -- i18n_args = @state ? { state: state_name_for_abbrev(@state) } : {} - -- title t("idv.titles.#{@reason}", **i18n_args) - -h1.h3.mb2.my0 = t("idv.titles.#{@reason}", **i18n_args) - -- if @state - p.mb1 = t("idv.messages.jurisdiction.#{@reason}", **i18n_args) - -.col-2 - hr.mt5.mb2.bw4.border-blue.rounded - -- if decorated_session.sp_name - - support_link = link_to(decorated_session.sp_name, decorated_session.sp_alert_learn_more) - p == t('idv.messages.jurisdiction.sp_support', link: support_link) - -- profile_link = link_to(t('idv.messages.jurisdiction.profile_link'), account_path) -p == t('idv.messages.jurisdiction.profile', link: profile_link) - -p.mt4 = link_to t('forms.buttons.back'), - decorated_session.cancel_link_url || account_path, - class: 'btn btn-primary btn-wide' diff --git a/app/views/shared/_failure.html.slim b/app/views/shared/_failure.html.slim new file mode 100644 index 00000000000..5031207322d --- /dev/null +++ b/app/views/shared/_failure.html.slim @@ -0,0 +1,19 @@ +- title presenter.title + += image_tag(asset_url(presenter.state_icon), + alt: presenter.state_alt_text, width: 54) + +h1.h3.mb1.mt3.my0 = presenter.header + +p = presenter.description + +.col-2 + hr class="mt3 mb2 bw4 rounded border-#{presenter.state_color}" + +h2.h4.mb2.mt3.my0 = presenter.message + +- presenter.next_steps.each do |step| + p == step + +- if presenter.js + = nonced_javascript_tag presenter.js diff --git a/config/locales/idv/en.yml b/config/locales/idv/en.yml index 162fd34617c..06f6286285a 100644 --- a/config/locales/idv/en.yml +++ b/config/locales/idv/en.yml @@ -81,15 +81,17 @@ en: help_center_html: Visit our Help Center to learn more about verifying your account. jurisdiction: + no_id: We're working hard to add more ways to verify your identity. + profile: To access your account in the future, you can %{link}. + profile_link: view your account here + sp_support: Visit %{link} for more information. + try_again: Make a mistake? You can %{link}. + try_again_link: try again + unsupported_jurisdiction: We're working hard to add more states and hope to + support %{state} soon. why: To verify your identity, you'll need information from your state-issued ID. where: Where was your driver's license, driver's permit, or state ID issued? - no_id: I don't have a state-issued ID - unsupported_jurisdiction: We're working hard to add more states and hope to - support %{state} soon. - sp_support: Visit %{link} for more information. - profile: To access your account in the future, you can %{link}. - profile_link: view your account here loading: Verifying your identity mail_sent: Your letter is on its way otp_delivery_method: diff --git a/config/locales/idv/es.yml b/config/locales/idv/es.yml index d557def97bc..329e205e53a 100644 --- a/config/locales/idv/es.yml +++ b/config/locales/idv/es.yml @@ -79,16 +79,19 @@ es: help_center_html: Visite nuestro Centro de Ayuda para obtener más información sobre la verificación de su cuenta. jurisdiction: - why: Para verificar su identidad, necesitará información de su identificación - emitida por el estado. - where: "¿Dónde se emitió su licencia de conducir, permiso de conducir o identificación - del estado?" - no_id: No tengo una identificación emitida por el estado + no_id: Estamos trabajando arduamente para agregar más formas de verificar + su identidad. profile: Para acceder a su cuenta en el futuro, puede %{link}. profile_link: mira tu cuenta aquí sp_support: Visita %{link} para obtener más información. + try_again: "¿Cometer un error? Puedes %{link}." + try_again_link: intentarlo de nuevo unsupported_jurisdiction: Estamos trabajando duro para agregar más estados y esperamos apoyar a %{state} pronto. + why: Para verificar su identidad, necesitará información de su identificación + emitida por el estado. + where: "¿Dónde se emitió su licencia de conducir, permiso de conducir o identificación + del estado?" loading: NOT TRANSLATED YET mail_sent: Su carta está en camino otp_delivery_method: diff --git a/config/locales/idv/fr.yml b/config/locales/idv/fr.yml index 2a61050ccd0..16ede99e835 100644 --- a/config/locales/idv/fr.yml +++ b/config/locales/idv/fr.yml @@ -85,16 +85,19 @@ fr: help_center_html: Visitez notre Centre d'aide pour en apprendre davantage sur la façon dont nous vérifions votre compte. jurisdiction: - why: Pour vérifier votre identité, vous aurez besoin d'informations provenant - de votre carte d'identité officielle. - where: Où a été délivré votre permis de conduire, votre permis de conduire - ou votre carte d'identité? - no_id: Je n'ai pas de carte d'identité officielle + no_id: Nous travaillons dur pour ajouter plus de moyens de vérifier votre + identité. profile: Pour accéder à votre compte dans le futur, vous pouvez %{link}. profile_link: voir votre compte ici sp_support: Visitez %{link} pour plus d'informations. + try_again: Faire une erreur? Vous pouvez %{link}. + try_again_link: réessayer unsupported_jurisdiction: Nous travaillons dur pour ajouter plus d'états et espérons pouvoir bientôt prendre en charge %{state}. + why: Pour vérifier votre identité, vous aurez besoin d'informations provenant + de votre carte d'identité officielle. + where: Où a été délivré votre permis de conduire, votre permis de conduire + ou votre carte d'identité? loading: NOT TRANSLATED YET mail_sent: Votre lettre est en route otp_delivery_method: diff --git a/spec/controllers/idv/jurisdiction_controller_spec.rb b/spec/controllers/idv/jurisdiction_controller_spec.rb index fcde8267922..84f1406eecd 100644 --- a/spec/controllers/idv/jurisdiction_controller_spec.rb +++ b/spec/controllers/idv/jurisdiction_controller_spec.rb @@ -76,22 +76,10 @@ controller.user_session[:idv_jurisdiction] = supported_jurisdiction end - it 'renders the `show` template' do + it 'renders the `_failure` template' do get :show, params: { reason: reason } - expect(response).to render_template(:show) - end - - it 'puts the jurisdiction from the user_session into @state' do - get :show, params: { reason: reason } - - expect(assigns(:state)).to eq(supported_jurisdiction) - end - - it 'puts the reason from the params in @reason' do - get :show, params: { reason: reason } - - expect(assigns(:reason)).to eq(reason) + expect(response).to render_template('shared/_failure') end end end From a4a746f1c18313af5913072ec4dd6d7301f1ee79 Mon Sep 17 00:00:00 2001 From: David Corwin Date: Thu, 14 Jun 2018 15:10:11 -0700 Subject: [PATCH 03/26] Fix translations; --- app/presenters/idv/jurisdiction_failure_presenter.rb | 2 +- config/locales/idv/en.yml | 7 ++++--- config/locales/idv/es.yml | 7 ++++--- config/locales/idv/fr.yml | 9 +++++---- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/app/presenters/idv/jurisdiction_failure_presenter.rb b/app/presenters/idv/jurisdiction_failure_presenter.rb index 9e76dbf8a86..1b698e5432f 100644 --- a/app/presenters/idv/jurisdiction_failure_presenter.rb +++ b/app/presenters/idv/jurisdiction_failure_presenter.rb @@ -27,7 +27,7 @@ def header end def description - t("idv.messages.jurisdiction.#{reason}", **i18n_args) + t("idv.messages.jurisdiction.#{reason}_failure", **i18n_args) end def message diff --git a/config/locales/idv/en.yml b/config/locales/idv/en.yml index 06f6286285a..95e23031361 100644 --- a/config/locales/idv/en.yml +++ b/config/locales/idv/en.yml @@ -81,14 +81,15 @@ en: help_center_html: Visit our Help Center to learn more about verifying your account. jurisdiction: - no_id: We're working hard to add more ways to verify your identity. + no_id: I don't have a state-issued ID + no_id_failure: We're working hard to add more ways to verify your identity. profile: To access your account in the future, you can %{link}. profile_link: view your account here sp_support: Visit %{link} for more information. try_again: Make a mistake? You can %{link}. try_again_link: try again - unsupported_jurisdiction: We're working hard to add more states and hope to - support %{state} soon. + unsupported_jurisdiction_failure: We're working hard to add more states and + hope to support %{state} soon. why: To verify your identity, you'll need information from your state-issued ID. where: Where was your driver's license, driver's permit, or state ID issued? diff --git a/config/locales/idv/es.yml b/config/locales/idv/es.yml index 329e205e53a..22aaa709e4a 100644 --- a/config/locales/idv/es.yml +++ b/config/locales/idv/es.yml @@ -79,15 +79,16 @@ es: help_center_html: Visite nuestro Centro de Ayuda para obtener más información sobre la verificación de su cuenta. jurisdiction: - no_id: Estamos trabajando arduamente para agregar más formas de verificar + no_id: No tengo una identificación emitida por el estado + no_id_failure: Estamos trabajando arduamente para agregar más formas de verificar su identidad. profile: Para acceder a su cuenta en el futuro, puede %{link}. profile_link: mira tu cuenta aquí sp_support: Visita %{link} para obtener más información. try_again: "¿Cometer un error? Puedes %{link}." try_again_link: intentarlo de nuevo - unsupported_jurisdiction: Estamos trabajando duro para agregar más estados - y esperamos apoyar a %{state} pronto. + unsupported_jurisdiction_failure: Estamos trabajando duro para agregar más + estados y esperamos apoyar a %{state} pronto. why: Para verificar su identidad, necesitará información de su identificación emitida por el estado. where: "¿Dónde se emitió su licencia de conducir, permiso de conducir o identificación diff --git a/config/locales/idv/fr.yml b/config/locales/idv/fr.yml index 16ede99e835..7f31c4748cd 100644 --- a/config/locales/idv/fr.yml +++ b/config/locales/idv/fr.yml @@ -85,15 +85,16 @@ fr: help_center_html: Visitez notre Centre d'aide pour en apprendre davantage sur la façon dont nous vérifions votre compte. jurisdiction: - no_id: Nous travaillons dur pour ajouter plus de moyens de vérifier votre - identité. + no_id: Je n'ai pas de carte d'identité officielle + no_id_failure: Nous travaillons dur pour ajouter plus de moyens de vérifier + votre identité. profile: Pour accéder à votre compte dans le futur, vous pouvez %{link}. profile_link: voir votre compte ici sp_support: Visitez %{link} pour plus d'informations. try_again: Faire une erreur? Vous pouvez %{link}. try_again_link: réessayer - unsupported_jurisdiction: Nous travaillons dur pour ajouter plus d'états et - espérons pouvoir bientôt prendre en charge %{state}. + unsupported_jurisdiction_failure: Nous travaillons dur pour ajouter plus d'états + et espérons pouvoir bientôt prendre en charge %{state}. why: Pour vérifier votre identité, vous aurez besoin d'informations provenant de votre carte d'identité officielle. where: Où a été délivré votre permis de conduire, votre permis de conduire From 02d76224ef50446c82ec372e7b8052f360a33959 Mon Sep 17 00:00:00 2001 From: David Corwin Date: Thu, 14 Jun 2018 15:41:37 -0700 Subject: [PATCH 04/26] Explicitly set translations as used --- config/i18n-tasks.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml index 23fdba5e82b..6b4300eea71 100644 --- a/config/i18n-tasks.yml +++ b/config/i18n-tasks.yml @@ -116,6 +116,7 @@ ignore_unused: - 'headings.piv_cac_setup.*' - 'titles.sign_up.*' - 'users.delete.bullet_2_loa*' + - 'idv.messages.jurisdiction.{no_id,unsupported_jurisdiction}_failure' # - 'simple_form.{yes,no}' # - 'simple_form.{placeholders,hints,labels}.*' # - 'simple_form.{error_notification,required}.:' From 377daccfb92c05afcf616037e462ef3a1f6a7415 Mon Sep 17 00:00:00 2001 From: David Corwin Date: Fri, 15 Jun 2018 10:23:16 -0700 Subject: [PATCH 05/26] Lint fixes --- app/controllers/idv/jurisdiction_controller.rb | 3 ++- app/presenters/idv/jurisdiction_failure_presenter.rb | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/controllers/idv/jurisdiction_controller.rb b/app/controllers/idv/jurisdiction_controller.rb index 89f1b31e157..5eb733b6fb9 100644 --- a/app/controllers/idv/jurisdiction_controller.rb +++ b/app/controllers/idv/jurisdiction_controller.rb @@ -30,7 +30,8 @@ def show presenter = JurisdictionFailurePresenter.new( reason: params[:reason], jurisdiction: user_session[:idv_jurisdiction], - view_context: view_context) + view_context: view_context + ) render_full_width('shared/_failure', locals: { presenter: presenter }) end diff --git a/app/presenters/idv/jurisdiction_failure_presenter.rb b/app/presenters/idv/jurisdiction_failure_presenter.rb index 1b698e5432f..db81973c6da 100644 --- a/app/presenters/idv/jurisdiction_failure_presenter.rb +++ b/app/presenters/idv/jurisdiction_failure_presenter.rb @@ -1,6 +1,5 @@ module Idv class JurisdictionFailurePresenter < FailurePresenter - attr_reader :jurisdiction, :reason, :view_context delegate :account_path, @@ -50,8 +49,8 @@ def try_again_step end def sp_step - return unless decorated_session.sp_name - support_link = link_to(decorated_session.sp_name, decorated_session.sp_alert_learn_more) + return unless (sp_name = decorated_session.sp_name) + support_link = link_to(sp_name, decorated_session.sp_alert_learn_more) t('idv.messages.jurisdiction.sp_support', link: support_link) end From c27fdf9edc162757c902e8a73765d5dcce635936 Mon Sep 17 00:00:00 2001 From: David Corwin Date: Fri, 15 Jun 2018 19:42:06 -0700 Subject: [PATCH 06/26] Update profile attempts fail screen --- app/controllers/idv/sessions_controller.rb | 6 ++ .../idv/profile_failure_presenter.rb | 57 +++++++++++++++++++ app/services/marketing_site.rb | 4 ++ app/views/shared/_failure.html.slim | 2 +- config/locales/idv/en.yml | 12 ++-- config/locales/idv/es.yml | 12 ++-- config/locales/idv/fr.yml | 12 ++-- 7 files changed, 89 insertions(+), 16 deletions(-) create mode 100644 app/presenters/idv/profile_failure_presenter.rb diff --git a/app/controllers/idv/sessions_controller.rb b/app/controllers/idv/sessions_controller.rb index d434f610094..60b9dfe7811 100644 --- a/app/controllers/idv/sessions_controller.rb +++ b/app/controllers/idv/sessions_controller.rb @@ -80,6 +80,12 @@ def process_failure flash[:error] = t('idv.errors.duplicate_ssn') redirect_to idv_session_dupe_url else + if step_attempts_exceeded? + presenter = ProfileFailurePresenter.new(decorated_session: decorated_session, + step_name: view_model.step_name, + view_context: view_context) + return render_full_width('shared/_failure', locals: { presenter: presenter }) + end render_failure @view_model.unsupported_jurisdiction_error(decorated_session.sp_name) render :new diff --git a/app/presenters/idv/profile_failure_presenter.rb b/app/presenters/idv/profile_failure_presenter.rb new file mode 100644 index 00000000000..f640a0addce --- /dev/null +++ b/app/presenters/idv/profile_failure_presenter.rb @@ -0,0 +1,57 @@ +module Idv + class ProfileFailurePresenter < FailurePresenter + attr_reader :decorated_session, :step_name, :view_context + + delegate :account_path, + :idv_session_path, + :link_to, + :t, + to: :view_context + + def initialize(decorated_session:, step_name:, view_context:) + super(:locked) + @decorated_session = decorated_session + @step_name = step_name + @view_context = view_context + end + + def title + t("idv.modal.#{step_name}.heading") + end + + def header + t("idv.modal.#{step_name}.heading") + end + + def description + t("idv.modal.#{step_name}.fail") + end + + def message + t('headings.lock_failure') + end + + def next_steps + [sp_step, help_step, profile_step].compact + end + + private + + def sp_step + return unless (sp_name = decorated_session.sp_name) + support_link = link_to(sp_name, decorated_session.sp_alert_learn_more) + t('idv.messages.jurisdiction.sp_support', link: support_link) + end + + def help_step + help_link = link_to(t('idv.messages.read_about_security_and_privacy.link'), + MarketingSite.help_privacy_and_security_url) + t('idv.messages.read_about_security_and_privacy.text', link: help_link) + end + + def profile_step + profile_link = link_to(t('idv.messages.jurisdiction.profile_link'), account_path) + t('idv.messages.jurisdiction.profile', link: profile_link) + end + end +end diff --git a/app/services/marketing_site.rb b/app/services/marketing_site.rb index fecfbe8faf6..35feb2a6111 100644 --- a/app/services/marketing_site.rb +++ b/app/services/marketing_site.rb @@ -25,4 +25,8 @@ def self.help_url def self.help_authentication_app_url URI.join(BASE_URL, locale_segment, 'help/signing-in/what-is-an-authentication-app/').to_s end + + def self.help_privacy_and_security_url + URI.join(BASE_URL, locale_segment, 'help', 'privacy-and-security', 'how-does-logingov-protect-my-data').to_s + end end diff --git a/app/views/shared/_failure.html.slim b/app/views/shared/_failure.html.slim index 5031207322d..9a60389a561 100644 --- a/app/views/shared/_failure.html.slim +++ b/app/views/shared/_failure.html.slim @@ -5,7 +5,7 @@ h1.h3.mb1.mt3.my0 = presenter.header -p = presenter.description +p == presenter.description .col-2 hr class="mt3 mb2 bw4 rounded border-#{presenter.state_color}" diff --git a/config/locales/idv/en.yml b/config/locales/idv/en.yml index 95e23031361..0b9486e97a9 100644 --- a/config/locales/idv/en.yml +++ b/config/locales/idv/en.yml @@ -107,6 +107,9 @@ en: - not a virtual phone (such as Google Voice or Skype) - not a pre-paid phone number - a U.S. number + read_about_security_and_privacy: + link: read about how login.gov keeps your information safe + text: You can %{link} on our help page. return_to_profile: "‹ Return to your login.gov profile" return_to_sp_html: You can now log into %{sp}. review: @@ -140,17 +143,16 @@ en: jobfail: Try again tomorrow warning: Try again phone: - fail: Your account is locked for 24 hours before you can - try to verify again. Check our Help section for more information about identity - verification. + fail: For your security, identity verification for your account is locked + for 24 hours. heading: We could not find records matching your phone information. jobfail: Something went wrong and we cannot process your request at this time. Please try again tomorrow. timeout: Our request to verify your information timed out. warning: Please check the information you entered. sessions: - fail: Your account is locked for 24 hours before you can - try to verify again. + fail: For your security, identity verification for your account is locked + for 24 hours. heading: We could not find records matching your personal information. jobfail: Something went wrong and we cannot process your request at this time. Please try again tomorrow. diff --git a/config/locales/idv/es.yml b/config/locales/idv/es.yml index 22aaa709e4a..8547cba5e76 100644 --- a/config/locales/idv/es.yml +++ b/config/locales/idv/es.yml @@ -107,6 +107,9 @@ es: - no es un teléfono virtual (como Google Voice o Skype) - no es un número de teléfono prepago - un número de EE. UU. + read_about_security_and_privacy: + link: leer sobre cómo login.gov mantiene su información segura + text: Puede %{link} en nuestra página de ayuda. return_to_profile: NOT TRANSLATED YET return_to_sp_html: NOT TRANSLATED YET review: @@ -142,17 +145,16 @@ es: jobfail: Inténtelo de nuevo mañana warning: Inténtelo de nuevo phone: - fail: Su cuenta está bloqueada por 24 horas antes de intentar - verificarla de nuevo. Consulte nuestra sección de Ayuda para obtener más - información sobre la verificación de identidad. + fail: Para su seguridad, la verificación de identidad de su cuenta está bloqueada + durante 24 horas. heading: No hemos podido encontrar registros que coincidan con la información de su teléfono. jobfail: NOT TRANSLATED YET timeout: NOT TRANSLATED YET warning: Compruebe la información que ingresó. sessions: - fail: Su cuenta está bloqueada por 24 horas antes de que - pueda intentar verificarla de nuevo. + fail: Para su seguridad, la verificación de identidad de su cuenta está bloqueada + durante 24 horas. heading: No hemos podido encontrar registros que coincidan con su información personal. jobfail: NOT TRANSLATED YET diff --git a/config/locales/idv/fr.yml b/config/locales/idv/fr.yml index 7f31c4748cd..4c869803039 100644 --- a/config/locales/idv/fr.yml +++ b/config/locales/idv/fr.yml @@ -114,6 +114,9 @@ fr: - pas un téléphone virtuel (comme Google Voice ou Skype) - pas un numéro de téléphone prépayé - un numéro américain + read_about_security_and_privacy: + link: lire comment login.gov protège vos informations + text: Vous pouvez %{link} sur notre page d'aide. return_to_profile: NOT TRANSLATED YET return_to_sp_html: NOT TRANSLATED YET review: @@ -152,17 +155,16 @@ fr: jobfail: Essayez à nouveau demain warning: Essayez à nouveau phone: - fail: Votre compte est strongverrouillé pour 24 heures/strong au cours desquelles - vous ne pourrez pas y accéder. Consultez notre Centre d'aide pour plus d'information - sur la vérification de votre identité. + fail: Pour votre sécurité, la vérification d'identité de votre compte est + verrouillée pendant 24 heures. heading: Nous ne trouvons pas de données qui correspondent à vos informations téléphoniques. jobfail: NOT TRANSLATED YET timeout: NOT TRANSLATED YET warning: Veuillez vérifier l'information que vous avez fournie. sessions: - fail: Votre compte est strongverrouillé pour 24 heures/strong au cours desquelles - vous ne pourrez pas y accéder. + fail: Pour votre sécurité, la vérification d'identité de votre compte est + verrouillée pendant 24 heures. heading: Nous ne trouvons pas de données qui correspondent à vos informations téléphoniques. jobfail: NOT TRANSLATED YET From 541a9550374d16ac30bd6bc7153a18081ba3bcc0 Mon Sep 17 00:00:00 2001 From: David Corwin Date: Fri, 15 Jun 2018 20:27:04 -0700 Subject: [PATCH 07/26] Update specs --- app/controllers/idv/sessions_controller.rb | 6 ++++-- app/presenters/idv/profile_failure_presenter.rb | 6 ++++-- spec/support/idv_examples/max_attempts.rb | 17 +++-------------- 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/app/controllers/idv/sessions_controller.rb b/app/controllers/idv/sessions_controller.rb index 60b9dfe7811..702c2c787a9 100644 --- a/app/controllers/idv/sessions_controller.rb +++ b/app/controllers/idv/sessions_controller.rb @@ -81,9 +81,11 @@ def process_failure redirect_to idv_session_dupe_url else if step_attempts_exceeded? - presenter = ProfileFailurePresenter.new(decorated_session: decorated_session, + presenter = ProfileFailurePresenter.new( + decorated_session: decorated_session, step_name: view_model.step_name, - view_context: view_context) + view_context: view_context + ) return render_full_width('shared/_failure', locals: { presenter: presenter }) end render_failure diff --git a/app/presenters/idv/profile_failure_presenter.rb b/app/presenters/idv/profile_failure_presenter.rb index f640a0addce..0f80b486351 100644 --- a/app/presenters/idv/profile_failure_presenter.rb +++ b/app/presenters/idv/profile_failure_presenter.rb @@ -44,8 +44,10 @@ def sp_step end def help_step - help_link = link_to(t('idv.messages.read_about_security_and_privacy.link'), - MarketingSite.help_privacy_and_security_url) + help_link = link_to( + t('idv.messages.read_about_security_and_privacy.link'), + MarketingSite.help_privacy_and_security_url + ) t('idv.messages.read_about_security_and_privacy.text', link: help_link) end diff --git a/spec/support/idv_examples/max_attempts.rb b/spec/support/idv_examples/max_attempts.rb index ffda4afb25f..46fac21337f 100644 --- a/spec/support/idv_examples/max_attempts.rb +++ b/spec/support/idv_examples/max_attempts.rb @@ -60,21 +60,10 @@ end end - scenario 'user sees failure flash message' do - expect(page).to have_css('.alert-error', text: t("idv.modal.#{step_locale_key}.heading")) - expect(page).to have_css( - '.alert-error', - text: strip_tags(t("idv.modal.#{step_locale_key}.fail")) - ) - end - context 'with js', :js do - scenario 'user sees the failure modal' do - expect(page).to have_css('.modal-fail', text: t("idv.modal.#{step_locale_key}.heading")) - expect(page).to have_css( - '.modal-fail', - text: strip_tags(t("idv.modal.#{step_locale_key}.fail")) - ) + scenario 'user sees the failure screen' do + expect(page).to have_content(t("idv.modal.#{step_locale_key}.heading")) + expect(page).to have_content(strip_tags(t("idv.modal.#{step_locale_key}.fail"))) end end end From 7ad119a2de0a6dc6164142c9c7ada4445f125079 Mon Sep 17 00:00:00 2001 From: David Corwin Date: Tue, 19 Jun 2018 07:52:40 -0700 Subject: [PATCH 08/26] WIP --- .../concerns/idv_failure_concern.rb | 63 +++++++++++-------- app/controllers/concerns/idv_session.rb | 2 - .../idv/jurisdiction_controller.rb | 6 +- app/controllers/idv/phone_controller.rb | 22 +++---- app/controllers/idv/sessions_controller.rb | 57 ++++++++--------- app/forms/idv/profile_form.rb | 9 +++ .../idv/attempt_failure_presenter.rb | 25 ++++++++ ...r.rb => max_attempts_failure_presenter.rb} | 2 +- app/presenters/idv/ssn_failure_presenter.rb | 55 ++++++++++++++++ app/presenters/idv/warning_presenter.rb | 49 +++++++++++++++ .../failed_verification_attempt.html.slim | 5 ++ app/views/idv/jurisdiction/new.html.slim | 2 +- app/views/idv/phone/new.html.slim | 6 +- app/views/idv/sessions/dupe.html.slim | 7 --- app/views/idv/sessions/new.html.slim | 15 +++-- app/views/idv/shared/other_failure.html.slim | 5 ++ config/locales/idv/en.yml | 4 ++ config/locales/idv/es.yml | 1 + config/locales/idv/fr.yml | 1 + config/routes.rb | 5 +- saml_20180619025351.txt | 0 spec/features/idv/steps/profile_step_spec.rb | 2 +- spec/support/idv_examples/fail_to_verify.rb | 62 ++++++------------ spec/support/idv_examples/failed_idv_job.rb | 55 +++++++--------- spec/support/idv_examples/max_attempts.rb | 4 +- 25 files changed, 291 insertions(+), 173 deletions(-) create mode 100644 app/presenters/idv/attempt_failure_presenter.rb rename app/presenters/idv/{profile_failure_presenter.rb => max_attempts_failure_presenter.rb} (96%) create mode 100644 app/presenters/idv/ssn_failure_presenter.rb create mode 100644 app/presenters/idv/warning_presenter.rb create mode 100644 app/views/idv/failure/failed_verification_attempt.html.slim delete mode 100644 app/views/idv/sessions/dupe.html.slim create mode 100644 app/views/idv/shared/other_failure.html.slim create mode 100644 saml_20180619025351.txt diff --git a/app/controllers/concerns/idv_failure_concern.rb b/app/controllers/concerns/idv_failure_concern.rb index b8e30cdb569..b465f2b5211 100644 --- a/app/controllers/concerns/idv_failure_concern.rb +++ b/app/controllers/concerns/idv_failure_concern.rb @@ -1,37 +1,50 @@ module IdvFailureConcern extend ActiveSupport::Concern - # rubocop:disable Metrics/MethodLength - def render_failure - if step_attempts_exceeded? - @view_model = view_model(error: 'fail') - flash_message(type: :error) + def idv_step_failure_reason + if idv_attempter.exceeded? || step_attempts_exceeded? + :fail elsif step.vendor_validator_job_failed? - @view_model = view_model(error: 'jobfail') - flash_message(type: :warning) - elsif form_valid_but_vendor_validation_failed? - @view_model = view_model(error: 'warning', timed_out: step.vendor_validation_timed_out?) - flash_message(type: :warning) - else - @view_model = view_model + :jobfail + elsif !step.vendor_validation_passed? + step.vendor_validation_timed_out? ? :timeout : :warning end end - # rubocop:enable Metrics/MethodLength - def form_valid_but_vendor_validation_failed? - idv_form.valid? && !step.vendor_validation_passed? + def render_idv_step_failure(step, reason) + case reason + when :fail + presenter = Idv::MaxAttemptsFailurePresenter.new( + decorated_session: decorated_session, + step_name: step, + view_context: view_context + ) + render_failure('shared/_failure', presenter) + when :jobfail, :timeout, :warning + presenter = Idv::WarningPresenter.new( + reason: reason, + remaining_attempts: remaining_step_attempts, + step_name: step, + view_context: view_context + ) + render_failure('idv/shared/other_failure', presenter) + end end - def flash_message(type:) - flash.now[type.to_sym] = @view_model.flash_message - end + # def form_valid_but_vendor_validation_failed? + # idv_form.valid? && !step.vendor_validation_passed? + # end + + # def view_model(error: nil, timed_out: nil) + # view_model_class.new( + # error: error, + # remaining_attempts: remaining_step_attempts, + # idv_form: idv_form, + # timed_out: timed_out + # ) + # end - def view_model(error: nil, timed_out: nil) - view_model_class.new( - error: error, - remaining_attempts: remaining_step_attempts, - idv_form: idv_form, - timed_out: timed_out - ) + def render_failure(template, presenter) + render_full_width(template, locals: { presenter: presenter }) end end diff --git a/app/controllers/concerns/idv_session.rb b/app/controllers/concerns/idv_session.rb index 83450691aaa..a2108073133 100644 --- a/app/controllers/concerns/idv_session.rb +++ b/app/controllers/concerns/idv_session.rb @@ -8,9 +8,7 @@ def confirm_idv_session_started def confirm_idv_attempts_allowed if idv_attempter.exceeded? - flash[:error] = t('idv.errors.hardfail') analytics.track_event(Analytics::IDV_MAX_ATTEMPTS_EXCEEDED, request_path: request.path) - redirect_to idv_fail_url elsif idv_attempter.reset_attempts? idv_attempter.reset end diff --git a/app/controllers/idv/jurisdiction_controller.rb b/app/controllers/idv/jurisdiction_controller.rb index 5eb733b6fb9..52bea61462e 100644 --- a/app/controllers/idv/jurisdiction_controller.rb +++ b/app/controllers/idv/jurisdiction_controller.rb @@ -22,12 +22,12 @@ def create # The only invalid result here is due to an unsupported jurisdiction # and if it is missing from the params, it will be stopped by # `strong_params`. - redirect_to idv_jurisdiction_fail_url(:unsupported_jurisdiction) + redirect_to idv_jurisdiction_failure_url(:unsupported_jurisdiction) end end - def show - presenter = JurisdictionFailurePresenter.new( + def failure + presenter = Idv::JurisdictionFailurePresenter.new( reason: params[:reason], jurisdiction: user_session[:idv_jurisdiction], view_context: view_context diff --git a/app/controllers/idv/phone_controller.rb b/app/controllers/idv/phone_controller.rb index 21583bcad8f..92625efde7c 100644 --- a/app/controllers/idv/phone_controller.rb +++ b/app/controllers/idv/phone_controller.rb @@ -8,19 +8,19 @@ class PhoneController < ApplicationController before_action :refresh_if_not_ready, only: [:show] def new - @view_model = view_model + @idv_form = idv_form analytics.track_event(Analytics::IDV_PHONE_RECORD_VISIT) end def create - result = idv_form.submit(step_params) + @idv_form = idv_form + result = @idv_form.submit(step_params) analytics.track_event(Analytics::IDV_PHONE_CONFIRMATION_FORM, result.to_h) if result.success? Idv::Job.submit(idv_session, [:address]) redirect_to idv_phone_result_url else - @view_model = view_model render :new end end @@ -30,12 +30,12 @@ def show analytics.track_event(Analytics::IDV_PHONE_CONFIRMATION_VENDOR, result.to_h) increment_step_attempts - if result.success? - redirect_to_next_step - else - render_failure - render :new - end + redirect_to_next_step and return if result.success? + redirect_to idv_phone_failure_url(idv_step_failure_reason) + end + + def failure + render_idv_step_failure(:phone, params[:reason].to_sym) end private @@ -64,10 +64,6 @@ def step ) end - def view_model_class - Idv::PhoneNew - end - def step_params params.require(:idv_phone_form).permit(:phone) end diff --git a/app/controllers/idv/sessions_controller.rb b/app/controllers/idv/sessions_controller.rb index 702c2c787a9..3d7c4d9eca6 100644 --- a/app/controllers/idv/sessions_controller.rb +++ b/app/controllers/idv/sessions_controller.rb @@ -15,20 +15,21 @@ class SessionsController < ApplicationController def new user_session[:context] = 'idv' - @view_model = view_model - @view_model.selected_state = user_session[:idv_jurisdiction] + @idv_form = idv_form + @selected_state = user_session[:idv_jurisdiction] analytics.track_event(Analytics::IDV_BASIC_INFO_VISIT) end def create - result = idv_form.submit(profile_params) + @idv_form = idv_form + result = @idv_form.submit(profile_params) analytics.track_event(Analytics::IDV_BASIC_INFO_SUBMITTED_FORM, result.to_h) if result.success? Idv::Job.submit(idv_session, %i[resolution state_id]) redirect_to idv_session_result_url else - process_failure + process_form_failure end end @@ -36,11 +37,14 @@ def show result = step.submit analytics.track_event(Analytics::IDV_BASIC_INFO_SUBMITTED_VENDOR, result.to_h) - if result.success? - process_success - else - process_failure - end + redirect_to idv_session_success_url and return if result.success? + redirect_to idv_session_failure_url(idv_step_failure_reason) + end + + def failure + reason = params[:reason].to_sym + render_dupe_ssn_failure and return if reason == :dupe_ssn + render_idv_step_failure(:sessions, reason) end def success; end @@ -71,31 +75,24 @@ def handle_idv_redirect redirect_to manage_personal_key_url end - def process_success - redirect_to idv_session_success_url + def process_form_failure + redirect_to idv_session_failure_url(:dupe_ssn) and return if @idv_form.duplicate_ssn? + if (sp_name = decorated_session.sp_name) && @idv_form.unsupported_jurisdiction? + @idv_form.add_sp_unsupported_jurisdiction_error(sp_name) + end + render :new end - def process_failure - if idv_form.duplicate_ssn? - flash[:error] = t('idv.errors.duplicate_ssn') - redirect_to idv_session_dupe_url - else - if step_attempts_exceeded? - presenter = ProfileFailurePresenter.new( - decorated_session: decorated_session, - step_name: view_model.step_name, - view_context: view_context - ) - return render_full_width('shared/_failure', locals: { presenter: presenter }) - end - render_failure - @view_model.unsupported_jurisdiction_error(decorated_session.sp_name) - render :new - end + def render_dupe_ssn_failure + presenter = Idv::SsnFailurePresenter.new( + decorated_session: decorated_session, + view_context: view_context + ) + render_failure('shared/_failure', presenter) end - def view_model_class - Idv::SessionsNew + def step_name + :sessions end def remaining_step_attempts diff --git a/app/forms/idv/profile_form.rb b/app/forms/idv/profile_form.rb index 64f171c39fc..634ec0905af 100644 --- a/app/forms/idv/profile_form.rb +++ b/app/forms/idv/profile_form.rb @@ -29,6 +29,15 @@ def submit(params) FormResponse.new(success: valid?, errors: errors.messages) end + def add_sp_unsupported_jurisdiction_error(sp_name) + error_message = [ + I18n.t('idv.errors.unsupported_jurisdiction'), + I18n.t('idv.errors.unsupported_jurisdiction_sp', sp_name: sp_name), + ].join(' ') + errors.delete(:state) + errors.add(:state, error_message) + end + private def consume_params(params) diff --git a/app/presenters/idv/attempt_failure_presenter.rb b/app/presenters/idv/attempt_failure_presenter.rb new file mode 100644 index 00000000000..5e9ede951ce --- /dev/null +++ b/app/presenters/idv/attempt_failure_presenter.rb @@ -0,0 +1,25 @@ +module Idv + class AttemptFailurePresenter < FailurePresenter + include ActionView::Helpers::TranslationHelper + + attr_reader :remaining_attempts, :step_name + + def initialize(remaining_attempts:, step_name:) + super(:warning) + @remaining_attempts = remaining_attempts + @step_name = step_name + end + + def title + t("idv.modal.#{step_name}.heading") + end + + def header + t("idv.modal.#{step_name}.heading") + end + + def description + t("idv.modal.#{step_name}.warning") + end + end +end diff --git a/app/presenters/idv/profile_failure_presenter.rb b/app/presenters/idv/max_attempts_failure_presenter.rb similarity index 96% rename from app/presenters/idv/profile_failure_presenter.rb rename to app/presenters/idv/max_attempts_failure_presenter.rb index 0f80b486351..0bf53a79ba9 100644 --- a/app/presenters/idv/profile_failure_presenter.rb +++ b/app/presenters/idv/max_attempts_failure_presenter.rb @@ -1,5 +1,5 @@ module Idv - class ProfileFailurePresenter < FailurePresenter + class MaxAttemptsFailurePresenter < FailurePresenter attr_reader :decorated_session, :step_name, :view_context delegate :account_path, diff --git a/app/presenters/idv/ssn_failure_presenter.rb b/app/presenters/idv/ssn_failure_presenter.rb new file mode 100644 index 00000000000..c5a1b206626 --- /dev/null +++ b/app/presenters/idv/ssn_failure_presenter.rb @@ -0,0 +1,55 @@ +module Idv + class SsnFailurePresenter < FailurePresenter + attr_reader :decorated_session, :view_context + + delegate :account_path, + :destroy_user_session_path, + :idv_session_path, + :link_to, + :t, + to: :view_context + + def initialize(decorated_session:, view_context:) + super(:failure) + @decorated_session = decorated_session + @view_context = view_context + end + + def title + t('idv.titles.dupe') + end + + def header + t('idv.titles.dupe') + end + + def description + t('idv.messages.dupe_ssn1') + end + + def message + t('headings.lock_failure') + end + + def next_steps + [try_again_step, sign_out_step, profile_step].compact + end + + private + + def try_again_step + link = link_to(t('idv.messages.jurisdiction.try_again_link'), idv_session_path) + t('idv.messages.jurisdiction.try_again', link: link) + end + + def sign_out_step + link = link_to(t('idv.messages.dupe_ssn2_link'), destroy_user_session_path) + t('idv.messages.dupe_ssn2_html', link: link) + end + + def profile_step + link = link_to(t('idv.messages.jurisdiction.profile_link'), account_path) + t('idv.messages.jurisdiction.profile', link: link) + end + end +end diff --git a/app/presenters/idv/warning_presenter.rb b/app/presenters/idv/warning_presenter.rb new file mode 100644 index 00000000000..df03dd98bd1 --- /dev/null +++ b/app/presenters/idv/warning_presenter.rb @@ -0,0 +1,49 @@ +module Idv + class WarningPresenter < FailurePresenter + attr_reader :reason, :remaining_attempts, :step_name, :view_context + + delegate :link_to, + :t, + to: :view_context + + + def initialize(reason:, remaining_attempts:, step_name:, view_context:) + super(:warning) + @reason = reason + @remaining_attempts = remaining_attempts + @step_name = step_name + @view_context = view_context + end + + def title + t("idv.modal.#{step_name}.heading") + end + + def header + t("idv.modal.#{step_name}.heading") + end + + def description + t("idv.modal.#{step_name}.#{reason}") + end + + def warning_message + reason == :warning ? warning : error + end + + def button_text + t("idv.modal.button.#{reason}") + end + + private + + def warning + t('idv.modal.attempts', count: remaining_attempts) + end + + def error + link = link_to(t('idv.modal.errors.link'), '') + t('idv.modal.errors.text', link: link) + end + end +end diff --git a/app/views/idv/failure/failed_verification_attempt.html.slim b/app/views/idv/failure/failed_verification_attempt.html.slim new file mode 100644 index 00000000000..1bd8e86687a --- /dev/null +++ b/app/views/idv/failure/failed_verification_attempt.html.slim @@ -0,0 +1,5 @@ += render 'shared/failure', presenter: presenter += render 'shared/modal_verification_warning', count: presenter.remaining_attempts + +.mt4 + = link_to t("idv.modal.button.warning"), idv_session_path, class: 'btn btn-primary' diff --git a/app/views/idv/jurisdiction/new.html.slim b/app/views/idv/jurisdiction/new.html.slim index a03462cae6e..67867a21d8b 100644 --- a/app/views/idv/jurisdiction/new.html.slim +++ b/app/views/idv/jurisdiction/new.html.slim @@ -17,7 +17,7 @@ p.mt4.mb0 id='jurisdiction-label' = t('idv.messages.jurisdiction.where') wrapper_html: { class: 'jurisdiction-select' }, input_html: { 'aria-labelledBy': 'jurisdiction-label' } - p = link_to t('idv.messages.jurisdiction.no_id'), idv_jurisdiction_fail_path(:no_id) + p = link_to t('idv.messages.jurisdiction.no_id'), idv_jurisdiction_failure_path(:no_id) .mt4 button type='submit' class='btn btn-primary btn-wide' = t('forms.buttons.continue') diff --git a/app/views/idv/phone/new.html.slim b/app/views/idv/phone/new.html.slim index 95d85af95e8..2afe431af84 100644 --- a/app/views/idv/phone/new.html.slim +++ b/app/views/idv/phone/new.html.slim @@ -1,4 +1,4 @@ -- title @view_model.title +- title t('idv.titles.phone') h1.h2.my0 = t('idv.titles.session.phone') @@ -9,7 +9,7 @@ ul.py1.m0 - t('idv.messages.phone.rules').each do |msg| li = msg -= simple_form_for(@view_model.idv_form, url: idv_phone_path, += simple_form_for(@idv_form, url: idv_phone_path, html: { autocomplete: 'off', method: :put, role: 'form', class: 'mt2' }) do |f| = f.label :phone, label: t('idv.form.phone'), class: 'bold' = f.input :phone, required: true, input_html: { class: 'us-phone' }, label: false, @@ -21,5 +21,3 @@ ul.py1.m0 = f.button :submit, t('forms.buttons.continue'), class: 'btn-wide mt6' = render 'shared/cancel', link: idv_cancel_path - -= render @view_model.modal_partial, view_model: @view_model diff --git a/app/views/idv/sessions/dupe.html.slim b/app/views/idv/sessions/dupe.html.slim deleted file mode 100644 index c2742a8764b..00000000000 --- a/app/views/idv/sessions/dupe.html.slim +++ /dev/null @@ -1,7 +0,0 @@ -- title t('idv.titles.dupe') - -h1.h3.my0 = t('idv.titles.dupe') - -p.mb1 = t('idv.messages.dupe_ssn1') -p.mb1 = t('idv.messages.dupe_ssn2_html', - link: link_to(t('idv.messages.dupe_ssn2_link'), destroy_user_session_path)) diff --git a/app/views/idv/sessions/new.html.slim b/app/views/idv/sessions/new.html.slim index e5c465ee9be..45f9897aadc 100644 --- a/app/views/idv/sessions/new.html.slim +++ b/app/views/idv/sessions/new.html.slim @@ -1,11 +1,11 @@ -- title @view_model.title +- title t('idv.titles.sessions') -h1.h3 = @view_model.title +h1.h3 = t('idv.titles.sessions') p = link_to t('links.access_help'), 'https://login.gov/help/privacy-and-security/how-does-logingov-protect-my-data/' -= simple_form_for(@view_model.idv_form, url: idv_session_path, += simple_form_for(@idv_form, url: idv_session_path, html: { autocomplete: 'off', method: :put, role: 'form' }) do |f| = f.error_notification fieldset.ml0.p0.border-none @@ -19,7 +19,7 @@ p = link_to t('links.access_help'), hint: t('idv.form.dob_hint'), hint_html: { id: 'dob-instructs', class: 'mb1' }, pattern: '(0[1-9]|1[012])/(0[1-9]|1[0-9]|2[0-9]|3[01])/[0-9]{4}', input_html: { class: 'dob', - value: @view_model.idv_form.dob, + value: @idv_form.dob, 'aria-describedby': 'dob-instructs' } .clearfix.mxn1 .sm-col.sm-col-6.px1 @@ -27,7 +27,7 @@ p = link_to t('links.access_help'), = f.input :ssn, as: :tel, label: t('idv.form.ssn_label_html'), required: true, pattern: '^\d{3}-?\d{2}-?\d{4}$', - input_html: { class: 'ssn', value: @view_model.idv_form.ssn } + input_html: { class: 'ssn', value: @idv_form.ssn } h2.h3 = t('idv.messages.sessions.id_information_subtitle') p = t('idv.messages.sessions.id_information_message') @@ -58,7 +58,7 @@ p = link_to t('links.access_help'), "data-error-message": t('idv.errors.unsupported_jurisdiction'), "data-error-message-sp": sp_error,\ } - - selected_state = @view_model.idv_form.state || @view_model.selected_state + - selected_state = @idv_form.state || @selected_state = f.input :state, collection: us_states_territories, label: t('idv.form.state'), required: true, input_html: data_attrs, selected: selected_state, @@ -69,9 +69,8 @@ p = link_to t('links.access_help'), = f.input :zipcode, as: :tel, label: t('idv.form.zipcode'), required: true, pattern: '(\d{5}([\-]\d{4})?)', - input_html: { class: 'zipcode', value: @view_model.idv_form.zipcode } + input_html: { class: 'zipcode', value: @idv_form.zipcode } .mt3 button type='submit' class='btn btn-primary btn-wide' = t('forms.buttons.continue') = render 'shared/cancel', link: idv_cancel_path -= render @view_model.modal_partial, view_model: @view_model diff --git a/app/views/idv/shared/other_failure.html.slim b/app/views/idv/shared/other_failure.html.slim new file mode 100644 index 00000000000..3315b730f46 --- /dev/null +++ b/app/views/idv/shared/other_failure.html.slim @@ -0,0 +1,5 @@ += render 'shared/failure', presenter: presenter +p == presenter.warning_message + +.mt4 + = link_to presenter.button_text, idv_session_path, class: 'btn btn-primary' diff --git a/config/locales/idv/en.yml b/config/locales/idv/en.yml index 0b9486e97a9..a8364ad7c96 100644 --- a/config/locales/idv/en.yml +++ b/config/locales/idv/en.yml @@ -141,7 +141,11 @@ en: button: fail: Okay jobfail: Try again tomorrow + timeout: Try again warning: Try again + errors: + link: please contact us + text: If you keep getting these errors, %{link}, or try again tomorrow. phone: fail: For your security, identity verification for your account is locked for 24 hours. diff --git a/config/locales/idv/es.yml b/config/locales/idv/es.yml index 8547cba5e76..71770f788d0 100644 --- a/config/locales/idv/es.yml +++ b/config/locales/idv/es.yml @@ -143,6 +143,7 @@ es: button: fail: Bueno jobfail: Inténtelo de nuevo mañana + timeout: Inténtelo de nuevo warning: Inténtelo de nuevo phone: fail: Para su seguridad, la verificación de identidad de su cuenta está bloqueada diff --git a/config/locales/idv/fr.yml b/config/locales/idv/fr.yml index 4c869803039..c6b372085a8 100644 --- a/config/locales/idv/fr.yml +++ b/config/locales/idv/fr.yml @@ -153,6 +153,7 @@ fr: button: fail: OK jobfail: Essayez à nouveau demain + timeout: Essayez à nouveau warning: Essayez à nouveau phone: fail: Pour votre sécurité, la vérification d'identité de votre compte est diff --git a/config/routes.rb b/config/routes.rb index 5e2c3f26cdc..96f1cca8a2e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -172,17 +172,18 @@ get '/phone' => 'phone#new' put '/phone' => 'phone#create' get '/phone/result' => 'phone#show' + get '/phone/failure/:reason' => 'phone#failure', as: :phone_failure get '/review' => 'review#new' put '/review' => 'review#create' get '/session' => 'sessions#new' put '/session' => 'sessions#create' get '/session/result' => 'sessions#show' get '/session/success' => 'sessions#success' + get '/session/failure/:reason' => 'sessions#failure', as: :session_failure delete '/session' => 'sessions#destroy' - get '/session/dupe' => 'sessions#dupe' get '/jurisdiction' => 'jurisdiction#new' post '/jurisdiction' => 'jurisdiction#create' - get '/jurisdiction/:reason' => 'jurisdiction#show', as: :jurisdiction_fail + get '/jurisdiction/failure/:reason' => 'jurisdiction#failure', as: :jurisdiction_failure end end diff --git a/saml_20180619025351.txt b/saml_20180619025351.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/spec/features/idv/steps/profile_step_spec.rb b/spec/features/idv/steps/profile_step_spec.rb index 847c4d977a2..f8a92becc1a 100644 --- a/spec/features/idv/steps/profile_step_spec.rb +++ b/spec/features/idv/steps/profile_step_spec.rb @@ -69,7 +69,7 @@ complete_idv_steps_before_profile_step fill_out_idv_form_fail(state: state) click_continue - click_button t('idv.modal.button.warning') + click_on t('idv.modal.button.warning') end it 'populates the state from the form' do diff --git a/spec/support/idv_examples/fail_to_verify.rb b/spec/support/idv_examples/fail_to_verify.rb index d12e7f6f31e..a9ac4245b5e 100644 --- a/spec/support/idv_examples/fail_to_verify.rb +++ b/spec/support/idv_examples/fail_to_verify.rb @@ -1,22 +1,18 @@ shared_examples 'fail to verify idv info' do |step| + let(:locale) { LinkLocaleResolver.locale } let(:step_locale_key) do return :sessions if step == :profile step end - before do - start_idv_from_sp - complete_idv_steps_before_step(step) - fill_out_idv_form_fail if step == :profile - fill_out_phone_form_fail if step == :phone - click_continue - end + shared_examples 'warning failure' do + it 'renders a warning failure screen and lets the user try again' do + expect(page).to have_current_path(idv_session_failure_path(:warning, locale: locale)) if step == :profile + expect(page).to have_current_path(idv_phone_failure_path(:warning, locale: locale)) if step == :phone + expect(page).to have_content t("idv.modal.#{step_locale_key}.heading") + expect(page).to have_content t("idv.modal.#{step_locale_key}.warning") - context 'without js' do - it 'renders a flash message and lets the user try again' do - expect_page_to_have_warning_message - expect(page).to have_current_path(idv_session_result_path) if step == :profile - expect(page).to have_current_path(idv_phone_result_path) if step == :phone + click_on t('idv.modal.button.warning') if step == :profile fill_out_idv_form_ok @@ -25,48 +21,26 @@ fill_out_phone_form_ok if step == :phone click_idv_continue - expect(page).to have_content(t('idv.titles.session.phone')) if step == :profile expect(page).to have_current_path(idv_phone_path) if step == :profile - expect(page).to have_content(t('idv.titles.otp_delivery_method')) if step == :phone expect(page).to have_current_path(idv_otp_delivery_method_path) if step == :phone - end - end - - context 'with js', :js do - it 'renders a modal and lets the user try again' do - expect_page_to_have_warning_modal - expect(page).to have_current_path(idv_session_result_path) if step == :profile - expect(page).to have_current_path(idv_phone_result_path) if step == :phone - - dismiss_warning_modal - if step == :profile - fill_out_idv_form_ok - click_idv_continue - end - fill_out_phone_form_ok if step == :phone - click_idv_continue - expect(page).to have_content(t('idv.titles.session.phone')) if step == :profile - expect(page).to have_current_path(idv_phone_path) if step == :profile expect(page).to have_content(t('idv.titles.otp_delivery_method')) if step == :phone - expect(page).to have_current_path(idv_otp_delivery_method_path) if step == :phone end end - def expect_page_to_have_warning_message - expect(page).to have_content t("idv.modal.#{step_locale_key}.heading") - expect(page).to have_content t("idv.modal.#{step_locale_key}.warning") + before do + start_idv_from_sp + complete_idv_steps_before_step(step) + fill_out_idv_form_fail if step == :profile + fill_out_phone_form_fail if step == :phone + click_continue end - def expect_page_to_have_warning_modal - expect(page).to have_css('.modal-warning', text: t("idv.modal.#{step_locale_key}.heading")) - expect(page).to have_css( - '.modal-warning', - text: strip_tags(t("idv.modal.#{step_locale_key}.warning")) - ) + context 'without js' do + it_behaves_like 'warning failure' end - def dismiss_warning_modal - click_button t('idv.modal.button.warning') + context 'with js', :js do + it_behaves_like 'warning failure' end end diff --git a/spec/support/idv_examples/failed_idv_job.rb b/spec/support/idv_examples/failed_idv_job.rb index e9efa5bb055..9f73f1e5fbe 100644 --- a/spec/support/idv_examples/failed_idv_job.rb +++ b/spec/support/idv_examples/failed_idv_job.rb @@ -1,4 +1,5 @@ shared_examples 'failed idv job' do |step| + let(:locale) { LinkLocaleResolver.locale } let(:idv_job_class) { Idv::ProoferJob } let(:step_locale_key) do return :sessions if step == :profile @@ -12,6 +13,15 @@ end context 'the job raises an error' do + shared_examples 'shows a warning' do + it 'renders a jobfail failure screen' do + expect(page).to have_current_path(idv_session_failure_path(:jobfail, locale: locale)) if step == :profile + expect(page).to have_current_path(idv_phone_failure_path(:jobfail, locale: locale)) if step == :phone + expect(page).to have_content t("idv.modal.#{step_locale_key}.heading") + expect(page).to have_content t("idv.modal.#{step_locale_key}.jobfail") + end + end + before do stub_idv_job_to_raise_error_in_background(idv_job_class) @@ -21,28 +31,24 @@ end context 'without js' do - it 'shows a warning' do - expect(page).to have_content t("idv.modal.#{step_locale_key}.heading") - expect(page).to have_content t("idv.modal.#{step_locale_key}.jobfail") - expect(page).to have_current_path(idv_session_result_path) if step == :profile - expect(page).to have_current_path(idv_phone_result_path) if step == :phone - end + it_behaves_like 'shows a warning' end context 'with js', :js do - it 'shows a modal' do - expect(page).to have_css('.modal-warning', text: t("idv.modal.#{step_locale_key}.heading")) - expect(page).to have_css( - '.modal-warning', - text: strip_tags(t("idv.modal.#{step_locale_key}.jobfail")) - ) - expect(page).to have_current_path(idv_session_result_path) if step == :profile - expect(page).to have_current_path(idv_phone_result_path) if step == :phone - end + it_behaves_like 'shows a warning' end end context 'the job times out' do + shared_examples 'shows a warning' do + it 'renders a timeout failure page' do + expect(page).to have_current_path(idv_session_failure_path(:timeout, locale: locale)) if step == :profile + expect(page).to have_current_path(idv_phone_failure_path(:timeout, locale: locale)) if step == :phone + expect(page).to have_content t("idv.modal.#{step_locale_key}.heading") + expect(page).to have_content t("idv.modal.#{step_locale_key}.timeout") + end + end + before do stub_idv_job_to_timeout_in_background(idv_job_class) @@ -61,24 +67,11 @@ end context 'without js' do - it 'shows a warning' do - expect(page).to have_content t("idv.modal.#{step_locale_key}.heading") - expect(page).to have_content t("idv.modal.#{step_locale_key}.timeout") - expect(page).to have_current_path(idv_session_result_path) if step == :profile - expect(page).to have_current_path(idv_phone_result_path) if step == :phone - end + it_behaves_like 'shows a warning' end - context 'with js' do - it 'shows a modal' do - expect(page).to have_css('.modal-warning', text: t("idv.modal.#{step_locale_key}.heading")) - expect(page).to have_css( - '.modal-warning', - text: strip_tags(t("idv.modal.#{step_locale_key}.timeout")) - ) - expect(page).to have_current_path(idv_session_result_path) if step == :profile - expect(page).to have_current_path(idv_phone_result_path) if step == :phone - end + context 'with js', :js do + it_behaves_like 'shows a warning' end end diff --git a/spec/support/idv_examples/max_attempts.rb b/spec/support/idv_examples/max_attempts.rb index 46fac21337f..c4f7d433f72 100644 --- a/spec/support/idv_examples/max_attempts.rb +++ b/spec/support/idv_examples/max_attempts.rb @@ -1,4 +1,5 @@ shared_examples 'verification step max attempts' do |step, sp| + let(:locale) { LinkLocaleResolver.locale } let(:user) { user_with_2fa } let(:step_locale_key) do return :sessions if step == :profile @@ -74,6 +75,7 @@ fill_out_idv_form_fail if step == :profile fill_out_phone_form_fail if step == :phone click_continue + click_on t('idv.modal.button.warning') end fill_out_idv_form_ok if step == :profile @@ -94,7 +96,7 @@ def perfom_maximum_allowed_idv_step_attempts max_attempts_less_one.times do yield click_idv_continue - click_button t('idv.modal.button.warning') if javascript_enabled? + click_on t('idv.modal.button.warning') end yield click_idv_continue From 530e8f43436d1dd24496a941ce8b1c824a67e03c Mon Sep 17 00:00:00 2001 From: David Corwin Date: Tue, 19 Jun 2018 15:04:48 -0700 Subject: [PATCH 09/26] A lot of cleanup --- .../concerns/idv_failure_concern.rb | 51 ++++------ app/controllers/concerns/idv_session.rb | 1 + app/controllers/concerns/idv_step_concern.rb | 3 +- .../idv/jurisdiction_controller.rb | 4 + app/controllers/idv/phone_controller.rb | 6 +- app/controllers/idv/sessions_controller.rb | 6 +- app/controllers/idv_controller.rb | 10 +- .../service_provider_session_decorator.rb | 4 - app/decorators/session_decorator.rb | 4 - app/presenters/idv/idv_failure_presenter.rb | 53 +++++++++++ app/presenters/idv/warning_presenter.rb | 9 +- app/services/marketing_site.rb | 8 +- app/view_models/idv/base.rb | 95 ------------------- app/view_models/idv/phone_new.rb | 7 -- app/view_models/idv/sessions_new.rb | 21 ---- app/views/idv/_hardfail4.html.slim | 11 --- app/views/idv/_no_sp_hardfail.html.slim | 9 -- app/views/idv/fail.html.slim | 11 --- .../failed_verification_attempt.html.slim | 5 - app/views/idv/shared/other_failure.html.slim | 2 +- app/views/shared/_modal_verification.slim | 12 --- .../_modal_verification_warning.html.slim | 1 - config/locales/idv/en.yml | 2 - config/locales/idv/es.yml | 5 +- config/locales/idv/fr.yml | 5 +- saml_20180620023548.txt | 0 .../concerns/idv_step_concern_spec.rb | 14 +-- .../idv/jurisdiction_controller_spec.rb | 6 +- spec/controllers/idv/phone_controller_spec.rb | 8 +- .../idv/sessions_controller_spec.rb | 22 ++--- spec/controllers/idv_controller_spec.rb | 2 +- ...service_provider_session_decorator_spec.rb | 6 -- spec/decorators/session_decorator_spec.rb | 6 -- spec/features/idv/state_id_data_spec.rb | 4 +- .../idv/steps/jurisdiction_step_spec.rb | 4 +- spec/features/idv/steps/phone_step_spec.rb | 2 +- spec/support/idv_examples/fail_to_verify.rb | 52 +++++----- spec/support/idv_examples/failed_idv_job.rb | 52 +++++----- spec/support/idv_examples/max_attempts.rb | 23 ++--- spec/view_models/idv/base_spec.rb | 72 -------------- spec/views/idv/_hardfail4.html.slim_spec.rb | 20 ---- .../idv/_no_sp_hardfail.html.slim_spec.rb | 12 --- spec/views/idv/fail.html.slim_spec.rb | 36 ------- 43 files changed, 199 insertions(+), 487 deletions(-) create mode 100644 app/presenters/idv/idv_failure_presenter.rb delete mode 100644 app/view_models/idv/base.rb delete mode 100644 app/view_models/idv/phone_new.rb delete mode 100644 app/view_models/idv/sessions_new.rb delete mode 100644 app/views/idv/_hardfail4.html.slim delete mode 100644 app/views/idv/_no_sp_hardfail.html.slim delete mode 100644 app/views/idv/fail.html.slim delete mode 100644 app/views/idv/failure/failed_verification_attempt.html.slim delete mode 100644 app/views/shared/_modal_verification.slim delete mode 100644 app/views/shared/_modal_verification_warning.html.slim create mode 100644 saml_20180620023548.txt delete mode 100644 spec/view_models/idv/base_spec.rb delete mode 100644 spec/views/idv/_hardfail4.html.slim_spec.rb delete mode 100644 spec/views/idv/_no_sp_hardfail.html.slim_spec.rb delete mode 100644 spec/views/idv/fail.html.slim_spec.rb diff --git a/app/controllers/concerns/idv_failure_concern.rb b/app/controllers/concerns/idv_failure_concern.rb index b465f2b5211..d5e9e29ecf2 100644 --- a/app/controllers/concerns/idv_failure_concern.rb +++ b/app/controllers/concerns/idv_failure_concern.rb @@ -12,39 +12,30 @@ def idv_step_failure_reason end def render_idv_step_failure(step, reason) - case reason - when :fail - presenter = Idv::MaxAttemptsFailurePresenter.new( - decorated_session: decorated_session, - step_name: step, - view_context: view_context - ) - render_failure('shared/_failure', presenter) - when :jobfail, :timeout, :warning - presenter = Idv::WarningPresenter.new( - reason: reason, - remaining_attempts: remaining_step_attempts, - step_name: step, - view_context: view_context - ) - render_failure('idv/shared/other_failure', presenter) - end + return render_failure('shared/_failure', failure_presenter(step)) if reason == :fail + render_failure('idv/shared/other_failure', warning_presenter(step, reason)) end - # def form_valid_but_vendor_validation_failed? - # idv_form.valid? && !step.vendor_validation_passed? - # end - - # def view_model(error: nil, timed_out: nil) - # view_model_class.new( - # error: error, - # remaining_attempts: remaining_step_attempts, - # idv_form: idv_form, - # timed_out: timed_out - # ) - # end - def render_failure(template, presenter) render_full_width(template, locals: { presenter: presenter }) end + + private + + def failure_presenter(step) + Idv::MaxAttemptsFailurePresenter.new( + decorated_session: decorated_session, + step_name: step, + view_context: view_context + ) + end + + def warning_presenter(step, reason) + Idv::WarningPresenter.new( + reason: reason, + remaining_attempts: remaining_step_attempts, + step_name: step, + view_context: view_context + ) + end end diff --git a/app/controllers/concerns/idv_session.rb b/app/controllers/concerns/idv_session.rb index a2108073133..c0d8abd1074 100644 --- a/app/controllers/concerns/idv_session.rb +++ b/app/controllers/concerns/idv_session.rb @@ -9,6 +9,7 @@ def confirm_idv_session_started def confirm_idv_attempts_allowed if idv_attempter.exceeded? analytics.track_event(Analytics::IDV_MAX_ATTEMPTS_EXCEEDED, request_path: request.path) + redirect_to failure_url(:fail) elsif idv_attempter.reset_attempts? idv_attempter.reset end diff --git a/app/controllers/concerns/idv_step_concern.rb b/app/controllers/concerns/idv_step_concern.rb index ea31f59a065..7a4a0231794 100644 --- a/app/controllers/concerns/idv_step_concern.rb +++ b/app/controllers/concerns/idv_step_concern.rb @@ -28,7 +28,6 @@ def confirm_step_allowed end def redirect_to_fail_url - flash[:max_attempts_exceeded] = true - redirect_to idv_fail_url + redirect_to failure_url(:fail) end end diff --git a/app/controllers/idv/jurisdiction_controller.rb b/app/controllers/idv/jurisdiction_controller.rb index 52bea61462e..20ce7f5b6cd 100644 --- a/app/controllers/idv/jurisdiction_controller.rb +++ b/app/controllers/idv/jurisdiction_controller.rb @@ -44,5 +44,9 @@ def jurisdiction_params def set_jurisdiction_form @jurisdiction_form ||= Idv::JurisdictionForm.new end + + def failure_url(reason) + idv_jurisdiction_failure_url(reason) + end end end diff --git a/app/controllers/idv/phone_controller.rb b/app/controllers/idv/phone_controller.rb index 92625efde7c..57da1da540e 100644 --- a/app/controllers/idv/phone_controller.rb +++ b/app/controllers/idv/phone_controller.rb @@ -4,7 +4,7 @@ class PhoneController < ApplicationController include IdvFailureConcern before_action :confirm_step_needed - before_action :confirm_step_allowed + before_action :confirm_step_allowed, except: [:failure] before_action :refresh_if_not_ready, only: [:show] def new @@ -75,5 +75,9 @@ def confirm_step_needed def idv_form @_idv_form ||= Idv::PhoneForm.new(idv_session.params, current_user) end + + def failure_url(reason) + idv_phone_failure_url(reason) + end end end diff --git a/app/controllers/idv/sessions_controller.rb b/app/controllers/idv/sessions_controller.rb index 3d7c4d9eca6..c6fc075177d 100644 --- a/app/controllers/idv/sessions_controller.rb +++ b/app/controllers/idv/sessions_controller.rb @@ -5,7 +5,7 @@ class SessionsController < ApplicationController include PersonalKeyConcern before_action :confirm_two_factor_authenticated, except: [:destroy] - before_action :confirm_idv_attempts_allowed, except: %i[destroy success] + before_action :confirm_idv_attempts_allowed, except: %i[destroy success failure] before_action :confirm_idv_needed before_action :confirm_step_needed, except: %i[destroy success] before_action :initialize_idv_session, only: [:create] @@ -112,5 +112,9 @@ def initialize_idv_session def profile_params params.require(:profile).permit(Idv::ProfileForm::PROFILE_ATTRIBUTES) end + + def failure_url(reason) + idv_session_failure_url(reason) + end end end diff --git a/app/controllers/idv_controller.rb b/app/controllers/idv_controller.rb index 2ac95f97270..a22bba6150c 100644 --- a/app/controllers/idv_controller.rb +++ b/app/controllers/idv_controller.rb @@ -26,7 +26,11 @@ def activated def cancel; end def fail - redirect_to idv_url unless ok_to_fail? + redirect_to idv_url and return unless idv_attempter.exceeded? + presenter = Idv::IdvFailurePresenter.new( + view_context: view_context + ) + render_full_width('shared/_failure', locals: { presenter: presenter }) end private @@ -40,8 +44,4 @@ def profile_needs_reactivation? def active_profile? current_user.active_profile.present? end - - def ok_to_fail? - idv_attempter.exceeded? || flash[:max_attempts_exceeded] - end end diff --git a/app/decorators/service_provider_session_decorator.rb b/app/decorators/service_provider_session_decorator.rb index 366a5353906..47bad4a5636 100644 --- a/app/decorators/service_provider_session_decorator.rb +++ b/app/decorators/service_provider_session_decorator.rb @@ -69,10 +69,6 @@ def verification_method_choice I18n.t('idv.messages.select_verification_with_sp', sp_name: sp_name) end - def idv_hardfail4_partial - 'idv/hardfail4' - end - def requested_attributes sp_session[:requested_attributes].sort end diff --git a/app/decorators/session_decorator.rb b/app/decorators/session_decorator.rb index 95e1dece91b..3f227672faf 100644 --- a/app/decorators/session_decorator.rb +++ b/app/decorators/session_decorator.rb @@ -27,10 +27,6 @@ def verification_method_choice I18n.t('idv.messages.select_verification_without_sp') end - def idv_hardfail4_partial - 'idv/no_sp_hardfail' - end - def cancel_link_url view_context.root_url end diff --git a/app/presenters/idv/idv_failure_presenter.rb b/app/presenters/idv/idv_failure_presenter.rb new file mode 100644 index 00000000000..e5e1c3767cf --- /dev/null +++ b/app/presenters/idv/idv_failure_presenter.rb @@ -0,0 +1,53 @@ +module Idv + class IdvFailurePresenter < FailurePresenter + attr_reader :view_context + + delegate :account_path, + :decorated_session, + :link_to, + :t, + to: :view_context + + def initialize(view_context:) + super(:locked) + @view_context = view_context + end + + def title + t('idv.titles.hardfail', app: APP_NAME) + end + + def header + t('idv.titles.hardfail', app: APP_NAME) + end + + def description + t('idv.messages.hardfail', hours: Figaro.env.idv_attempt_window_in_hours) + end + + def message + t('headings.lock_failure') + end + + def next_steps + [help_step, sp_step, profile_step].compact + end + + private + + def help_step + link_to t('idv.messages.help_center_html'), MarketingSite.help_url + end + + def sp_step + return unless (sp_name = decorated_session.sp_name) + link = link_to(sp_name, decorated_session.sp_alert_learn_more) + t('idv.messages.jurisdiction.sp_support', link: link) + end + + def profile_step + link = link_to(t('idv.messages.jurisdiction.profile_link'), account_path) + t('idv.messages.jurisdiction.profile', link: link) + end + end +end diff --git a/app/presenters/idv/warning_presenter.rb b/app/presenters/idv/warning_presenter.rb index df03dd98bd1..2d60e1d561f 100644 --- a/app/presenters/idv/warning_presenter.rb +++ b/app/presenters/idv/warning_presenter.rb @@ -2,11 +2,12 @@ module Idv class WarningPresenter < FailurePresenter attr_reader :reason, :remaining_attempts, :step_name, :view_context - delegate :link_to, + delegate :idv_phone_path, + :idv_session_path, + :link_to, :t, to: :view_context - def initialize(reason:, remaining_attempts:, step_name:, view_context:) super(:warning) @reason = reason @@ -35,6 +36,10 @@ def button_text t("idv.modal.button.#{reason}") end + def button_path + step_name == :sessions ? idv_session_path : idv_phone_path + end + private def warning diff --git a/app/services/marketing_site.rb b/app/services/marketing_site.rb index 35feb2a6111..5b763741968 100644 --- a/app/services/marketing_site.rb +++ b/app/services/marketing_site.rb @@ -27,6 +27,12 @@ def self.help_authentication_app_url end def self.help_privacy_and_security_url - URI.join(BASE_URL, locale_segment, 'help', 'privacy-and-security', 'how-does-logingov-protect-my-data').to_s + URI.join( + BASE_URL, + locale_segment, + 'help', + 'privacy-and-security', + 'how-does-logingov-protect-my-data' + ).to_s end end diff --git a/app/view_models/idv/base.rb b/app/view_models/idv/base.rb deleted file mode 100644 index ff779335bef..00000000000 --- a/app/view_models/idv/base.rb +++ /dev/null @@ -1,95 +0,0 @@ -module Idv - class Base - include Rails.application.routes.url_helpers - - def initialize(error: nil, remaining_attempts:, idv_form:, timed_out: nil) - @error = error - @remaining_attempts = remaining_attempts - @idv_form = idv_form - @timed_out = timed_out - end - - attr_reader :error, :remaining_attempts, :idv_form - - def title - I18n.t("idv.titles.#{step_name}") - end - - def modal_partial - if error.present? - 'shared/modal_verification' - else - 'shared/null' - end - end - - def warning_partial - if %w[warning jobfail].include?(error) - 'shared/modal_verification_warning' - else - 'shared/null' - end - end - - def message - return html_paragraph(text: I18n.t("idv.modal.#{step_name}.timeout")) if timed_out? - html_paragraph(text: I18n.t("idv.modal.#{step_name}.#{error}")) if error - end - - def button - if %w[warning jobfail].include?(error) - helper.content_tag( - :button, button_link_text, id: 'js-close-modal', class: button_css_classes - ) - else - helper.link_to button_link_text, idv_fail_path, class: button_css_classes - end - end - - def flash_message - flash_heading = html_paragraph( - text: I18n.t("idv.modal.#{step_name}.heading"), css_class: 'mb2 fs-20p' - ) - flash_body = message - flash_heading + flash_body + attempts - end - - def modal_class_name - return 'modal-warning' if %w[warning jobfail].include?(error) - "modal-#{error}" - end - - private - - def timed_out? - @timed_out - end - - def button_link_text - I18n.t("idv.modal.button.#{error}") - end - - def button_css_classes - 'btn btn-wide px2 py1 rounded-lg border bw2' - end - - def attempts - if %w[warning jobfail].include?(error) - html_paragraph(text: I18n.t('idv.modal.attempts', count: remaining_attempts)) - else - '' - end - end - - # rubocop:disable Rails/OutputSafety - def html_paragraph(text:, css_class: '') - html = helper.safe_join([text.html_safe]) - helper.content_tag(:p, html, class: css_class) - end - # rubocop:enable Rails/OutputSafety - - def helper - ActionController::Base.helpers - end - end -end diff --git a/app/view_models/idv/phone_new.rb b/app/view_models/idv/phone_new.rb deleted file mode 100644 index bff92046ffe..00000000000 --- a/app/view_models/idv/phone_new.rb +++ /dev/null @@ -1,7 +0,0 @@ -module Idv - class PhoneNew < Idv::Base - def step_name - :phone - end - end -end diff --git a/app/view_models/idv/sessions_new.rb b/app/view_models/idv/sessions_new.rb deleted file mode 100644 index 4663fc1c981..00000000000 --- a/app/view_models/idv/sessions_new.rb +++ /dev/null @@ -1,21 +0,0 @@ -module Idv - class SessionsNew < Idv::Base - attr_accessor :selected_state - - def step_name - :sessions - end - - def unsupported_jurisdiction_error(sp_name) - return unless idv_form.unsupported_jurisdiction? - return unless sp_name - errors = idv_form.errors - error_message = [ - I18n.t('idv.errors.unsupported_jurisdiction'), - I18n.t('idv.errors.unsupported_jurisdiction_sp', sp_name: sp_name), - ].join(' ') - errors.delete(:state) - errors.add(:state, error_message) - end - end -end diff --git a/app/views/idv/_hardfail4.html.slim b/app/views/idv/_hardfail4.html.slim deleted file mode 100644 index 0c2d17ff568..00000000000 --- a/app/views/idv/_hardfail4.html.slim +++ /dev/null @@ -1,11 +0,0 @@ -p.mb1 = t('idv.messages.hardfail', hours: Figaro.env.idv_attempt_window_in_hours) -.mt2.py2.px3.col-12.center.border-box.border.border-teal.rounded-xl - p.fs-20p = t('idv.messages.hardfail4_html', sp: decorated_session.sp_name) - p - = link_to t('idv.buttons.continue_plain'), - decorated_session.sp_return_url, - class: 'btn btn-primary btn-wide' -hr.mt2 -.mt2 = link_to t('idv.messages.help_center_html'), MarketingSite.help_url -.mt2 - = link_to t('idv.messages.return_to_profile', app: APP_NAME), profile_path diff --git a/app/views/idv/_no_sp_hardfail.html.slim b/app/views/idv/_no_sp_hardfail.html.slim deleted file mode 100644 index 6b5c1f14c5b..00000000000 --- a/app/views/idv/_no_sp_hardfail.html.slim +++ /dev/null @@ -1,9 +0,0 @@ -.mt2.py2.px3.col-12.center.border-box.border.border-teal.rounded-xl - p.fs-20p - = t('idv.messages.help_center_html') - p = link_to t('idv.buttons.continue_plain'), - MarketingSite.help_url, - class: 'btn btn-primary btn-wide' -hr.mt2 -.mt2 - = link_to t('idv.messages.return_to_profile', app: APP_NAME), profile_path diff --git a/app/views/idv/fail.html.slim b/app/views/idv/fail.html.slim deleted file mode 100644 index cacceea3263..00000000000 --- a/app/views/idv/fail.html.slim +++ /dev/null @@ -1,11 +0,0 @@ -- title t('idv.titles.hardfail') -.clearfix.col-10.sm-col-12.mx-auto - .center - = image_tag(asset_url('no-verify.svg'), - alt: '', - class: 'mb2', - width: 140) - - h1.h3.mb2.my0.px1.center = t('idv.titles.hardfail', app: APP_NAME) - - = render decorated_session.idv_hardfail4_partial diff --git a/app/views/idv/failure/failed_verification_attempt.html.slim b/app/views/idv/failure/failed_verification_attempt.html.slim deleted file mode 100644 index 1bd8e86687a..00000000000 --- a/app/views/idv/failure/failed_verification_attempt.html.slim +++ /dev/null @@ -1,5 +0,0 @@ -= render 'shared/failure', presenter: presenter -= render 'shared/modal_verification_warning', count: presenter.remaining_attempts - -.mt4 - = link_to t("idv.modal.button.warning"), idv_session_path, class: 'btn btn-primary' diff --git a/app/views/idv/shared/other_failure.html.slim b/app/views/idv/shared/other_failure.html.slim index 3315b730f46..34cac002f37 100644 --- a/app/views/idv/shared/other_failure.html.slim +++ b/app/views/idv/shared/other_failure.html.slim @@ -2,4 +2,4 @@ p == presenter.warning_message .mt4 - = link_to presenter.button_text, idv_session_path, class: 'btn btn-primary' + = link_to presenter.button_text, presenter.button_path, class: 'btn btn-primary' diff --git a/app/views/shared/_modal_verification.slim b/app/views/shared/_modal_verification.slim deleted file mode 100644 index b952a611306..00000000000 --- a/app/views/shared/_modal_verification.slim +++ /dev/null @@ -1,12 +0,0 @@ -#verification-modal.display-none - = render layout: '/shared/modal_layout' do - .p3.sm-p4.cntnr-xxskinny.border-box.bg-white.rounded-xxl(class="#{view_model.modal_class_name}") - h2.my2.fs-20p.sans-serif.regular.center = t("idv.modal.#{view_model.step_name}.heading") - hr.mb3.bw4.rounded - .mb4 - p = view_model.message - = render view_model.warning_partial, count: view_model.remaining_attempts - .center - = view_model.button - -== javascript_pack_tag 'verify-modal' diff --git a/app/views/shared/_modal_verification_warning.html.slim b/app/views/shared/_modal_verification_warning.html.slim deleted file mode 100644 index b1221a1d8ae..00000000000 --- a/app/views/shared/_modal_verification_warning.html.slim +++ /dev/null @@ -1 +0,0 @@ -p == t('idv.modal.attempts', count: count) diff --git a/config/locales/idv/en.yml b/config/locales/idv/en.yml index a8364ad7c96..52e828cb8a3 100644 --- a/config/locales/idv/en.yml +++ b/config/locales/idv/en.yml @@ -22,7 +22,6 @@ en: errors: bad_dob: Your date of birth must be a valid date. duplicate_ssn: An account already exists with the information you provided. - hardfail: We were unable to verify your identity at this time. incorrect_password: The password you entered is not correct. mail_limit_reached: You have have requested too much mail in the last month. pattern_mismatch: @@ -77,7 +76,6 @@ en: dupe_ssn2_link: sign out now and sign back in hardfail: We can't log you in right now, but you can try verifying your identity again in %{hours} hours. - hardfail4_html: Go to %{sp} for help accessing your services. help_center_html: Visit our Help Center to learn more about verifying your account. jurisdiction: diff --git a/config/locales/idv/es.yml b/config/locales/idv/es.yml index 71770f788d0..938198fa486 100644 --- a/config/locales/idv/es.yml +++ b/config/locales/idv/es.yml @@ -22,7 +22,6 @@ es: errors: bad_dob: Su fecha de nacimiento debe ser una fecha válida. duplicate_ssn: Ya existe una cuenta con la información que proporcionó. - hardfail: No pudimos verificar su identidad en este momento. incorrect_password: La contraseña que ingresó no es correcta. mail_limit_reached: Usted ha solicitado demasiado correo en el último mes. pattern_mismatch: @@ -75,7 +74,6 @@ es: dupe_ssn2_html: Por favor %{link} con el email que utilizó originalmente. dupe_ssn2_link: Cerrar ahora y volver a iniciar sesión hardfail: NOT TRANSLATED YET - hardfail4_html: NOT TRANSLATED YET help_center_html: Visite nuestro Centro de Ayuda para obtener más información sobre la verificación de su cuenta. jurisdiction: @@ -145,6 +143,9 @@ es: jobfail: Inténtelo de nuevo mañana timeout: Inténtelo de nuevo warning: Inténtelo de nuevo + errors: + link: contáctanos + text: Si sigues recibiendo estos errores, %{link} o vuelve a intentarlo mañana. phone: fail: Para su seguridad, la verificación de identidad de su cuenta está bloqueada durante 24 horas. diff --git a/config/locales/idv/fr.yml b/config/locales/idv/fr.yml index c6b372085a8..5770647681e 100644 --- a/config/locales/idv/fr.yml +++ b/config/locales/idv/fr.yml @@ -24,7 +24,6 @@ fr: bad_dob: Votre date de naissance doit être une date valide. duplicate_ssn: Un compte existe déjà avec l'information que vous avez fournie. chiffres. - hardfail: Nous sommes dans l'incapacité de vérifier votre identité pour le moment. incorrect_password: Le mot de passe que vous avez inscrit est incorrect. mail_limit_reached: Vous avez demandé trop de lettres au cours du dernier mois. pattern_mismatch: @@ -81,7 +80,6 @@ fr: originalement. dupe_ssn2_link: déconnectez-vous puis connectez-vous à nouveau hardfail: NOT TRANSLATED YET - hardfail4_html: NOT TRANSLATED YET help_center_html: Visitez notre Centre d'aide pour en apprendre davantage sur la façon dont nous vérifions votre compte. jurisdiction: @@ -155,6 +153,9 @@ fr: jobfail: Essayez à nouveau demain timeout: Essayez à nouveau warning: Essayez à nouveau + errors: + link: contactez-nous + text: Si vous continuez à recevoir ces erreurs, %{link} ou réessayez demain. phone: fail: Pour votre sécurité, la vérification d'identité de votre compte est verrouillée pendant 24 heures. diff --git a/saml_20180620023548.txt b/saml_20180620023548.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/spec/controllers/concerns/idv_step_concern_spec.rb b/spec/controllers/concerns/idv_step_concern_spec.rb index 3d997dd2443..8d6c106dc39 100644 --- a/spec/controllers/concerns/idv_step_concern_spec.rb +++ b/spec/controllers/concerns/idv_step_concern_spec.rb @@ -19,6 +19,10 @@ class StepController < ApplicationController def show render plain: 'Hello' end + + def failure_url(_) + 'foobar' + end end before(:each) do @@ -33,12 +37,11 @@ def show user.idv_attempts = 3 user.idv_attempted_at = Time.zone.now allow(subject).to receive(:confirm_idv_session_started).and_return(true) + get :show end it 'redirects to hardfail page' do - get :show - - expect(response).to redirect_to idv_fail_url + expect(response).to redirect_to 'foobar' end end @@ -47,12 +50,11 @@ def show allow(subject).to receive(:confirm_idv_session_started).and_return(true) user.idv_attempts = 3 user.idv_attempted_at = Time.zone.now + get :show end it 'redirects to hardfail page' do - get :show - - expect(response).to redirect_to idv_fail_url + expect(response).to redirect_to 'foobar' end end diff --git a/spec/controllers/idv/jurisdiction_controller_spec.rb b/spec/controllers/idv/jurisdiction_controller_spec.rb index 84f1406eecd..4d0a515dd67 100644 --- a/spec/controllers/idv/jurisdiction_controller_spec.rb +++ b/spec/controllers/idv/jurisdiction_controller_spec.rb @@ -56,7 +56,7 @@ it 'redirects to the unsupported jurisdiction fail page' do post :create, params: { jurisdiction: { state: unsupported_jurisdiction } } - expect(response).to redirect_to(idv_jurisdiction_fail_url(:unsupported_jurisdiction)) + expect(response).to redirect_to(idv_jurisdiction_failure_url(:unsupported_jurisdiction)) end end @@ -69,7 +69,7 @@ end end - describe '#show' do + describe '#failure' do let(:reason) { 'unsupported_jurisdiction' } before do @@ -77,7 +77,7 @@ end it 'renders the `_failure` template' do - get :show, params: { reason: reason } + get :failure, params: { reason: reason } expect(response).to render_template('shared/_failure') end diff --git a/spec/controllers/idv/phone_controller_spec.rb b/spec/controllers/idv/phone_controller_spec.rb index bcff48260b4..f6d84b8241c 100644 --- a/spec/controllers/idv/phone_controller_spec.rb +++ b/spec/controllers/idv/phone_controller_spec.rb @@ -56,7 +56,7 @@ get :new - expect(response).to redirect_to idv_fail_path + expect(response).to redirect_to idv_phone_failure_url(:fail) end end @@ -184,8 +184,7 @@ it 'displays an error' do get :show - expect(response).to render_template :new - expect(flash[:warning]).to include(t('idv.modal.phone.timeout')) + expect(response).to redirect_to idv_phone_failure_path(:timeout) end it 'tracks the failure as a timeout' do @@ -241,8 +240,7 @@ vendor: { messages: [], context: {}, exception: nil }, } - expect(flash[:warning]).to match t('idv.modal.phone.heading') - expect(flash[:warning]).to match t('idv.modal.attempts', count: max_attempts - 1) + expect(response).to redirect_to idv_phone_failure_path(:warning) expect(@analytics).to have_received(:track_event).with( Analytics::IDV_PHONE_CONFIRMATION_VENDOR, result ) diff --git a/spec/controllers/idv/sessions_controller_spec.rb b/spec/controllers/idv/sessions_controller_spec.rb index def52dc7132..555c28f248e 100644 --- a/spec/controllers/idv/sessions_controller_spec.rb +++ b/spec/controllers/idv/sessions_controller_spec.rb @@ -73,7 +73,7 @@ expect(@analytics).to have_received(:track_event). with(Analytics::IDV_MAX_ATTEMPTS_EXCEEDED, result) - expect(response).to redirect_to idv_fail_url + expect(response).to redirect_to idv_session_failure_url(:fail) end end end @@ -106,8 +106,7 @@ post :create, params: { profile: user_attrs.merge(ssn: '666-66-1234') } - expect(response).to redirect_to(idv_session_dupe_path) - expect(flash[:error]).to match t('idv.errors.duplicate_ssn') + expect(response).to redirect_to(idv_session_failure_url(:dupe_ssn)) end end @@ -115,7 +114,7 @@ it 'renders the form' do post :create, params: { profile: user_attrs.merge(ssn: '') } - expect(response).to_not redirect_to(idv_session_dupe_path) + expect(response).to_not redirect_to(idv_session_failure_url(:dupe_ssn)) expect(response).to render_template(:new) end end @@ -171,8 +170,7 @@ it 'displays an error' do get :show - expect(response).to render_template :new - expect(flash[:warning]).to include(t('idv.modal.sessions.timeout')) + expect(response).to redirect_to(idv_session_failure_url(:timeout)) end it 'tracks the failure as a timeout' do @@ -216,12 +214,10 @@ ) end - it 're-renders form' do + it 'redirects to the failure page' do get :show - expect(flash[:warning]).to match t('idv.modal.sessions.heading') - expect(flash[:warning]).to match(t('idv.modal.attempts', count: max_attempts - 1)) - expect(response).to render_template(:new) + expect(response).to redirect_to(idv_session_failure_url(:warning)) end it 'creates analytics event' do @@ -252,7 +248,7 @@ ) end - it 'logs failure and re-renders form' do + it 'logs failure and redirects to the failure page' do get :show result = { @@ -266,7 +262,7 @@ expect(@analytics).to have_received(:track_event). with(Analytics::IDV_BASIC_INFO_SUBMITTED_VENDOR, result) - expect(response).to render_template(:new) + expect(response).to redirect_to(idv_session_failure_url(:warning)) end end @@ -315,7 +311,7 @@ expect(@analytics).to have_received(:track_event). with(Analytics::IDV_MAX_ATTEMPTS_EXCEEDED, result) - expect(response).to redirect_to idv_fail_url + expect(response).to redirect_to idv_session_failure_url(:fail) end end diff --git a/spec/controllers/idv_controller_spec.rb b/spec/controllers/idv_controller_spec.rb index f75bdb6f602..42b31bdcada 100644 --- a/spec/controllers/idv_controller_spec.rb +++ b/spec/controllers/idv_controller_spec.rb @@ -142,7 +142,7 @@ get :fail - expect(response).to render_template(:fail) + expect(response).to render_template('shared/_failure') end end end diff --git a/spec/decorators/service_provider_session_decorator_spec.rb b/spec/decorators/service_provider_session_decorator_spec.rb index 8fcb26f208e..f2d63a9289d 100644 --- a/spec/decorators/service_provider_session_decorator_spec.rb +++ b/spec/decorators/service_provider_session_decorator_spec.rb @@ -49,12 +49,6 @@ end end - describe '#idv_hardfail4_partial' do - it 'returns the correct partial' do - expect(subject.idv_hardfail4_partial).to eq 'idv/hardfail4' - end - end - describe '#sp_name' do it 'returns the SP friendly name if present' do expect(subject.sp_name).to eq sp.friendly_name diff --git a/spec/decorators/session_decorator_spec.rb b/spec/decorators/session_decorator_spec.rb index 34d145ca63f..b867a2e6f1d 100644 --- a/spec/decorators/session_decorator_spec.rb +++ b/spec/decorators/session_decorator_spec.rb @@ -43,12 +43,6 @@ end end - describe '#idv_hardfail4_partial' do - it 'returns the correct partial' do - expect(subject.idv_hardfail4_partial).to eq 'idv/no_sp_hardfail' - end - end - describe '#sp_logo' do it 'returns nil' do expect(subject.sp_logo).to be_nil diff --git a/spec/features/idv/state_id_data_spec.rb b/spec/features/idv/state_id_data_spec.rb index ee8eba2d6f5..ce1020bdc21 100644 --- a/spec/features/idv/state_id_data_spec.rb +++ b/spec/features/idv/state_id_data_spec.rb @@ -3,6 +3,8 @@ feature 'idv state id data entry', :idv_job do include IdvStepHelper + let(:locale) { LinkLocaleResolver.locale } + before do start_idv_from_sp complete_idv_steps_before_profile_step @@ -14,7 +16,7 @@ click_idv_continue expect(page).to have_content t('idv.modal.sessions.warning') - expect(current_path).to eq(idv_session_result_path) + expect(current_path).to eq(idv_session_failure_path(:warning, locale: locale)) end it 'renders an error for blank state id number and does not submit a job', :email do diff --git a/spec/features/idv/steps/jurisdiction_step_spec.rb b/spec/features/idv/steps/jurisdiction_step_spec.rb index fae498190c5..75b51f2f9cd 100644 --- a/spec/features/idv/steps/jurisdiction_step_spec.rb +++ b/spec/features/idv/steps/jurisdiction_step_spec.rb @@ -30,7 +30,7 @@ click_idv_continue expect(page). - to have_current_path(idv_jurisdiction_fail_path(reason: :unsupported_jurisdiction)) + to have_current_path(idv_jurisdiction_failure_path(reason: :unsupported_jurisdiction)) expect(page).to have_content(t('idv.titles.unsupported_jurisdiction', state: 'Alabama')) end end @@ -39,7 +39,7 @@ it 'renders the `no_id` fail page' do click_on t('idv.messages.jurisdiction.no_id') - expect(page).to have_current_path(idv_jurisdiction_fail_path(reason: :no_id)) + expect(page).to have_current_path(idv_jurisdiction_failure_path(reason: :no_id)) expect(page).to have_content(t('idv.titles.no_id')) end end diff --git a/spec/features/idv/steps/phone_step_spec.rb b/spec/features/idv/steps/phone_step_spec.rb index 6de613e9e56..9a296f9204a 100644 --- a/spec/features/idv/steps/phone_step_spec.rb +++ b/spec/features/idv/steps/phone_step_spec.rb @@ -1,6 +1,6 @@ require 'rails_helper' -feature 'idv profile step', :idv_job do +feature 'idv phone step', :idv_job do include IdvStepHelper context 'with valid information' do diff --git a/spec/support/idv_examples/fail_to_verify.rb b/spec/support/idv_examples/fail_to_verify.rb index a9ac4245b5e..b6aebae2837 100644 --- a/spec/support/idv_examples/fail_to_verify.rb +++ b/spec/support/idv_examples/fail_to_verify.rb @@ -5,29 +5,6 @@ step end - shared_examples 'warning failure' do - it 'renders a warning failure screen and lets the user try again' do - expect(page).to have_current_path(idv_session_failure_path(:warning, locale: locale)) if step == :profile - expect(page).to have_current_path(idv_phone_failure_path(:warning, locale: locale)) if step == :phone - expect(page).to have_content t("idv.modal.#{step_locale_key}.heading") - expect(page).to have_content t("idv.modal.#{step_locale_key}.warning") - - click_on t('idv.modal.button.warning') - - if step == :profile - fill_out_idv_form_ok - click_idv_continue - end - fill_out_phone_form_ok if step == :phone - click_idv_continue - - expect(page).to have_current_path(idv_phone_path) if step == :profile - expect(page).to have_current_path(idv_otp_delivery_method_path) if step == :phone - expect(page).to have_content(t('idv.titles.session.phone')) if step == :profile - expect(page).to have_content(t('idv.titles.otp_delivery_method')) if step == :phone - end - end - before do start_idv_from_sp complete_idv_steps_before_step(step) @@ -36,11 +13,32 @@ click_continue end - context 'without js' do - it_behaves_like 'warning failure' + it 'renders a warning failure screen and lets the user try again' do + expect(page).to have_current_path(session_failure_path) if step == :profile + expect(page).to have_current_path(phone_failure_path) if step == :phone + expect(page).to have_content t("idv.modal.#{step_locale_key}.heading") + expect(page).to have_content t("idv.modal.#{step_locale_key}.warning") + + click_on t('idv.modal.button.warning') + + if step == :profile + fill_out_idv_form_ok + click_idv_continue + end + fill_out_phone_form_ok if step == :phone + click_idv_continue + + expect(page).to have_current_path(idv_phone_path) if step == :profile + expect(page).to have_current_path(idv_otp_delivery_method_path) if step == :phone + expect(page).to have_content(t('idv.titles.session.phone')) if step == :profile + expect(page).to have_content(t('idv.titles.otp_delivery_method')) if step == :phone + end + + def session_failure_path + idv_session_failure_path(:warning, locale: locale) end - context 'with js', :js do - it_behaves_like 'warning failure' + def phone_failure_path + idv_phone_failure_path(:warning, locale: locale) end end diff --git a/spec/support/idv_examples/failed_idv_job.rb b/spec/support/idv_examples/failed_idv_job.rb index 9f73f1e5fbe..e513bda3ed0 100644 --- a/spec/support/idv_examples/failed_idv_job.rb +++ b/spec/support/idv_examples/failed_idv_job.rb @@ -13,15 +13,6 @@ end context 'the job raises an error' do - shared_examples 'shows a warning' do - it 'renders a jobfail failure screen' do - expect(page).to have_current_path(idv_session_failure_path(:jobfail, locale: locale)) if step == :profile - expect(page).to have_current_path(idv_phone_failure_path(:jobfail, locale: locale)) if step == :phone - expect(page).to have_content t("idv.modal.#{step_locale_key}.heading") - expect(page).to have_content t("idv.modal.#{step_locale_key}.jobfail") - end - end - before do stub_idv_job_to_raise_error_in_background(idv_job_class) @@ -30,25 +21,15 @@ click_idv_continue end - context 'without js' do - it_behaves_like 'shows a warning' - end - - context 'with js', :js do - it_behaves_like 'shows a warning' + it 'renders a jobfail failure screen' do + expect(page).to have_current_path(session_failure_path(:jobfail)) if step == :profile + expect(page).to have_current_path(phone_failure_path(:jobfail)) if step == :phone + expect(page).to have_content t("idv.modal.#{step_locale_key}.heading") + expect(page).to have_content t("idv.modal.#{step_locale_key}.jobfail") end end context 'the job times out' do - shared_examples 'shows a warning' do - it 'renders a timeout failure page' do - expect(page).to have_current_path(idv_session_failure_path(:timeout, locale: locale)) if step == :profile - expect(page).to have_current_path(idv_phone_failure_path(:timeout, locale: locale)) if step == :phone - expect(page).to have_content t("idv.modal.#{step_locale_key}.heading") - expect(page).to have_content t("idv.modal.#{step_locale_key}.timeout") - end - end - before do stub_idv_job_to_timeout_in_background(idv_job_class) @@ -66,16 +47,18 @@ Timecop.return end - context 'without js' do - it_behaves_like 'shows a warning' - end - - context 'with js', :js do - it_behaves_like 'shows a warning' + it 'renders a timeout failure page' do + expect(page).to have_current_path(session_failure_path(:timeout)) if step == :profile + expect(page).to have_current_path(phone_failure_path(:timeout)) if step == :phone + expect(page).to have_content t("idv.modal.#{step_locale_key}.heading") + expect(page).to have_content t("idv.modal.#{step_locale_key}.timeout") end end # rubocop:disable Lint/HandleExceptions + # rubocop:disable Style/RedundantBegin + # Disabling Style/RedundantBegin because when i remove make the changes + # to remove it, fasterer can no longer parse the code... def stub_idv_job_to_raise_error_in_background(idv_job_class) allow(Idv::Agent).to receive(:new).and_raise('this is a test error') allow(idv_job_class).to receive(:perform_now).and_wrap_original do |perform_now, *args| @@ -86,9 +69,18 @@ def stub_idv_job_to_raise_error_in_background(idv_job_class) end end end + # rubocop:enable Style/RedundantBegin # rubocop:enable Lint/HandleExceptions def stub_idv_job_to_timeout_in_background(idv_job_class) allow(idv_job_class).to receive(:perform_now) end + + def session_failure_path(reason) + idv_session_failure_path(reason, locale: locale) + end + + def phone_failure_path(reason) + idv_phone_failure_path(reason, locale: locale) + end end diff --git a/spec/support/idv_examples/max_attempts.rb b/spec/support/idv_examples/max_attempts.rb index c4f7d433f72..8983991814c 100644 --- a/spec/support/idv_examples/max_attempts.rb +++ b/spec/support/idv_examples/max_attempts.rb @@ -24,12 +24,12 @@ # Blocked if visiting verify directly visit idv_url advance_to_phone_step if step == :phone - expect_user_to_be_unable_to_perform_idv(sp) + expect_user_to_be_unable_to_perform_idv(step) # Blocked if visiting from an SP visit_idp_from_sp_with_loa3(:oidc) advance_to_phone_step if step == :phone - expect_user_to_be_unable_to_perform_idv(sp) + expect_user_to_be_unable_to_perform_idv(step) if step == :sessions user.reload @@ -102,21 +102,10 @@ def perfom_maximum_allowed_idv_step_attempts click_idv_continue end - def expect_user_to_be_unable_to_perform_idv(sp) - expect(page).to have_content(t('idv.titles.hardfail', app: 'login.gov')) - if sp.present? - expect(page).to have_content( - t('idv.messages.hardfail', hours: Figaro.env.idv_attempt_window_in_hours) - ) - expect(page).to have_content( - strip_tags(t('idv.messages.hardfail4_html', sp: 'Test SP')) - ) - else - expect(page).to have_content( - strip_tags(t('idv.messages.help_center_html')) - ) - end - expect(current_url).to eq(idv_fail_url) + def expect_user_to_be_unable_to_perform_idv(step) + expect(page).to have_content(t("idv.modal.#{step_locale_key}.heading")) + expect(current_url).to eq(idv_phone_failure_url(:fail, locale: locale)) if step == :phone + expect(current_url).to eq(idv_session_failure_url(:fail, locale: locale)) if step == :profile end def advance_to_phone_step diff --git a/spec/view_models/idv/base_spec.rb b/spec/view_models/idv/base_spec.rb deleted file mode 100644 index 9a9132ada42..00000000000 --- a/spec/view_models/idv/base_spec.rb +++ /dev/null @@ -1,72 +0,0 @@ -require 'rails_helper' - -RSpec.describe Idv::Base do - describe '#message' do - let(:timed_out) { false } - let(:view_model) do - Idv::Base.new( - error: error, - remaining_attempts: 1, - idv_form: nil, - timed_out: timed_out - ) - end - - subject(:message) { view_model.message } - - before { expect(view_model).to receive(:step_name).and_return(:phone) } - - context 'with a warning' do - let(:error) { 'warning' } - - it 'uses the warning copy' do - expect(message).to include(t('idv.modal.phone.warning')) - end - - context 'with a timeout' do - let(:timed_out) { true } - - it 'uses the timeout copy' do - expect(message).to include(t('idv.modal.phone.timeout')) - end - end - end - end - - describe '#modal_class_name' do - let(:view_model) do - Idv::Base.new( - error: error, - remaining_attempts: 1, - idv_form: nil, - timed_out: false - ) - end - - subject(:modal_class_name) { view_model.modal_class_name } - - context 'when error is warning' do - let(:error) { 'warning' } - - it 'returns modal_warning' do - expect(modal_class_name).to eq 'modal-warning' - end - end - - context 'when error is jobfail' do - let(:error) { 'jobfail' } - - it 'returns modal_warning' do - expect(modal_class_name).to eq 'modal-warning' - end - end - - context 'when error is fail' do - let(:error) { 'fail' } - - it 'returns modal_fail' do - expect(modal_class_name).to eq 'modal-fail' - end - end - end -end diff --git a/spec/views/idv/_hardfail4.html.slim_spec.rb b/spec/views/idv/_hardfail4.html.slim_spec.rb deleted file mode 100644 index fb573ef77ab..00000000000 --- a/spec/views/idv/_hardfail4.html.slim_spec.rb +++ /dev/null @@ -1,20 +0,0 @@ -require 'rails_helper' - -RSpec.describe 'idv/_hardfail4.html.slim' do - let(:decorated_session) do - instance_double('SessionDecorator', sp_name: 'Example SP', sp_return_url: 'test.host') - end - - before do - allow(view).to receive(:decorated_session).and_return(decorated_session) - end - - it 'links to the profile' do - render - - expect(rendered).to have_link( - t('idv.messages.return_to_profile', app: APP_NAME), - href: profile_path - ) - end -end diff --git a/spec/views/idv/_no_sp_hardfail.html.slim_spec.rb b/spec/views/idv/_no_sp_hardfail.html.slim_spec.rb deleted file mode 100644 index dea6d862f7d..00000000000 --- a/spec/views/idv/_no_sp_hardfail.html.slim_spec.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'rails_helper' - -RSpec.describe 'idv/_no_sp_hardfail.html.slim' do - it 'links to the profile' do - render - - expect(rendered).to have_link( - t('idv.messages.return_to_profile', app: APP_NAME), - href: profile_path - ) - end -end diff --git a/spec/views/idv/fail.html.slim_spec.rb b/spec/views/idv/fail.html.slim_spec.rb deleted file mode 100644 index fcc29ef4421..00000000000 --- a/spec/views/idv/fail.html.slim_spec.rb +++ /dev/null @@ -1,36 +0,0 @@ -require 'rails_helper' - -describe 'idv/fail.html.slim' do - let(:view_context) { ActionController::Base.new.view_context } - - context 'when SP is present' do - before do - sp = build_stubbed(:service_provider, friendly_name: 'Awesome Application!') - @decorated_session = ServiceProviderSessionDecorator.new( - sp: sp, view_context: view_context, sp_session: {}, service_provider_request: nil - ) - allow(view).to receive(:decorated_session).and_return(@decorated_session) - end - - it 'displays the hardfail4 partial' do - render - - expect(view).to render_template(partial: 'idv/_hardfail4') - expect(rendered).to have_content( - strip_tags(t('idv.messages.hardfail4_html', sp: @decorated_session.sp_name)) - ) - end - end - - context 'when SP is not present' do - before do - allow(view).to receive(:decorated_session).and_return(SessionDecorator.new) - end - - it 'displays the null partial' do - render - - expect(view).to render_template(partial: 'idv/_no_sp_hardfail') - end - end -end From 9f0d4833d4c535100783631a0c32fdade907244d Mon Sep 17 00:00:00 2001 From: David Corwin Date: Tue, 19 Jun 2018 15:37:15 -0700 Subject: [PATCH 10/26] Fix specs --- spec/support/idv_examples/max_attempts.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spec/support/idv_examples/max_attempts.rb b/spec/support/idv_examples/max_attempts.rb index 8983991814c..6a4c325410c 100644 --- a/spec/support/idv_examples/max_attempts.rb +++ b/spec/support/idv_examples/max_attempts.rb @@ -103,9 +103,10 @@ def perfom_maximum_allowed_idv_step_attempts end def expect_user_to_be_unable_to_perform_idv(step) - expect(page).to have_content(t("idv.modal.#{step_locale_key}.heading")) + expect(page).to have_content(t("idv.modal.#{step_locale_key}.heading")) if step == :phone + expect(page).to have_content(t('idv.titles.hardfail', app: 'login.gov')) if step == :profile expect(current_url).to eq(idv_phone_failure_url(:fail, locale: locale)) if step == :phone - expect(current_url).to eq(idv_session_failure_url(:fail, locale: locale)) if step == :profile + expect(current_url).to eq(idv_fail_url) if step == :profile end def advance_to_phone_step From b9dff277833d676a5598001b109dc54564079a44 Mon Sep 17 00:00:00 2001 From: David Corwin Date: Tue, 19 Jun 2018 19:37:45 -0700 Subject: [PATCH 11/26] Rubocop fixes --- spec/controllers/concerns/idv_step_concern_spec.rb | 2 +- spec/controllers/idv/sessions_controller_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/controllers/concerns/idv_step_concern_spec.rb b/spec/controllers/concerns/idv_step_concern_spec.rb index 8d6c106dc39..61d589fa6d9 100644 --- a/spec/controllers/concerns/idv_step_concern_spec.rb +++ b/spec/controllers/concerns/idv_step_concern_spec.rb @@ -20,7 +20,7 @@ def show render plain: 'Hello' end - def failure_url(_) + def failure_url(__) 'foobar' end end diff --git a/spec/controllers/idv/sessions_controller_spec.rb b/spec/controllers/idv/sessions_controller_spec.rb index 555c28f248e..33b14bbf594 100644 --- a/spec/controllers/idv/sessions_controller_spec.rb +++ b/spec/controllers/idv/sessions_controller_spec.rb @@ -262,7 +262,7 @@ expect(@analytics).to have_received(:track_event). with(Analytics::IDV_BASIC_INFO_SUBMITTED_VENDOR, result) - expect(response).to redirect_to(idv_session_failure_url(:warning)) + expect(response).to redirect_to(idv_session_failure_url(:warning)) end end From 556762d703af7f3f6cbf30f7363d9c993154a2f9 Mon Sep 17 00:00:00 2001 From: David Corwin Date: Tue, 19 Jun 2018 20:00:22 -0700 Subject: [PATCH 12/26] Rubocop fix --- .../concerns/idv_failure_concern.rb | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/app/controllers/concerns/idv_failure_concern.rb b/app/controllers/concerns/idv_failure_concern.rb index d5e9e29ecf2..9eb6a4fb4e4 100644 --- a/app/controllers/concerns/idv_failure_concern.rb +++ b/app/controllers/concerns/idv_failure_concern.rb @@ -2,13 +2,10 @@ module IdvFailureConcern extend ActiveSupport::Concern def idv_step_failure_reason - if idv_attempter.exceeded? || step_attempts_exceeded? - :fail - elsif step.vendor_validator_job_failed? - :jobfail - elsif !step.vendor_validation_passed? - step.vendor_validation_timed_out? ? :timeout : :warning - end + return :fail if fail? + return :jobfail if jobfail? + return :timeout if timeout? + return :warning if warning? end def render_idv_step_failure(step, reason) @@ -22,6 +19,22 @@ def render_failure(template, presenter) private + def fail? + idv_attempter.exceeded? || step_attempts_exceeded? + end + + def jobfail? + step.vendor_validator_job_failed? + end + + def timeout? + !step.vendor_validation_passed? && step.vendor_validation_timed_out? + end + + def warning? + !step.vendor_validation_passed? && !step.vendor_validation_timed_out? + end + def failure_presenter(step) Idv::MaxAttemptsFailurePresenter.new( decorated_session: decorated_session, From eef8367367fb12e055a8554daa81c143b71e326b Mon Sep 17 00:00:00 2001 From: David Corwin Date: Wed, 20 Jun 2018 08:46:12 -0700 Subject: [PATCH 13/26] Add presenter specs --- .../idv/idv_failure_presenter_spec.rb | 99 +++++++++++++++++++ spec/presenters/idv/warning_presenter_spec.rb | 83 ++++++++++++++++ 2 files changed, 182 insertions(+) create mode 100644 spec/presenters/idv/idv_failure_presenter_spec.rb create mode 100644 spec/presenters/idv/warning_presenter_spec.rb diff --git a/spec/presenters/idv/idv_failure_presenter_spec.rb b/spec/presenters/idv/idv_failure_presenter_spec.rb new file mode 100644 index 00000000000..39ecb8c5360 --- /dev/null +++ b/spec/presenters/idv/idv_failure_presenter_spec.rb @@ -0,0 +1,99 @@ +require 'rails_helper' + +describe Idv::IdvFailurePresenter do + let(:decorated_session) { mock_decorated_session } + let(:view_context) { mock_view_context } + let(:presenter) { described_class.new(view_context: view_context) } + + describe 'it uses the :locked failure state' do + subject { presenter.state } + + it { is_expected.to eq(:locked) } + end + + context 'methods are overriden' do + %i[message title header description].each do |method| + describe "##{method}" do + subject { presenter.send(method) } + + it { is_expected.to_not be_nil } + end + end + end + + describe '#title' do + subject { presenter.send(:title) } + + it 'includes the app name' do + expect(subject).to include('login.gov') + end + end + + describe '#header' do + subject { presenter.send(:header) } + + it 'includes the app name' do + expect(subject).to include('login.gov') + end + end + + describe '#description' do + subject { presenter.send(:description) } + + it 'includes the lockout window' do + expect(subject).to include(Figaro.env.idv_attempt_window_in_hours) + end + end + + describe '#next_steps' do + subject { presenter.next_steps } + + it 'includes `help_step`, `sp_step`, and `profile_step`' do + expect(subject).to eq( + [ + presenter.send(:help_step), + presenter.send(:sp_step), + presenter.send(:profile_step), + ] + ) + end + end + + describe '#help_step' do + subject { presenter.send(:help_step) } + + it 'includes help url' do + expect(subject).to include(MarketingSite.help_url) + end + end + + describe '#sp_step' do + subject { presenter.send(:sp_step) } + + it 'includes sp url' do + expect(subject).to include(decorated_session.sp_alert_learn_more) + end + end + + describe '#profile_step' do + subject { presenter.send(:profile_step) } + + it 'includes profile url' do + expect(subject).to include(view_context.account_path) + end + end + + def mock_view_context + view_context = ActionView::Base.new + allow(view_context).to receive(:account_path).and_return('Account Path') + allow(view_context).to receive(:decorated_session).and_return(mock_decorated_session) + view_context + end + + def mock_decorated_session + decorated_session = instance_double(SessionDecorator) + allow(decorated_session).to receive(:sp_name).and_return('Test SP') + allow(decorated_session).to receive(:sp_alert_learn_more).and_return('SP Link') + decorated_session + end +end diff --git a/spec/presenters/idv/warning_presenter_spec.rb b/spec/presenters/idv/warning_presenter_spec.rb new file mode 100644 index 00000000000..8fff876883c --- /dev/null +++ b/spec/presenters/idv/warning_presenter_spec.rb @@ -0,0 +1,83 @@ +require 'rails_helper' + +describe Idv::WarningPresenter do + let(:reason) { :warning } + let(:remaining_attempts) { 2 } + let(:step_name) { :sessions } + let(:view_context) { mock_view_context } + let(:presenter) do + described_class.new( + reason: reason, + remaining_attempts: remaining_attempts, + step_name: step_name, + view_context: view_context + ) + end + + describe 'it uses the :warning failure state' do + subject { presenter.state } + + it { is_expected.to eq(:warning) } + end + + context 'methods are overriden' do + %i[title header description].each do |method| + describe "##{method}" do + subject { presenter.send(method) } + + it { is_expected.to_not be_nil } + end + end + end + + describe '#warning_message' do + context 'when `reason == :warning`' do + let(:reason) { :warning } + + subject { presenter.warning_message } + + it { is_expected.to eq(presenter.send(:warning)) } + end + + context 'when `reason != :warning`' do + let(:reason) { :fail } + + subject { presenter.warning_message } + + it { is_expected.to eq(presenter.send(:error)) } + end + end + + describe '#button_path' do + context 'when `step_name == :sessions`' do + let(:step_name) { :sessions } + + subject { presenter.button_path } + + it { is_expected.to eq(view_context.idv_session_path) } + end + + context 'when `step_name != :sessions`' do + let(:step_name) { :phone } + + subject { presenter.button_path } + + it { is_expected.to eq(view_context.idv_phone_path) } + end + end + + describe '#warning' do + subject { presenter.send(:warning) } + + it 'includes the number of remaining attempts' do + expect(subject).to include(remaining_attempts.to_s) + end + end + + def mock_view_context + view_context = ActionView::Base.new + allow(view_context).to receive(:idv_phone_path).and_return('idv phone path') + allow(view_context).to receive(:idv_session_path).and_return('idv session path') + view_context + end +end From 3173d5444a2b1b21e21f5d6a0ac155531acbff76 Mon Sep 17 00:00:00 2001 From: David Corwin Date: Wed, 20 Jun 2018 08:55:56 -0700 Subject: [PATCH 14/26] Update spec, i18n path --- app/assets/javascripts/i18n-strings.js.erb | 2 +- .../idv/attempt_failure_presenter.rb | 6 +- .../idv/max_attempts_failure_presenter.rb | 6 +- app/presenters/idv/warning_presenter.rb | 14 ++--- config/i18n-tasks.yml | 2 +- config/locales/idv/en.yml | 58 +++++++++--------- config/locales/idv/es.yml | 58 +++++++++--------- config/locales/idv/fr.yml | 60 +++++++++---------- spec/features/idv/state_id_data_spec.rb | 2 +- spec/features/idv/steps/profile_step_spec.rb | 2 +- spec/presenters/idv/warning_presenter_spec.rb | 8 +++ spec/support/idv_examples/fail_to_verify.rb | 6 +- spec/support/idv_examples/failed_idv_job.rb | 8 +-- spec/support/idv_examples/max_attempts.rb | 12 ++-- 14 files changed, 126 insertions(+), 118 deletions(-) diff --git a/app/assets/javascripts/i18n-strings.js.erb b/app/assets/javascripts/i18n-strings.js.erb index fd535a4ebe6..4a36792f633 100644 --- a/app/assets/javascripts/i18n-strings.js.erb +++ b/app/assets/javascripts/i18n-strings.js.erb @@ -12,7 +12,7 @@ window.LoginGov = window.LoginGov || {}; 'idv.errors.pattern_mismatch.personal_key', 'idv.errors.pattern_mismatch.ssn', 'idv.errors.pattern_mismatch.zipcode', - 'idv.modal.button.warning', + 'idv.failure.button.warning', 'instructions.password.strength.i', 'instructions.password.strength.ii', 'instructions.password.strength.iii', diff --git a/app/presenters/idv/attempt_failure_presenter.rb b/app/presenters/idv/attempt_failure_presenter.rb index 5e9ede951ce..17882fa257c 100644 --- a/app/presenters/idv/attempt_failure_presenter.rb +++ b/app/presenters/idv/attempt_failure_presenter.rb @@ -11,15 +11,15 @@ def initialize(remaining_attempts:, step_name:) end def title - t("idv.modal.#{step_name}.heading") + t("idv.failure.#{step_name}.heading") end def header - t("idv.modal.#{step_name}.heading") + t("idv.failure.#{step_name}.heading") end def description - t("idv.modal.#{step_name}.warning") + t("idv.failure.#{step_name}.warning") end end end diff --git a/app/presenters/idv/max_attempts_failure_presenter.rb b/app/presenters/idv/max_attempts_failure_presenter.rb index 0bf53a79ba9..01ac4b1cfcc 100644 --- a/app/presenters/idv/max_attempts_failure_presenter.rb +++ b/app/presenters/idv/max_attempts_failure_presenter.rb @@ -16,15 +16,15 @@ def initialize(decorated_session:, step_name:, view_context:) end def title - t("idv.modal.#{step_name}.heading") + t("idv.failure.#{step_name}.heading") end def header - t("idv.modal.#{step_name}.heading") + t("idv.failure.#{step_name}.heading") end def description - t("idv.modal.#{step_name}.fail") + t("idv.failure.#{step_name}.fail") end def message diff --git a/app/presenters/idv/warning_presenter.rb b/app/presenters/idv/warning_presenter.rb index 2d60e1d561f..7fa516466f8 100644 --- a/app/presenters/idv/warning_presenter.rb +++ b/app/presenters/idv/warning_presenter.rb @@ -17,15 +17,15 @@ def initialize(reason:, remaining_attempts:, step_name:, view_context:) end def title - t("idv.modal.#{step_name}.heading") + t("idv.failure.#{step_name}.heading") end def header - t("idv.modal.#{step_name}.heading") + t("idv.failure.#{step_name}.heading") end def description - t("idv.modal.#{step_name}.#{reason}") + t("idv.failure.#{step_name}.#{reason}") end def warning_message @@ -33,7 +33,7 @@ def warning_message end def button_text - t("idv.modal.button.#{reason}") + t("idv.failure.button.#{reason}") end def button_path @@ -43,12 +43,12 @@ def button_path private def warning - t('idv.modal.attempts', count: remaining_attempts) + t('idv.failure.attempts', count: remaining_attempts) end def error - link = link_to(t('idv.modal.errors.link'), '') - t('idv.modal.errors.text', link: link) + link = link_to(t('idv.failure.errors.link'), MarketingSite.contact_url) + t('idv.failure.errors.text', link: link) end end end diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml index 6b4300eea71..7edf225b75e 100644 --- a/config/i18n-tasks.yml +++ b/config/i18n-tasks.yml @@ -97,7 +97,7 @@ ignore_unused: - 'errors.not_authorized' - 'event_types.*' - 'idv.errors.pattern_mismatch.*' - - 'idv.modal.*' + - 'idv.failure.*' - 'links.remove' - 'valid_email.validations.email.invalid' - 'zxcvbn.*' diff --git a/config/locales/idv/en.yml b/config/locales/idv/en.yml index 52e828cb8a3..7f4409437fc 100644 --- a/config/locales/idv/en.yml +++ b/config/locales/idv/en.yml @@ -31,6 +31,35 @@ en: zipcode: 'Your zipcode must be entered in as #####-####' unsupported_jurisdiction: Sorry, we can't verify people from this state. unsupported_jurisdiction_sp: Please visit %{sp_name} to access your account. + failure: + attempts: + one: You have 1 attempt remaining. + other: You have %{count} attempts remaining. + button: + fail: Okay + jobfail: Try again tomorrow + timeout: Try again + warning: Try again + errors: + link: please contact us + text: If you keep getting these errors, %{link}, or try again tomorrow. + phone: + fail: For your security, identity verification for your account is locked + for 24 hours. + heading: We could not find records matching your phone information. + jobfail: Something went wrong and we cannot process your request at this time. + Please try again tomorrow. + timeout: Our request to verify your information timed out. + warning: Please check the information you entered. + sessions: + fail: For your security, identity verification for your account is locked + for 24 hours. + heading: We could not find records matching your personal information. + jobfail: Something went wrong and we cannot process your request at this time. + Please try again tomorrow. + timeout: Our request to verify your information timed out. + warning: Please check the information you entered. Common mistakes are an + incorrect Social Security Number, ZIP Code, or date of birth. form: activate_by_mail: get a code via mail instead › address1: Address @@ -132,35 +161,6 @@ en: success: It should arrive in 5 to 10 business days. agencies_login: You can now continue to and log into these agencies. agency_login_html: You can now continue to and into
%{sp}. - modal: - attempts: - one: You have 1 attempt remaining. - other: You have %{count} attempts remaining. - button: - fail: Okay - jobfail: Try again tomorrow - timeout: Try again - warning: Try again - errors: - link: please contact us - text: If you keep getting these errors, %{link}, or try again tomorrow. - phone: - fail: For your security, identity verification for your account is locked - for 24 hours. - heading: We could not find records matching your phone information. - jobfail: Something went wrong and we cannot process your request at this time. - Please try again tomorrow. - timeout: Our request to verify your information timed out. - warning: Please check the information you entered. - sessions: - fail: For your security, identity verification for your account is locked - for 24 hours. - heading: We could not find records matching your personal information. - jobfail: Something went wrong and we cannot process your request at this time. - Please try again tomorrow. - timeout: Our request to verify your information timed out. - warning: Please check the information you entered. Common mistakes are an - incorrect Social Security Number, ZIP Code, or date of birth. review: dob: Date of birth full_name: Full name diff --git a/config/locales/idv/es.yml b/config/locales/idv/es.yml index 938198fa486..857a9d9a386 100644 --- a/config/locales/idv/es.yml +++ b/config/locales/idv/es.yml @@ -32,6 +32,35 @@ es: unsupported_jurisdiction: Lo sentimos, no podemos verificar personas de este estado. unsupported_jurisdiction_sp: Visita %{sp_name} para acceder a tu cuenta. + failure: + attempts: + one: Tiene usted 1 intento restante. + other: Tiene usted %{count} intentos restantes. + button: + fail: Bueno + jobfail: Inténtelo de nuevo mañana + timeout: Inténtelo de nuevo + warning: Inténtelo de nuevo + errors: + link: contáctanos + text: Si sigues recibiendo estos errores, %{link} o vuelve a intentarlo mañana. + phone: + fail: Para su seguridad, la verificación de identidad de su cuenta está bloqueada + durante 24 horas. + heading: No hemos podido encontrar registros que coincidan con la información + de su teléfono. + jobfail: NOT TRANSLATED YET + timeout: NOT TRANSLATED YET + warning: Compruebe la información que ingresó. + sessions: + fail: Para su seguridad, la verificación de identidad de su cuenta está bloqueada + durante 24 horas. + heading: No hemos podido encontrar registros que coincidan con su información + personal. + jobfail: NOT TRANSLATED YET + timeout: NOT TRANSLATED YET + warning: Compruebe la información que ingresó. Los errores comunes son números + incorrectos de Seguro Social, código postal o fecha de nacimiento. form: activate_by_mail: obtener un código por correo electrónico en su lugar › address1: Dirección @@ -134,35 +163,6 @@ es: success: Debe llegar en 5 a 10 días laborales. agencies_login: NOT TRANSLATED YET agency_login_html: NOT TRANSLATED YET - modal: - attempts: - one: Tiene usted 1 intento restante. - other: Tiene usted %{count} intentos restantes. - button: - fail: Bueno - jobfail: Inténtelo de nuevo mañana - timeout: Inténtelo de nuevo - warning: Inténtelo de nuevo - errors: - link: contáctanos - text: Si sigues recibiendo estos errores, %{link} o vuelve a intentarlo mañana. - phone: - fail: Para su seguridad, la verificación de identidad de su cuenta está bloqueada - durante 24 horas. - heading: No hemos podido encontrar registros que coincidan con la información - de su teléfono. - jobfail: NOT TRANSLATED YET - timeout: NOT TRANSLATED YET - warning: Compruebe la información que ingresó. - sessions: - fail: Para su seguridad, la verificación de identidad de su cuenta está bloqueada - durante 24 horas. - heading: No hemos podido encontrar registros que coincidan con su información - personal. - jobfail: NOT TRANSLATED YET - timeout: NOT TRANSLATED YET - warning: Compruebe la información que ingresó. Los errores comunes son números - incorrectos de Seguro Social, código postal o fecha de nacimiento. review: dob: Fecha de nacimiento full_name: Nombre completo diff --git a/config/locales/idv/fr.yml b/config/locales/idv/fr.yml index 5770647681e..3043ace2ecd 100644 --- a/config/locales/idv/fr.yml +++ b/config/locales/idv/fr.yml @@ -37,6 +37,36 @@ fr: de cet état. unsupported_jurisdiction_sp: Veuillez visiter %{sp_name} pour accéder à votre compte. + failure: + attempts: + one: Il ne vous reste qu' strongune tentative./strong + other: Il ne vous reste que strong%{count} tentatives./strong + button: + fail: OK + jobfail: Essayez à nouveau demain + timeout: Essayez à nouveau + warning: Essayez à nouveau + errors: + link: contactez-nous + text: Si vous continuez à recevoir ces erreurs, %{link} ou réessayez demain. + phone: + fail: Pour votre sécurité, la vérification d'identité de votre compte est + verrouillée pendant 24 heures. + heading: Nous ne trouvons pas de données qui correspondent à vos informations + téléphoniques. + jobfail: NOT TRANSLATED YET + timeout: NOT TRANSLATED YET + warning: Veuillez vérifier l'information que vous avez fournie. + sessions: + fail: Pour votre sécurité, la vérification d'identité de votre compte est + verrouillée pendant 24 heures. + heading: Nous ne trouvons pas de données qui correspondent à vos informations + téléphoniques. + jobfail: NOT TRANSLATED YET + timeout: NOT TRANSLATED YET + warning: Veuillez vérifier l'information que vous avez fournie. Un numéro + de sécurité sociale, un code ZIP ou une date de naissance mal écrits sont + des erreurs communes. form: activate_by_mail: obtenir un code par courrier à la place › address1: Adresse @@ -144,36 +174,6 @@ fr: success: Elle devrait arriver dans 5 à 10 jours ouvrables. agencies_login: NOT TRANSLATED YET agency_login_html: NOT TRANSLATED YET - modal: - attempts: - one: Il ne vous reste qu' strongune tentative./strong - other: Il ne vous reste que strong%{count} tentatives./strong - button: - fail: OK - jobfail: Essayez à nouveau demain - timeout: Essayez à nouveau - warning: Essayez à nouveau - errors: - link: contactez-nous - text: Si vous continuez à recevoir ces erreurs, %{link} ou réessayez demain. - phone: - fail: Pour votre sécurité, la vérification d'identité de votre compte est - verrouillée pendant 24 heures. - heading: Nous ne trouvons pas de données qui correspondent à vos informations - téléphoniques. - jobfail: NOT TRANSLATED YET - timeout: NOT TRANSLATED YET - warning: Veuillez vérifier l'information que vous avez fournie. - sessions: - fail: Pour votre sécurité, la vérification d'identité de votre compte est - verrouillée pendant 24 heures. - heading: Nous ne trouvons pas de données qui correspondent à vos informations - téléphoniques. - jobfail: NOT TRANSLATED YET - timeout: NOT TRANSLATED YET - warning: Veuillez vérifier l'information que vous avez fournie. Un numéro - de sécurité sociale, un code ZIP ou une date de naissance mal écrits sont - des erreurs communes. review: dob: Date de naissance full_name: Nom complet diff --git a/spec/features/idv/state_id_data_spec.rb b/spec/features/idv/state_id_data_spec.rb index ce1020bdc21..b7b973727d6 100644 --- a/spec/features/idv/state_id_data_spec.rb +++ b/spec/features/idv/state_id_data_spec.rb @@ -15,7 +15,7 @@ fill_in :profile_state_id_number, with: '000000000' click_idv_continue - expect(page).to have_content t('idv.modal.sessions.warning') + expect(page).to have_content t('idv.failure.sessions.warning') expect(current_path).to eq(idv_session_failure_path(:warning, locale: locale)) end diff --git a/spec/features/idv/steps/profile_step_spec.rb b/spec/features/idv/steps/profile_step_spec.rb index f8a92becc1a..4d836f16903 100644 --- a/spec/features/idv/steps/profile_step_spec.rb +++ b/spec/features/idv/steps/profile_step_spec.rb @@ -69,7 +69,7 @@ complete_idv_steps_before_profile_step fill_out_idv_form_fail(state: state) click_continue - click_on t('idv.modal.button.warning') + click_on t('idv.failure.button.warning') end it 'populates the state from the form' do diff --git a/spec/presenters/idv/warning_presenter_spec.rb b/spec/presenters/idv/warning_presenter_spec.rb index 8fff876883c..3b5959dd02d 100644 --- a/spec/presenters/idv/warning_presenter_spec.rb +++ b/spec/presenters/idv/warning_presenter_spec.rb @@ -74,6 +74,14 @@ end end + describe '#error' do + subject { presenter.send(:error) } + + it 'includes the contact url' do + expect(subject).to include(MarketingSite.contact_url) + end + end + def mock_view_context view_context = ActionView::Base.new allow(view_context).to receive(:idv_phone_path).and_return('idv phone path') diff --git a/spec/support/idv_examples/fail_to_verify.rb b/spec/support/idv_examples/fail_to_verify.rb index b6aebae2837..2754787430e 100644 --- a/spec/support/idv_examples/fail_to_verify.rb +++ b/spec/support/idv_examples/fail_to_verify.rb @@ -16,10 +16,10 @@ it 'renders a warning failure screen and lets the user try again' do expect(page).to have_current_path(session_failure_path) if step == :profile expect(page).to have_current_path(phone_failure_path) if step == :phone - expect(page).to have_content t("idv.modal.#{step_locale_key}.heading") - expect(page).to have_content t("idv.modal.#{step_locale_key}.warning") + expect(page).to have_content t("idv.failure.#{step_locale_key}.heading") + expect(page).to have_content t("idv.failure.#{step_locale_key}.warning") - click_on t('idv.modal.button.warning') + click_on t('idv.failure.button.warning') if step == :profile fill_out_idv_form_ok diff --git a/spec/support/idv_examples/failed_idv_job.rb b/spec/support/idv_examples/failed_idv_job.rb index e513bda3ed0..0e1699cec07 100644 --- a/spec/support/idv_examples/failed_idv_job.rb +++ b/spec/support/idv_examples/failed_idv_job.rb @@ -24,8 +24,8 @@ it 'renders a jobfail failure screen' do expect(page).to have_current_path(session_failure_path(:jobfail)) if step == :profile expect(page).to have_current_path(phone_failure_path(:jobfail)) if step == :phone - expect(page).to have_content t("idv.modal.#{step_locale_key}.heading") - expect(page).to have_content t("idv.modal.#{step_locale_key}.jobfail") + expect(page).to have_content t("idv.failure.#{step_locale_key}.heading") + expect(page).to have_content t("idv.failure.#{step_locale_key}.jobfail") end end @@ -50,8 +50,8 @@ it 'renders a timeout failure page' do expect(page).to have_current_path(session_failure_path(:timeout)) if step == :profile expect(page).to have_current_path(phone_failure_path(:timeout)) if step == :phone - expect(page).to have_content t("idv.modal.#{step_locale_key}.heading") - expect(page).to have_content t("idv.modal.#{step_locale_key}.timeout") + expect(page).to have_content t("idv.failure.#{step_locale_key}.heading") + expect(page).to have_content t("idv.failure.#{step_locale_key}.timeout") end end diff --git a/spec/support/idv_examples/max_attempts.rb b/spec/support/idv_examples/max_attempts.rb index 6a4c325410c..6822cb2bbd3 100644 --- a/spec/support/idv_examples/max_attempts.rb +++ b/spec/support/idv_examples/max_attempts.rb @@ -48,7 +48,7 @@ click_link t('links.sign_in') sign_in_live_with_2fa(user) - expect(page).to_not have_content(t("idv.modal.#{step_locale_key}.heading")) + expect(page).to_not have_content(t("idv.failure.#{step_locale_key}.heading")) expect(current_url).to eq(idv_jurisdiction_url) fill_out_idv_jurisdiction_ok @@ -63,8 +63,8 @@ context 'with js', :js do scenario 'user sees the failure screen' do - expect(page).to have_content(t("idv.modal.#{step_locale_key}.heading")) - expect(page).to have_content(strip_tags(t("idv.modal.#{step_locale_key}.fail"))) + expect(page).to have_content(t("idv.failure.#{step_locale_key}.heading")) + expect(page).to have_content(strip_tags(t("idv.failure.#{step_locale_key}.fail"))) end end end @@ -75,7 +75,7 @@ fill_out_idv_form_fail if step == :profile fill_out_phone_form_fail if step == :phone click_continue - click_on t('idv.modal.button.warning') + click_on t('idv.failure.button.warning') end fill_out_idv_form_ok if step == :profile @@ -96,14 +96,14 @@ def perfom_maximum_allowed_idv_step_attempts max_attempts_less_one.times do yield click_idv_continue - click_on t('idv.modal.button.warning') + click_on t('idv.failure.button.warning') end yield click_idv_continue end def expect_user_to_be_unable_to_perform_idv(step) - expect(page).to have_content(t("idv.modal.#{step_locale_key}.heading")) if step == :phone + expect(page).to have_content(t("idv.failure.#{step_locale_key}.heading")) if step == :phone expect(page).to have_content(t('idv.titles.hardfail', app: 'login.gov')) if step == :profile expect(current_url).to eq(idv_phone_failure_url(:fail, locale: locale)) if step == :phone expect(current_url).to eq(idv_fail_url) if step == :profile From fd88f8c67b592d467f5f55d9012ce224a0155558 Mon Sep 17 00:00:00 2001 From: David Corwin Date: Wed, 20 Jun 2018 09:30:23 -0700 Subject: [PATCH 15/26] More presenter specs --- app/controllers/idv/sessions_controller.rb | 5 +- app/presenters/idv/ssn_failure_presenter.rb | 7 +- .../idv/attempt_failure_presenter_spec.rb | 28 ++++++++ .../idv/ssn_failure_presenter_spec.rb | 68 +++++++++++++++++++ 4 files changed, 100 insertions(+), 8 deletions(-) create mode 100644 spec/presenters/idv/attempt_failure_presenter_spec.rb create mode 100644 spec/presenters/idv/ssn_failure_presenter_spec.rb diff --git a/app/controllers/idv/sessions_controller.rb b/app/controllers/idv/sessions_controller.rb index c6fc075177d..549c2141fc9 100644 --- a/app/controllers/idv/sessions_controller.rb +++ b/app/controllers/idv/sessions_controller.rb @@ -84,10 +84,7 @@ def process_form_failure end def render_dupe_ssn_failure - presenter = Idv::SsnFailurePresenter.new( - decorated_session: decorated_session, - view_context: view_context - ) + presenter = Idv::SsnFailurePresenter.new(view_context: view_context) render_failure('shared/_failure', presenter) end diff --git a/app/presenters/idv/ssn_failure_presenter.rb b/app/presenters/idv/ssn_failure_presenter.rb index c5a1b206626..7250f3c9866 100644 --- a/app/presenters/idv/ssn_failure_presenter.rb +++ b/app/presenters/idv/ssn_failure_presenter.rb @@ -1,6 +1,6 @@ module Idv class SsnFailurePresenter < FailurePresenter - attr_reader :decorated_session, :view_context + attr_reader :view_context delegate :account_path, :destroy_user_session_path, @@ -9,9 +9,8 @@ class SsnFailurePresenter < FailurePresenter :t, to: :view_context - def initialize(decorated_session:, view_context:) + def initialize(view_context:) super(:failure) - @decorated_session = decorated_session @view_context = view_context end @@ -32,7 +31,7 @@ def message end def next_steps - [try_again_step, sign_out_step, profile_step].compact + [try_again_step, sign_out_step, profile_step] end private diff --git a/spec/presenters/idv/attempt_failure_presenter_spec.rb b/spec/presenters/idv/attempt_failure_presenter_spec.rb new file mode 100644 index 00000000000..716d167ab6d --- /dev/null +++ b/spec/presenters/idv/attempt_failure_presenter_spec.rb @@ -0,0 +1,28 @@ +require 'rails_helper' + +describe Idv::AttemptFailurePresenter do + let(:remaining_attempts) { 2 } + let(:step_name) { :sessions } + let(:presenter) do + described_class.new( + remaining_attempts: remaining_attempts, + step_name: step_name + ) + end + + describe 'it uses the :warning failure state' do + subject { presenter.state } + + it { is_expected.to eq(:warning) } + end + + context 'methods are overriden' do + %i[title header description].each do |method| + describe "##{method}" do + subject { presenter.send(method) } + + it { is_expected.to_not be_nil } + end + end + end +end diff --git a/spec/presenters/idv/ssn_failure_presenter_spec.rb b/spec/presenters/idv/ssn_failure_presenter_spec.rb new file mode 100644 index 00000000000..476a10cf170 --- /dev/null +++ b/spec/presenters/idv/ssn_failure_presenter_spec.rb @@ -0,0 +1,68 @@ +require 'rails_helper' + +describe Idv::SsnFailurePresenter do + let(:view_context) { mock_view_context } + let(:presenter) { described_class.new(view_context: view_context) } + + describe 'it uses the :failure failure state' do + subject { presenter.state } + + it { is_expected.to eq(:failure) } + end + + context 'methods are overriden' do + %i[title header description message].each do |method| + describe "##{method}" do + subject { presenter.send(method) } + + it { is_expected.to_not be_nil } + end + end + end + + describe '#next_steps' do + subject { presenter.next_steps } + + it 'includes `try_again_step`, `sign_out_step`, and `profile_step`' do + expect(subject).to eq( + [ + presenter.send(:try_again_step), + presenter.send(:sign_out_step), + presenter.send(:profile_step), + ] + ) + end + end + + describe '#try_again_step' do + subject { presenter.send(:try_again_step) } + + it 'includes session path' do + expect(subject).to include(view_context.idv_session_path) + end + end + + describe '#sign_out_step' do + subject { presenter.send(:sign_out_step) } + + it 'includes sign_out url' do + expect(subject).to include(view_context.destroy_user_session_path) + end + end + + describe '#profile_step' do + subject { presenter.send(:profile_step) } + + it 'includes profile url' do + expect(subject).to include(view_context.account_path) + end + end + + def mock_view_context + view_context = ActionView::Base.new + allow(view_context).to receive(:account_path).and_return('account path') + allow(view_context).to receive(:destroy_user_session_path).and_return('sign out path') + allow(view_context).to receive(:idv_session_path).and_return('idv session path') + view_context + end +end From 11539ddb940960744c50434b3e4b8d92592a90a4 Mon Sep 17 00:00:00 2001 From: David Corwin Date: Wed, 20 Jun 2018 16:04:15 -0700 Subject: [PATCH 16/26] Add failure specs to sessions controller spec --- .../idv/sessions_controller_spec.rb | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/spec/controllers/idv/sessions_controller_spec.rb b/spec/controllers/idv/sessions_controller_spec.rb index 33b14bbf594..638d8c72993 100644 --- a/spec/controllers/idv/sessions_controller_spec.rb +++ b/spec/controllers/idv/sessions_controller_spec.rb @@ -343,5 +343,25 @@ expect(response).to redirect_to(account_path) end end + + describe '#failure' do + context 'reason == :dupe_ssn' do + it 'renders the dupe_ssn failure screen' do + get :failure, params: { reason: :dupe_ssn } + + expect(response).to render_template('shared/_failure') + end + end + + context 'reason != :dupe_ssn' do + let(:reason) { :fail } + + it 'calls `render_step_failure` with step_name of :sessions and the reason' do + expect(controller).to receive(:render_idv_step_failure).with(:sessions, reason) + + get :failure, params: { reason: reason } + end + end + end end end From 551d914370f3afc7b4572c6aef73b0674553a36e Mon Sep 17 00:00:00 2001 From: David Corwin Date: Wed, 20 Jun 2018 20:41:02 -0700 Subject: [PATCH 17/26] Fix SP return urls --- app/decorators/service_provider_session_decorator.rb | 4 ++-- app/presenters/idv/idv_failure_presenter.rb | 2 +- app/presenters/idv/jurisdiction_failure_presenter.rb | 12 ++++++------ app/presenters/idv/max_attempts_failure_presenter.rb | 12 ++++++------ .../max_attempts_reached_presenter.rb | 3 +-- 5 files changed, 16 insertions(+), 17 deletions(-) diff --git a/app/decorators/service_provider_session_decorator.rb b/app/decorators/service_provider_session_decorator.rb index ae1b44ce20e..23ce09fa122 100644 --- a/app/decorators/service_provider_session_decorator.rb +++ b/app/decorators/service_provider_session_decorator.rb @@ -107,11 +107,11 @@ def sp_alert? end def sp_alert_name - sp_alert? ? SP_ALERTS[sp_name][:i18n_name] : nil + SP_ALERTS.dig(sp_name, :i18n_name) || nil end def sp_alert_learn_more - sp_alert? ? SP_ALERTS[sp_name][:learn_more] : nil + SP_ALERTS.dig(sp_name, :learn_more) || nil end private diff --git a/app/presenters/idv/idv_failure_presenter.rb b/app/presenters/idv/idv_failure_presenter.rb index e5e1c3767cf..bae0cdc260d 100644 --- a/app/presenters/idv/idv_failure_presenter.rb +++ b/app/presenters/idv/idv_failure_presenter.rb @@ -41,7 +41,7 @@ def help_step def sp_step return unless (sp_name = decorated_session.sp_name) - link = link_to(sp_name, decorated_session.sp_alert_learn_more) + link = link_to(sp_name, decorated_session.sp_return_url) t('idv.messages.jurisdiction.sp_support', link: link) end diff --git a/app/presenters/idv/jurisdiction_failure_presenter.rb b/app/presenters/idv/jurisdiction_failure_presenter.rb index db81973c6da..29e18bc0964 100644 --- a/app/presenters/idv/jurisdiction_failure_presenter.rb +++ b/app/presenters/idv/jurisdiction_failure_presenter.rb @@ -44,19 +44,19 @@ def i18n_args end def try_again_step - try_again_link = link_to(t('idv.messages.jurisdiction.try_again_link'), idv_jurisdiction_path) - t('idv.messages.jurisdiction.try_again', link: try_again_link) + link = link_to(t('idv.messages.jurisdiction.try_again_link'), idv_jurisdiction_path) + t('idv.messages.jurisdiction.try_again', link: link) end def sp_step return unless (sp_name = decorated_session.sp_name) - support_link = link_to(sp_name, decorated_session.sp_alert_learn_more) - t('idv.messages.jurisdiction.sp_support', link: support_link) + link = link_to(sp_name, decorated_session.sp_return_url) + t('idv.messages.jurisdiction.sp_support', link: link) end def profile_step - profile_link = link_to(t('idv.messages.jurisdiction.profile_link'), account_path) - t('idv.messages.jurisdiction.profile', link: profile_link) + link = link_to(t('idv.messages.jurisdiction.profile_link'), account_path) + t('idv.messages.jurisdiction.profile', link: link) end end end diff --git a/app/presenters/idv/max_attempts_failure_presenter.rb b/app/presenters/idv/max_attempts_failure_presenter.rb index 01ac4b1cfcc..33df16ab249 100644 --- a/app/presenters/idv/max_attempts_failure_presenter.rb +++ b/app/presenters/idv/max_attempts_failure_presenter.rb @@ -39,21 +39,21 @@ def next_steps def sp_step return unless (sp_name = decorated_session.sp_name) - support_link = link_to(sp_name, decorated_session.sp_alert_learn_more) - t('idv.messages.jurisdiction.sp_support', link: support_link) + link = link_to(sp_name, decorated_session.sp_return_url) + t('idv.messages.jurisdiction.sp_support', link: link) end def help_step - help_link = link_to( + link = link_to( t('idv.messages.read_about_security_and_privacy.link'), MarketingSite.help_privacy_and_security_url ) - t('idv.messages.read_about_security_and_privacy.text', link: help_link) + t('idv.messages.read_about_security_and_privacy.text', link: link) end def profile_step - profile_link = link_to(t('idv.messages.jurisdiction.profile_link'), account_path) - t('idv.messages.jurisdiction.profile', link: profile_link) + link = link_to(t('idv.messages.jurisdiction.profile_link'), account_path) + t('idv.messages.jurisdiction.profile', link: link) end end end diff --git a/app/presenters/two_factor_auth_code/max_attempts_reached_presenter.rb b/app/presenters/two_factor_auth_code/max_attempts_reached_presenter.rb index 707295ac8dd..e7e8b1cc46d 100644 --- a/app/presenters/two_factor_auth_code/max_attempts_reached_presenter.rb +++ b/app/presenters/two_factor_auth_code/max_attempts_reached_presenter.rb @@ -56,8 +56,7 @@ def read_about_two_factor_authentication MarketingSite.help_url ) - t('read_about_two_factor_authentication.text_html', - scope: T_SCOPE, link: link) + t('read_about_two_factor_authentication.text_html', scope: T_SCOPE, link: link) end end end From 66a287cbb4e30f507c684d3b5b213a708ae959b5 Mon Sep 17 00:00:00 2001 From: David Corwin Date: Wed, 20 Jun 2018 20:50:46 -0700 Subject: [PATCH 18/26] Add timeout example to moc resolution proofer --- lib/proofer_mocks/resolution_mock.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/proofer_mocks/resolution_mock.rb b/lib/proofer_mocks/resolution_mock.rb index 5e256e149b1..5dd9bfb76d5 100644 --- a/lib/proofer_mocks/resolution_mock.rb +++ b/lib/proofer_mocks/resolution_mock.rb @@ -11,6 +11,9 @@ class ResolutionMock < Proofer::Base if first_name.match?(/Bad/i) result.add_error(:first_name, 'Unverified first name.') + elsif first_name.match?(/Time/i) + sleep((Figaro.env.async_job_refresh_max_wait_seconds.to_i + 5).seconds) + elsif applicant[:ssn].match?(/6666/) result.add_error(:ssn, 'Unverified SSN.') From 4b388b2c78e378dd6ae46c6d93dd1a3379794f3e Mon Sep 17 00:00:00 2001 From: David Corwin Date: Wed, 20 Jun 2018 21:12:29 -0700 Subject: [PATCH 19/26] Fix spec --- spec/presenters/idv/idv_failure_presenter_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/presenters/idv/idv_failure_presenter_spec.rb b/spec/presenters/idv/idv_failure_presenter_spec.rb index 39ecb8c5360..d44377ff4f4 100644 --- a/spec/presenters/idv/idv_failure_presenter_spec.rb +++ b/spec/presenters/idv/idv_failure_presenter_spec.rb @@ -93,7 +93,7 @@ def mock_view_context def mock_decorated_session decorated_session = instance_double(SessionDecorator) allow(decorated_session).to receive(:sp_name).and_return('Test SP') - allow(decorated_session).to receive(:sp_alert_learn_more).and_return('SP Link') + allow(decorated_session).to receive(:sp_return_url).and_return('SP Link') decorated_session end end From 429211cda31fff7eba297243a272a5f38aa7d299 Mon Sep 17 00:00:00 2001 From: David Corwin Date: Wed, 20 Jun 2018 21:12:54 -0700 Subject: [PATCH 20/26] Fix spec again --- spec/presenters/idv/idv_failure_presenter_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/presenters/idv/idv_failure_presenter_spec.rb b/spec/presenters/idv/idv_failure_presenter_spec.rb index d44377ff4f4..fad49064627 100644 --- a/spec/presenters/idv/idv_failure_presenter_spec.rb +++ b/spec/presenters/idv/idv_failure_presenter_spec.rb @@ -71,7 +71,7 @@ subject { presenter.send(:sp_step) } it 'includes sp url' do - expect(subject).to include(decorated_session.sp_alert_learn_more) + expect(subject).to include(decorated_session.sp_return_url) end end From aa4f70520d7d82ce848e091776e7315b5e80d21d Mon Sep 17 00:00:00 2001 From: David Corwin Date: Mon, 25 Jun 2018 12:59:34 -0700 Subject: [PATCH 21/26] Exclude proofer mocks from test coverage --- .codeclimate.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.codeclimate.yml b/.codeclimate.yml index 0cefeeb427a..eb7b8ae58c3 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -90,6 +90,7 @@ plugins: exclude_patterns: - 'db/schema.rb' - 'node_modules/' + - 'lib/proofer_mocks/' - 'lib/rspec/formatters/user_flow_formatter.rb' - 'lib/tasks/create_test_accounts.rb' - 'lib/user_flow_exporter.rb' From da4ba0efee521768272a20a2e9c7da1f34186ed0 Mon Sep 17 00:00:00 2001 From: Jonathan Hooper Date: Wed, 11 Jul 2018 10:58:14 -0500 Subject: [PATCH 22/26] clean up failure urls and add form before actions --- app/controllers/idv/jurisdiction_controller.rb | 2 +- app/controllers/idv/phone_controller.rb | 7 +++++-- app/controllers/idv/sessions_controller.rb | 17 +++++++++-------- .../service_provider_session_decorator.rb | 4 ++-- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/app/controllers/idv/jurisdiction_controller.rb b/app/controllers/idv/jurisdiction_controller.rb index 20ce7f5b6cd..f3eaf1d57e8 100644 --- a/app/controllers/idv/jurisdiction_controller.rb +++ b/app/controllers/idv/jurisdiction_controller.rb @@ -22,7 +22,7 @@ def create # The only invalid result here is due to an unsupported jurisdiction # and if it is missing from the params, it will be stopped by # `strong_params`. - redirect_to idv_jurisdiction_failure_url(:unsupported_jurisdiction) + redirect_to failure_url(:unsupported_jurisdiction) end end diff --git a/app/controllers/idv/phone_controller.rb b/app/controllers/idv/phone_controller.rb index 57da1da540e..b459753b573 100644 --- a/app/controllers/idv/phone_controller.rb +++ b/app/controllers/idv/phone_controller.rb @@ -3,9 +3,12 @@ class PhoneController < ApplicationController include IdvStepConcern include IdvFailureConcern + attr_reader :idv_form + before_action :confirm_step_needed before_action :confirm_step_allowed, except: [:failure] before_action :refresh_if_not_ready, only: [:show] + before_action :set_idv_form, only: %i[new create] def new @idv_form = idv_form @@ -72,8 +75,8 @@ def confirm_step_needed redirect_to_next_step if idv_session.user_phone_confirmation == true end - def idv_form - @_idv_form ||= Idv::PhoneForm.new(idv_session.params, current_user) + def set_idv_form + @idv_form ||= Idv::PhoneForm.new(idv_session.params, current_user) end def failure_url(reason) diff --git a/app/controllers/idv/sessions_controller.rb b/app/controllers/idv/sessions_controller.rb index 549c2141fc9..bc40ff971aa 100644 --- a/app/controllers/idv/sessions_controller.rb +++ b/app/controllers/idv/sessions_controller.rb @@ -4,25 +4,26 @@ class SessionsController < ApplicationController include IdvFailureConcern include PersonalKeyConcern + attr_reader :idv_form + before_action :confirm_two_factor_authenticated, except: [:destroy] before_action :confirm_idv_attempts_allowed, except: %i[destroy success failure] before_action :confirm_idv_needed before_action :confirm_step_needed, except: %i[destroy success] before_action :initialize_idv_session, only: [:create] before_action :refresh_if_not_ready, only: [:show] + before_action :set_idv_form, only: %i[new create] delegate :attempts_exceeded?, to: :step, prefix: true def new user_session[:context] = 'idv' - @idv_form = idv_form @selected_state = user_session[:idv_jurisdiction] analytics.track_event(Analytics::IDV_BASIC_INFO_VISIT) end def create - @idv_form = idv_form - result = @idv_form.submit(profile_params) + result = idv_form.submit(profile_params) analytics.track_event(Analytics::IDV_BASIC_INFO_SUBMITTED_FORM, result.to_h) if result.success? @@ -76,9 +77,9 @@ def handle_idv_redirect end def process_form_failure - redirect_to idv_session_failure_url(:dupe_ssn) and return if @idv_form.duplicate_ssn? - if (sp_name = decorated_session.sp_name) && @idv_form.unsupported_jurisdiction? - @idv_form.add_sp_unsupported_jurisdiction_error(sp_name) + redirect_to idv_session_failure_url(:dupe_ssn) and return if idv_form.duplicate_ssn? + if (sp_name = decorated_session.sp_name) && idv_form.unsupported_jurisdiction? + idv_form.add_sp_unsupported_jurisdiction_error(sp_name) end render :new end @@ -96,8 +97,8 @@ def remaining_step_attempts Idv::Attempter.idv_max_attempts - current_user.idv_attempts end - def idv_form - @_idv_form ||= Idv::ProfileForm.new((idv_session.params || {}), current_user) + def set_idv_form + @idv_form ||= Idv::ProfileForm.new((idv_session.params || {}), current_user) end def initialize_idv_session diff --git a/app/decorators/service_provider_session_decorator.rb b/app/decorators/service_provider_session_decorator.rb index 23ce09fa122..32fc5c69ca0 100644 --- a/app/decorators/service_provider_session_decorator.rb +++ b/app/decorators/service_provider_session_decorator.rb @@ -107,11 +107,11 @@ def sp_alert? end def sp_alert_name - SP_ALERTS.dig(sp_name, :i18n_name) || nil + SP_ALERTS.dig(sp_name, :i18n_name) end def sp_alert_learn_more - SP_ALERTS.dig(sp_name, :learn_more) || nil + SP_ALERTS.dig(sp_name, :learn_more) end private From 081f08b1e8afcbe9beab45561b67ca5ba641c01d Mon Sep 17 00:00:00 2001 From: Jonathan Hooper Date: Wed, 11 Jul 2018 11:55:01 -0500 Subject: [PATCH 23/26] fix some tests --- app/controllers/idv/jurisdiction_controller.rb | 2 +- app/controllers/idv/phone_controller.rb | 4 +--- app/controllers/idv/sessions_controller.rb | 3 ++- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/app/controllers/idv/jurisdiction_controller.rb b/app/controllers/idv/jurisdiction_controller.rb index f3eaf1d57e8..880f68aa2ec 100644 --- a/app/controllers/idv/jurisdiction_controller.rb +++ b/app/controllers/idv/jurisdiction_controller.rb @@ -5,7 +5,7 @@ class JurisdictionController < ApplicationController before_action :confirm_two_factor_authenticated before_action :confirm_idv_attempts_allowed before_action :confirm_idv_needed - before_action :set_jurisdiction_form, only: %i[new create] + before_action :set_jurisdiction_form, except: [:failure] def new analytics.track_event(Analytics::IDV_JURISDICTION_VISIT) diff --git a/app/controllers/idv/phone_controller.rb b/app/controllers/idv/phone_controller.rb index b459753b573..12ddc9b101d 100644 --- a/app/controllers/idv/phone_controller.rb +++ b/app/controllers/idv/phone_controller.rb @@ -8,15 +8,13 @@ class PhoneController < ApplicationController before_action :confirm_step_needed before_action :confirm_step_allowed, except: [:failure] before_action :refresh_if_not_ready, only: [:show] - before_action :set_idv_form, only: %i[new create] + before_action :set_idv_form, except: [:failure] def new - @idv_form = idv_form analytics.track_event(Analytics::IDV_PHONE_RECORD_VISIT) end def create - @idv_form = idv_form result = @idv_form.submit(step_params) analytics.track_event(Analytics::IDV_PHONE_CONFIRMATION_FORM, result.to_h) diff --git a/app/controllers/idv/sessions_controller.rb b/app/controllers/idv/sessions_controller.rb index bc40ff971aa..a1c272411f7 100644 --- a/app/controllers/idv/sessions_controller.rb +++ b/app/controllers/idv/sessions_controller.rb @@ -12,17 +12,18 @@ class SessionsController < ApplicationController before_action :confirm_step_needed, except: %i[destroy success] before_action :initialize_idv_session, only: [:create] before_action :refresh_if_not_ready, only: [:show] - before_action :set_idv_form, only: %i[new create] delegate :attempts_exceeded?, to: :step, prefix: true def new user_session[:context] = 'idv' + set_idv_form @selected_state = user_session[:idv_jurisdiction] analytics.track_event(Analytics::IDV_BASIC_INFO_VISIT) end def create + set_idv_form result = idv_form.submit(profile_params) analytics.track_event(Analytics::IDV_BASIC_INFO_SUBMITTED_FORM, result.to_h) From b6c138437a29aae904c9e131c870eddef4dbbf46 Mon Sep 17 00:00:00 2001 From: Jonathan Hooper Date: Wed, 11 Jul 2018 14:03:45 -0500 Subject: [PATCH 24/26] reduce cognition --- spec/support/idv_examples/max_attempts.rb | 37 ++++++++++++++--------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/spec/support/idv_examples/max_attempts.rb b/spec/support/idv_examples/max_attempts.rb index 6822cb2bbd3..25fb4bdd203 100644 --- a/spec/support/idv_examples/max_attempts.rb +++ b/spec/support/idv_examples/max_attempts.rb @@ -23,13 +23,21 @@ scenario 'more than 3 attempts in 24 hours prevents further attempts' do # Blocked if visiting verify directly visit idv_url - advance_to_phone_step if step == :phone - expect_user_to_be_unable_to_perform_idv(step) + if step == :phone + advance_to_phone_step + expect_user_to_fail_at_phone_step + else + expect_user_to_fail_at_profile_step + end # Blocked if visiting from an SP visit_idp_from_sp_with_loa3(:oidc) - advance_to_phone_step if step == :phone - expect_user_to_be_unable_to_perform_idv(step) + if step == :phone + advance_to_phone_step + expect_user_to_fail_at_phone_step + else + expect_user_to_fail_at_profile_step + end if step == :sessions user.reload @@ -61,11 +69,9 @@ end end - context 'with js', :js do - scenario 'user sees the failure screen' do - expect(page).to have_content(t("idv.failure.#{step_locale_key}.heading")) - expect(page).to have_content(strip_tags(t("idv.failure.#{step_locale_key}.fail"))) - end + scenario 'user sees the failure screen' do + expect(page).to have_content(t("idv.failure.#{step_locale_key}.heading")) + expect(page).to have_content(strip_tags(t("idv.failure.#{step_locale_key}.fail"))) end end @@ -102,11 +108,14 @@ def perfom_maximum_allowed_idv_step_attempts click_idv_continue end - def expect_user_to_be_unable_to_perform_idv(step) - expect(page).to have_content(t("idv.failure.#{step_locale_key}.heading")) if step == :phone - expect(page).to have_content(t('idv.titles.hardfail', app: 'login.gov')) if step == :profile - expect(current_url).to eq(idv_phone_failure_url(:fail, locale: locale)) if step == :phone - expect(current_url).to eq(idv_fail_url) if step == :profile + def expect_user_to_fail_at_profile_step + expect(page).to have_content(t('idv.titles.hardfail', app: 'login.gov')) + expect(current_url).to eq(idv_fail_url) + end + + def expect_user_to_fail_at_phone_step + expect(page).to have_content(t("idv.failure.#{step_locale_key}.heading")) + expect(current_url).to eq(idv_phone_failure_url(:fail, locale: locale)) end def advance_to_phone_step From 9c79ef1cdd8ad7ced9d9910413e525f93374e591 Mon Sep 17 00:00:00 2001 From: Jonathan Hooper Date: Wed, 11 Jul 2018 16:12:15 -0500 Subject: [PATCH 25/26] rename other failure to verification failure --- app/controllers/concerns/idv_failure_concern.rb | 2 +- .../{other_failure.html.slim => verification_failure.html.slim} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename app/views/idv/shared/{other_failure.html.slim => verification_failure.html.slim} (100%) diff --git a/app/controllers/concerns/idv_failure_concern.rb b/app/controllers/concerns/idv_failure_concern.rb index 9eb6a4fb4e4..aedc9ff3dc3 100644 --- a/app/controllers/concerns/idv_failure_concern.rb +++ b/app/controllers/concerns/idv_failure_concern.rb @@ -10,7 +10,7 @@ def idv_step_failure_reason def render_idv_step_failure(step, reason) return render_failure('shared/_failure', failure_presenter(step)) if reason == :fail - render_failure('idv/shared/other_failure', warning_presenter(step, reason)) + render_failure('idv/shared/verification_failure', warning_presenter(step, reason)) end def render_failure(template, presenter) diff --git a/app/views/idv/shared/other_failure.html.slim b/app/views/idv/shared/verification_failure.html.slim similarity index 100% rename from app/views/idv/shared/other_failure.html.slim rename to app/views/idv/shared/verification_failure.html.slim From d8d26cba58ae729b73bad4f9b8a5f45ef1ed9bd1 Mon Sep 17 00:00:00 2001 From: David Corwin Date: Mon, 16 Jul 2018 14:36:36 -0700 Subject: [PATCH 26/26] Use the accessor for `idv_form` not the instance variable --- app/controllers/idv/phone_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/idv/phone_controller.rb b/app/controllers/idv/phone_controller.rb index 12ddc9b101d..1a6810dbf86 100644 --- a/app/controllers/idv/phone_controller.rb +++ b/app/controllers/idv/phone_controller.rb @@ -15,7 +15,7 @@ def new end def create - result = @idv_form.submit(step_params) + result = idv_form.submit(step_params) analytics.track_event(Analytics::IDV_PHONE_CONFIRMATION_FORM, result.to_h) if result.success?