diff --git a/.codeclimate.yml b/.codeclimate.yml
index 88d30880bd7..bb08cef8e3e 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'
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/controllers/concerns/idv_failure_concern.rb b/app/controllers/concerns/idv_failure_concern.rb
index b8e30cdb569..aedc9ff3dc3 100644
--- a/app/controllers/concerns/idv_failure_concern.rb
+++ b/app/controllers/concerns/idv_failure_concern.rb
@@ -1,37 +1,54 @@
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)
- 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
- end
- end
- # rubocop:enable Metrics/MethodLength
-
- def form_valid_but_vendor_validation_failed?
- idv_form.valid? && !step.vendor_validation_passed?
- end
-
- def flash_message(type:)
- flash.now[type.to_sym] = @view_model.flash_message
- end
-
- def view_model(error: nil, timed_out: nil)
- view_model_class.new(
- error: error,
+ def idv_step_failure_reason
+ return :fail if fail?
+ return :jobfail if jobfail?
+ return :timeout if timeout?
+ return :warning if warning?
+ end
+
+ def render_idv_step_failure(step, reason)
+ return render_failure('shared/_failure', failure_presenter(step)) if reason == :fail
+ render_failure('idv/shared/verification_failure', warning_presenter(step, reason))
+ end
+
+ def render_failure(template, presenter)
+ render_full_width(template, locals: { presenter: presenter })
+ end
+
+ 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,
+ step_name: step,
+ view_context: view_context
+ )
+ end
+
+ def warning_presenter(step, reason)
+ Idv::WarningPresenter.new(
+ reason: reason,
remaining_attempts: remaining_step_attempts,
- idv_form: idv_form,
- timed_out: timed_out
+ 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 83450691aaa..c0d8abd1074 100644
--- a/app/controllers/concerns/idv_session.rb
+++ b/app/controllers/concerns/idv_session.rb
@@ -8,9 +8,8 @@ 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
+ 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 5eb733b6fb9..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)
@@ -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 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
@@ -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 21583bcad8f..1a6810dbf86 100644
--- a/app/controllers/idv/phone_controller.rb
+++ b/app/controllers/idv/phone_controller.rb
@@ -3,12 +3,14 @@ class PhoneController < ApplicationController
include IdvStepConcern
include IdvFailureConcern
+ attr_reader :idv_form
+
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]
+ before_action :set_idv_form, except: [:failure]
def new
- @view_model = view_model
analytics.track_event(Analytics::IDV_PHONE_RECORD_VISIT)
end
@@ -20,7 +22,6 @@ def create
Idv::Job.submit(idv_session, [:address])
redirect_to idv_phone_result_url
else
- @view_model = view_model
render :new
end
end
@@ -30,12 +31,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 +65,6 @@ def step
)
end
- def view_model_class
- Idv::PhoneNew
- end
-
def step_params
params.require(:idv_phone_form).permit(:phone)
end
@@ -76,8 +73,12 @@ 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)
+ 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 d434f610094..a1c272411f7 100644
--- a/app/controllers/idv/sessions_controller.rb
+++ b/app/controllers/idv/sessions_controller.rb
@@ -4,8 +4,10 @@ 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]
+ 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]
@@ -15,12 +17,13 @@ class SessionsController < ApplicationController
def new
user_session[:context] = 'idv'
- @view_model = view_model
- @view_model.selected_state = user_session[:idv_jurisdiction]
+ 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)
@@ -28,7 +31,7 @@ def create
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 +39,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 +77,29 @@ 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
- render_failure
- @view_model.unsupported_jurisdiction_error(decorated_session.sp_name)
- render :new
- end
+ def render_dupe_ssn_failure
+ presenter = Idv::SsnFailurePresenter.new(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
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
@@ -107,5 +111,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 3cb8bfff2bd..32fc5c69ca0 100644
--- a/app/decorators/service_provider_session_decorator.rb
+++ b/app/decorators/service_provider_session_decorator.rb
@@ -78,10 +78,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
@@ -111,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)
end
def sp_alert_learn_more
- sp_alert? ? SP_ALERTS[sp_name][:learn_more] : nil
+ SP_ALERTS.dig(sp_name, :learn_more)
end
private
diff --git a/app/decorators/session_decorator.rb b/app/decorators/session_decorator.rb
index 923990c5a0d..8a9bf592b71 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/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..17882fa257c
--- /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.failure.#{step_name}.heading")
+ end
+
+ def header
+ t("idv.failure.#{step_name}.heading")
+ end
+
+ def description
+ t("idv.failure.#{step_name}.warning")
+ end
+ end
+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..bae0cdc260d
--- /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_return_url)
+ 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/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
new file mode 100644
index 00000000000..33df16ab249
--- /dev/null
+++ b/app/presenters/idv/max_attempts_failure_presenter.rb
@@ -0,0 +1,59 @@
+module Idv
+ class MaxAttemptsFailurePresenter < 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.failure.#{step_name}.heading")
+ end
+
+ def header
+ t("idv.failure.#{step_name}.heading")
+ end
+
+ def description
+ t("idv.failure.#{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)
+ link = link_to(sp_name, decorated_session.sp_return_url)
+ t('idv.messages.jurisdiction.sp_support', link: link)
+ end
+
+ def help_step
+ 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: 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/ssn_failure_presenter.rb b/app/presenters/idv/ssn_failure_presenter.rb
new file mode 100644
index 00000000000..7250f3c9866
--- /dev/null
+++ b/app/presenters/idv/ssn_failure_presenter.rb
@@ -0,0 +1,54 @@
+module Idv
+ class SsnFailurePresenter < FailurePresenter
+ attr_reader :view_context
+
+ delegate :account_path,
+ :destroy_user_session_path,
+ :idv_session_path,
+ :link_to,
+ :t,
+ to: :view_context
+
+ def initialize(view_context:)
+ super(:failure)
+ @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]
+ 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..7fa516466f8
--- /dev/null
+++ b/app/presenters/idv/warning_presenter.rb
@@ -0,0 +1,54 @@
+module Idv
+ class WarningPresenter < FailurePresenter
+ attr_reader :reason, :remaining_attempts, :step_name, :view_context
+
+ 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
+ @remaining_attempts = remaining_attempts
+ @step_name = step_name
+ @view_context = view_context
+ end
+
+ def title
+ t("idv.failure.#{step_name}.heading")
+ end
+
+ def header
+ t("idv.failure.#{step_name}.heading")
+ end
+
+ def description
+ t("idv.failure.#{step_name}.#{reason}")
+ end
+
+ def warning_message
+ reason == :warning ? warning : error
+ end
+
+ def button_text
+ t("idv.failure.button.#{reason}")
+ end
+
+ def button_path
+ step_name == :sessions ? idv_session_path : idv_phone_path
+ end
+
+ private
+
+ def warning
+ t('idv.failure.attempts', count: remaining_attempts)
+ end
+
+ def error
+ link = link_to(t('idv.failure.errors.link'), MarketingSite.contact_url)
+ t('idv.failure.errors.text', 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
diff --git a/app/services/marketing_site.rb b/app/services/marketing_site.rb
index fecfbe8faf6..5b763741968 100644
--- a/app/services/marketing_site.rb
+++ b/app/services/marketing_site.rb
@@ -25,4 +25,14 @@ 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/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/jurisdiction/new.html.slim b/app/views/idv/jurisdiction/new.html.slim
index 5a1303709ef..5fad74fbac7 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 sm-col-6 col-12'
diff --git a/app/views/idv/phone/new.html.slim b/app/views/idv/phone/new.html.slim
index 034afb93361..f8ace36d003 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 sm-col-6 col-12'
= 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 7221333b143..779a7f9488c 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,10 +69,9 @@ 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 sm-col-6 col-12'
= 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/verification_failure.html.slim b/app/views/idv/shared/verification_failure.html.slim
new file mode 100644
index 00000000000..34cac002f37
--- /dev/null
+++ b/app/views/idv/shared/verification_failure.html.slim
@@ -0,0 +1,5 @@
+= render 'shared/failure', presenter: presenter
+p == presenter.warning_message
+
+.mt4
+ = link_to presenter.button_text, presenter.button_path, class: 'btn btn-primary'
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/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/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 52e4a432f3e..37995f8821d 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:
@@ -32,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
@@ -77,7 +105,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:
@@ -107,6 +134,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:
@@ -131,32 +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
- 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.
- 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.
- 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 22aaa709e4a..857a9d9a386 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:
@@ -33,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. strong>
+ 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
@@ -75,7 +103,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:
@@ -107,6 +134,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:
@@ -133,32 +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. strong>
- other: Tiene usted %{count} intentos restantes.
- button:
- fail: Bueno
- jobfail: Inténtelo de nuevo mañana
- warning: Inténtelo de nuevo
- phone:
- fail: Su cuenta está bloqueada por 24 horas strong> antes de intentar
- verificarla de nuevo. Consulte nuestra sección de Ayuda para obtener más
- información sobre la verificación de identidad.
- 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 strong> antes de que
- pueda intentar verificarla de nuevo.
- 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 7f31c4748cd..3043ace2ecd 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:
@@ -38,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
@@ -81,7 +110,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:
@@ -114,6 +142,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:
@@ -143,33 +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
- 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é.
- 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.
- 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/config/routes.rb b/config/routes.rb
index c01270118fa..9935a232575 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -187,17 +187,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/lib/proofer_mocks/resolution_mock.rb b/lib/proofer_mocks/resolution_mock.rb
index 4fc373e39f0..60ad3bf31b0 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.')
diff --git a/saml_20180619025351.txt b/saml_20180619025351.txt
new file mode 100644
index 00000000000..e69de29bb2d
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..61d589fa6d9 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 3b446905f8b..0484ad4fd50 100644
--- a/spec/controllers/idv/phone_controller_spec.rb
+++ b/spec/controllers/idv/phone_controller_spec.rb
@@ -57,7 +57,7 @@
get :new
- expect(response).to redirect_to idv_fail_path
+ expect(response).to redirect_to idv_phone_failure_url(:fail)
end
end
@@ -185,8 +185,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
@@ -242,8 +241,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..638d8c72993 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
@@ -347,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
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 47f943b48d8..6336bd8da51 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..b7b973727d6 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
@@ -13,8 +15,8 @@
fill_in :profile_state_id_number, with: '000000000'
click_idv_continue
- expect(page).to have_content t('idv.modal.sessions.warning')
- expect(current_path).to eq(idv_session_result_path)
+ expect(page).to have_content t('idv.failure.sessions.warning')
+ 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 29c4cfbd80c..52c139bfcb9 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
include IdvHelper
diff --git a/spec/features/idv/steps/profile_step_spec.rb b/spec/features/idv/steps/profile_step_spec.rb
index 847c4d977a2..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_button 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/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/idv_failure_presenter_spec.rb b/spec/presenters/idv/idv_failure_presenter_spec.rb
new file mode 100644
index 00000000000..fad49064627
--- /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_return_url)
+ 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_return_url).and_return('SP Link')
+ decorated_session
+ 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
diff --git a/spec/presenters/idv/warning_presenter_spec.rb b/spec/presenters/idv/warning_presenter_spec.rb
new file mode 100644
index 00000000000..3b5959dd02d
--- /dev/null
+++ b/spec/presenters/idv/warning_presenter_spec.rb
@@ -0,0 +1,91 @@
+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
+
+ 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')
+ allow(view_context).to receive(:idv_session_path).and_return('idv session path')
+ view_context
+ end
+end
diff --git a/spec/support/idv_examples/fail_to_verify.rb b/spec/support/idv_examples/fail_to_verify.rb
index d12e7f6f31e..2754787430e 100644
--- a/spec/support/idv_examples/fail_to_verify.rb
+++ b/spec/support/idv_examples/fail_to_verify.rb
@@ -1,4 +1,5 @@
shared_examples 'fail to verify idv info' do |step|
+ let(:locale) { LinkLocaleResolver.locale }
let(:step_locale_key) do
return :sessions if step == :profile
step
@@ -12,61 +13,32 @@
click_continue
end
- 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
+ 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.failure.#{step_locale_key}.heading")
+ expect(page).to have_content t("idv.failure.#{step_locale_key}.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_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
+ click_on t('idv.failure.button.warning')
- 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
+ if step == :profile
+ fill_out_idv_form_ok
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
+ fill_out_phone_form_ok if step == :phone
+ click_idv_continue
- 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")
+ 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 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"))
- )
+ def session_failure_path
+ idv_session_failure_path(:warning, locale: locale)
end
- def dismiss_warning_modal
- click_button t('idv.modal.button.warning')
+ 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 8319acd2101..0e1699cec07 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
@@ -20,25 +21,11 @@
click_idv_continue
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
- 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 '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.failure.#{step_locale_key}.heading")
+ expect(page).to have_content t("idv.failure.#{step_locale_key}.jobfail")
end
end
@@ -60,29 +47,18 @@
Timecop.return
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
- 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
+ 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.failure.#{step_locale_key}.heading")
+ expect(page).to have_content t("idv.failure.#{step_locale_key}.timeout")
end
end
- # rubocop:disable Lint/HandleExceptions, Style/RedundantBegin
+ # 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|
@@ -93,9 +69,18 @@ def stub_idv_job_to_raise_error_in_background(idv_job_class)
end
end
end
- # rubocop:enable Lint/HandleExceptions, Style/RedundantBegin
+ # 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 ffda4afb25f..25fb4bdd203 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
@@ -22,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(sp)
+ 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(sp)
+ 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
@@ -47,7 +56,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
@@ -60,22 +69,9 @@
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"))
- )
- 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
@@ -85,6 +81,7 @@
fill_out_idv_form_fail if step == :profile
fill_out_phone_form_fail if step == :phone
click_continue
+ click_on t('idv.failure.button.warning')
end
fill_out_idv_form_ok if step == :profile
@@ -105,29 +102,22 @@ 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.failure.button.warning')
end
yield
click_idv_continue
end
- def expect_user_to_be_unable_to_perform_idv(sp)
+ def expect_user_to_fail_at_profile_step
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)
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
fill_out_idv_jurisdiction_ok
click_idv_continue
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