diff --git a/Gemfile.lock b/Gemfile.lock index 63391bcf577..3ad249f6264 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -20,10 +20,11 @@ GIT GIT remote: https://github.com/18F/identity-idp-functions.git - revision: 1ffdce9da7fd2d69de2b51a04873bc8bbd9c3f4b - ref: 1ffdce9da7fd2d69de2b51a04873bc8bbd9c3f4b + revision: d32d49bc27c62a510695c6fe498c6d9b8942f6be + ref: d32d49bc27c62a510695c6fe498c6d9b8942f6be specs: - identity-idp-functions (0.3.0) + identity-idp-functions (0.3.2) + retries (>= 0.0.5) GIT remote: https://github.com/18F/identity-lexisnexis-api-client-gem.git diff --git a/app/controllers/idv/phone_controller.rb b/app/controllers/idv/phone_controller.rb index 8e7bbd1824e..82323ac6eeb 100644 --- a/app/controllers/idv/phone_controller.rb +++ b/app/controllers/idv/phone_controller.rb @@ -9,7 +9,19 @@ class PhoneController < ApplicationController before_action :set_idv_form def new - analytics.track_event(Analytics::IDV_PHONE_RECORD_VISIT) + async_state = step.async_state + + case async_state.status + when :none + analytics.track_event(Analytics::IDV_PHONE_RECORD_VISIT) + render :new + when :in_progress + render :wait + when :timed_out + render :new + when :done + async_state_done(async_state) + end end def create @@ -17,6 +29,7 @@ def create analytics.track_event(Analytics::IDV_PHONE_CONFIRMATION_FORM, result.to_h) return render(:new) unless result.success? submit_proofing_attempt + redirect_to idv_phone_path end private @@ -34,14 +47,11 @@ def phone_confirmation_required? end def submit_proofing_attempt - idv_result = step.submit(step_params.to_h) - analytics.track_event(Analytics::IDV_PHONE_CONFIRMATION_VENDOR, idv_result.to_h) - redirect_to_next_step and return if idv_result.success? - handle_proofing_failure + step.submit(step_params.to_h) end - def handle_proofing_failure - idv_session.previous_phone_step_params = step_params.to_h + def handle_proofing_failure(pii) + idv_session.previous_phone_step_params = { 'phone' => pii[:phone] } redirect_to failure_url(step.failure_reason) end @@ -80,5 +90,12 @@ def failure_url(reason) idv_phone_errors_failure_url end end + + def async_state_done(async_state) + form_result = step.async_state_done(async_state) + analytics.track_event(Analytics::IDV_PHONE_CONFIRMATION_VENDOR, form_result.to_h) + redirect_to_next_step and return if async_state.result[:success] + handle_proofing_failure(async_state.pii) + end end end diff --git a/app/controllers/lambda_callback/address_proof_result_controller.rb b/app/controllers/lambda_callback/address_proof_result_controller.rb index e014feadf0a..01a8f40f8b7 100644 --- a/app/controllers/lambda_callback/address_proof_result_controller.rb +++ b/app/controllers/lambda_callback/address_proof_result_controller.rb @@ -3,7 +3,7 @@ class AddressProofResultController < AuthTokenController def create dcs = DocumentCaptureSession.new dcs.result_id = result_id_parameter - dcs.store_proofing_result(address_result_parameter) + dcs.store_proofing_result(address_result_parameter.to_h) end private @@ -13,7 +13,8 @@ def result_id_parameter end def address_result_parameter - params.require(:address_result) + params.require(:address_result).permit(:exception, :success, :timed_out, + errors: {}, context: {}) end def config_auth_token diff --git a/app/services/idv/agent.rb b/app/services/idv/agent.rb index 01b73acb4e9..f200fd74150 100644 --- a/app/services/idv/agent.rb +++ b/app/services/idv/agent.rb @@ -14,9 +14,19 @@ def proof_resolution(should_proof_state_id:) submit_applicant(vendor: vendor, results: results) end - def proof_address - vendor = Idv::Proofer.address_vendor.new - submit_applicant(vendor: vendor, results: init_results) + def proof_address(document_capture_session) + callback_url = Rails.application.routes.url_helpers.address_proof_result_url( + document_capture_session.result_id, + ) + + LambdaJobs::Runner.new( + job_name: nil, job_class: Idv::Proofer.address_job_class, + args: { applicant_pii: @applicant, callback_url: callback_url } + ).run do |idv_result| + document_capture_session.store_proofing_result(idv_result[:address_result]) + + nil + end end private diff --git a/app/services/idv/phone_step.rb b/app/services/idv/phone_step.rb index 3b73b76edac..75d3d02a407 100644 --- a/app/services/idv/phone_step.rb +++ b/app/services/idv/phone_step.rb @@ -7,13 +7,6 @@ def initialize(idv_session:) def submit(step_params) self.step_params = step_params proof_address - increment_attempts_count unless failed_due_to_timeout_or_exception? - success = idv_result[:success] - handle_successful_proofing_attempt if success - FormResponse.new( - success: success, errors: idv_result[:errors], - extra: extra_analytics_attributes - ) end def failure_reason @@ -23,6 +16,36 @@ def failure_reason return :warning if idv_result[:success] != true end + def async_state + dcs_uuid = idv_session.idv_phone_step_document_capture_session_uuid + dcs = DocumentCaptureSession.find_by(uuid: dcs_uuid) + return ProofingDocumentCaptureSessionResult.none if dcs_uuid.nil? + return ProofingDocumentCaptureSessionResult.timed_out if dcs.nil? + + proofing_job_result = dcs.load_proofing_result + return ProofingDocumentCaptureSessionResult.timed_out if proofing_job_result.nil? + + if proofing_job_result.result + proofing_job_result.done + elsif proofing_job_result.pii + ProofingDocumentCaptureSessionResult.in_progress + end + end + + def async_state_done(async_state) + @idv_result = async_state.result + pii = async_state.pii + + increment_attempts_count unless failed_due_to_timeout_or_exception? + success = idv_result[:success] + handle_successful_proofing_attempt(pii) if success + idv_session.idv_phone_step_document_capture_session_uuid = nil + FormResponse.new( + success: success, errors: idv_result[:errors], + extra: extra_analytics_attributes + ) + end + private attr_accessor :idv_session, :step_params, :idv_result @@ -32,13 +55,19 @@ def idv_max_attempts end def proof_address - self.idv_result = Idv::Agent.new(applicant).proof_address + document_capture_session = DocumentCaptureSession.create(user_id: idv_session.current_user.id, + requested_at: Time.zone.now) + + document_capture_session.store_proofing_pii_from_doc(applicant) + idv_session.idv_phone_step_document_capture_session_uuid = document_capture_session.uuid + + run_job(document_capture_session) add_proofing_cost end - def handle_successful_proofing_attempt - update_idv_session - start_phone_confirmation_session + def handle_successful_proofing_attempt(successful_applicant) + update_idv_session(successful_applicant) + start_phone_confirmation_session(successful_applicant) end def add_proofing_cost @@ -81,24 +110,24 @@ def failed_due_to_timeout_or_exception? idv_result[:timed_out] || idv_result[:exception] end - def update_idv_session + def update_idv_session(successful_applicant) idv_session.address_verification_mechanism = :phone - idv_session.applicant = applicant + idv_session.applicant = successful_applicant idv_session.vendor_phone_confirmation = true - idv_session.user_phone_confirmation = phone_matches_user_phone? + idv_session.user_phone_confirmation = phone_matches_user_phone?(successful_applicant[:phone]) Db::ProofingComponent::Add.call(idv_session.current_user.id, :address_check, 'lexis_nexis_address') end - def start_phone_confirmation_session + def start_phone_confirmation_session(successful_applicant) idv_session.user_phone_confirmation_session = PhoneConfirmation::ConfirmationSession.start( - phone: PhoneFormatter.format(applicant[:phone]), + phone: PhoneFormatter.format(successful_applicant[:phone]), delivery_method: :sms, ) end - def phone_matches_user_phone? - applicant_phone = PhoneFormatter.format(applicant[:phone]) + def phone_matches_user_phone?(phone) + applicant_phone = PhoneFormatter.format(phone) return false if applicant_phone.blank? user_phones.include?(applicant_phone) end @@ -116,5 +145,9 @@ def extra_analytics_attributes vendor: idv_result.except(:errors, :success), } end + + def run_job(document_capture_session) + Idv::Agent.new(applicant).proof_address(document_capture_session) + end end end diff --git a/app/services/idv/proofer.rb b/app/services/idv/proofer.rb index d3ee3814b75..deffd327b46 100644 --- a/app/services/idv/proofer.rb +++ b/app/services/idv/proofer.rb @@ -4,9 +4,14 @@ module Proofer class << self def validate_vendors! + if mock_fallback_enabled? + require 'identity-idp-functions/proof_address_mock' + else + require 'identity-idp-functions/proof_address' + end + resolution_vendor.new state_id_vendor.new - address_vendor.new end def resolution_vendor @@ -25,16 +30,14 @@ def state_id_vendor end end - def address_vendor + def address_job_class if mock_fallback_enabled? - AddressMock + IdentityIdpFunctions::ProofAddressMock else - LexisNexis::PhoneFinder::Proofer + IdentityIdpFunctions::ProofAddress end end - private - def mock_fallback_enabled? Figaro.env.proofer_mock_fallback == 'true' end diff --git a/app/services/idv/session.rb b/app/services/idv/session.rb index e3ecee3bd00..3d876638614 100644 --- a/app/services/idv/session.rb +++ b/app/services/idv/session.rb @@ -3,6 +3,7 @@ class Session VALID_SESSION_ATTRIBUTES = %i[ address_verification_mechanism applicant + idv_phone_step_document_capture_session_uuid vendor_phone_confirmation user_phone_confirmation pii diff --git a/app/services/idv/steps/verify_wait_step_show.rb b/app/services/idv/steps/verify_wait_step_show.rb index b8671306257..f7290b45366 100644 --- a/app/services/idv/steps/verify_wait_step_show.rb +++ b/app/services/idv/steps/verify_wait_step_show.rb @@ -1,26 +1,6 @@ module Idv module Steps class VerifyWaitStepShow < VerifyBaseStep - State = Struct.new(:status, :pii, :result, keyword_init: true) do - def self.none - new(status: :none) - end - - def self.timed_out - new(status: :timed_out) - end - - def self.in_progress - new(status: :in_progress) - end - - def self.done(pii:, result:) - new(status: :done, pii: pii, result: result) - end - - private_class_method :new - end - def call poll_with_meta_refresh(Figaro.env.poll_rate_for_verify_in_seconds.to_i) @@ -59,18 +39,16 @@ def async_state_done(current_async_state) def async_state dcs_uuid = flow_session[:idv_verify_step_document_capture_session_uuid] dcs = DocumentCaptureSession.find_by(uuid: dcs_uuid) - return State.none if dcs_uuid.nil? - return State.timed_out if dcs.nil? + return ProofingDocumentCaptureSessionResult.none if dcs_uuid.nil? + return ProofingDocumentCaptureSessionResult.timed_out if dcs.nil? proofing_job_result = dcs.load_proofing_result - return State.timed_out if proofing_job_result.nil? + return ProofingDocumentCaptureSessionResult.timed_out if proofing_job_result.nil? if proofing_job_result.result - proofing_job_result.result.deep_symbolize_keys! - proofing_job_result.pii.deep_symbolize_keys! - State.done(pii: proofing_job_result.pii, result: proofing_job_result.result) + proofing_job_result.done elsif proofing_job_result.pii - State.in_progress + ProofingDocumentCaptureSessionResult.in_progress end end diff --git a/app/services/lambda_jobs/git_ref.rb b/app/services/lambda_jobs/git_ref.rb index aee3bc752da..2be1cb99c01 100644 --- a/app/services/lambda_jobs/git_ref.rb +++ b/app/services/lambda_jobs/git_ref.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module LambdaJobs - GIT_REF = '1ffdce9da7fd2d69de2b51a04873bc8bbd9c3f4b' + GIT_REF = 'd32d49bc27c62a510695c6fe498c6d9b8942f6be' end diff --git a/app/services/lambda_jobs/runner.rb b/app/services/lambda_jobs/runner.rb index 46a0a6390ba..4cf5ad4ae2b 100644 --- a/app/services/lambda_jobs/runner.rb +++ b/app/services/lambda_jobs/runner.rb @@ -18,7 +18,7 @@ def run(&local_callback) ) else job_class.handle( - event: { body: args.to_json }, + event: { 'body' => args.to_json }, context: nil, &local_callback ) diff --git a/app/services/proofing_document_capture_session_result.rb b/app/services/proofing_document_capture_session_result.rb index 461e8740733..19e71feaa19 100644 --- a/app/services/proofing_document_capture_session_result.rb +++ b/app/services/proofing_document_capture_session_result.rb @@ -1,7 +1,28 @@ # frozen_string_literal: true -ProofingDocumentCaptureSessionResult = Struct.new(:id, :pii, :result, keyword_init: true) do +ProofingDocumentCaptureSessionResult = Struct.new(:id, :pii, :result, :status, + keyword_init: true) do def self.redis_key_prefix 'dcs-proofing:result' end + + def self.none + new(status: :none) + end + + def self.timed_out + new(status: :timed_out) + end + + def self.in_progress + new(status: :in_progress) + end + + def done + ProofingDocumentCaptureSessionResult.new( + pii: pii.deep_symbolize_keys, + result: result.deep_symbolize_keys, + status: :done, + ) + end end diff --git a/app/views/idv/phone/wait.html.erb b/app/views/idv/phone/wait.html.erb new file mode 100644 index 00000000000..60a35d3eef1 --- /dev/null +++ b/app/views/idv/phone/wait.html.erb @@ -0,0 +1,3 @@ +<% title t('doc_auth.titles.doc_auth') %> + +

<%= t('doc_auth.info.interstitial_eta') %>

diff --git a/config/application.yml.default b/config/application.yml.default index e755331c90c..b1359692559 100644 --- a/config/application.yml.default +++ b/config/application.yml.default @@ -108,6 +108,7 @@ pinpoint_voice_longcode_pool: pinpoint_voice_region: poll_rate_for_verify_in_seconds: '10' proofer_mock_fallback: 'true' +proofing_lambda_http_callback: push_notifications_enabled: reauthn_window: '120' recaptcha_enabled_percent: '0' @@ -207,6 +208,7 @@ development: otp_delivery_blocklist_maxretry: '10' participate_in_dap: password_pepper: f22d4b2cafac9066fe2f4416f5b7a32c + proofing_lambda_http_callback: 'true' identity_pki_disabled: 'false' identity_pki_local_dev: 'true' piv_cac_service_url: https://localhost:8443/ @@ -321,6 +323,7 @@ production: piv_cac_service_url: piv_cac_verify_token_secret: piv_cac_verify_token_url: + proofing_lambda_http_callback: rack_mini_profiler: recurring_jobs_disabled_names: "[]" redis_throttle_url: redis://redis.login.gov.internal:6379/1 @@ -430,6 +433,7 @@ test: piv_cac_service_url: https://localhost:8443/ piv_cac_verify_token_secret: 3ac13bfa23e22adae321194c083e783faf89469f6f85dcc0802b27475c94b5c3891b5657bd87d0c1ad65de459166440512f2311018db90d57b15d8ab6660748f piv_cac_verify_token_url: https://localhost:8443/ + proofing_lambda_http_callback: false rack_mini_profiler: recurring_jobs_disabled_names: '["disabled job"]' redis_throttle_url: redis://localhost:6379/1 diff --git a/lib/proofer_mocks/address_mock.rb b/lib/proofer_mocks/address_mock.rb index d43734bdec5..e69de29bb2d 100644 --- a/lib/proofer_mocks/address_mock.rb +++ b/lib/proofer_mocks/address_mock.rb @@ -1,19 +0,0 @@ -class AddressMock < Proofer::Base - required_attributes :phone - - optional_attributes :uuid, :uuid_prefix - - stage :address - - proof do |applicant, result| - plain_phone = applicant[:phone].gsub(/\D/, '').gsub(/\A1/, '') - if plain_phone == '7035555555' - result.add_error(:phone, 'The phone number could not be verified.') - elsif plain_phone == '7035555999' - raise 'Failed to contact proofing vendor' - elsif plain_phone == '7035555888' - raise Proofer::TimeoutError, 'address mock timeout' - end - result.context[:message] = 'some context for the mock address proofer' - end -end diff --git a/spec/controllers/idv/phone_controller_spec.rb b/spec/controllers/idv/phone_controller_spec.rb index 816b931190b..0dd9b50c871 100644 --- a/spec/controllers/idv/phone_controller_spec.rb +++ b/spec/controllers/idv/phone_controller_spec.rb @@ -5,6 +5,9 @@ let(:max_attempts) { idv_max_attempts } let(:good_phone) { '+1 (703) 555-0000' } + let(:bad_phone) do + IdentityIdpFunctions::AddressMockClient::UNVERIFIABLE_PHONE_NUMBER + end let(:normalized_phone) { '7035550000' } let(:bad_phone) { '+1 (703) 555-5555' } @@ -61,6 +64,29 @@ expect(response).to redirect_to idv_phone_errors_failure_url end + + it 'shows phone form if async process times out' do + # setting the document capture session to a nonexistent uuid will trigger async + # timed_out behavior + subject.idv_session.idv_phone_step_document_capture_session_uuid = 'abc123' + + get :new + expect(response).to render_template :new + end + + it 'shows waiting interstitial if async process is in progress' do + # having a document capture session with PII but without results will trigger + # in progress behavior + document_capture_session = DocumentCaptureSession.create(user_id: user.id, + requested_at: Time.zone.now) + document_capture_session.store_proofing_pii_from_doc({}) + + subject.idv_session.idv_phone_step_document_capture_session_uuid = + document_capture_session.uuid + + get :new + expect(response).to render_template :wait + end end describe '#create' do @@ -133,6 +159,8 @@ put :create, params: { idv_phone_form: { phone: good_phone } } + expect(response).to redirect_to idv_phone_path + get :new expect(response).to redirect_to idv_review_path expected_applicant = { @@ -140,7 +168,7 @@ last_name: 'One', phone: normalized_phone, uuid_prefix: nil, - }.with_indifferent_access + } expect(subject.idv_session.applicant).to eq expected_applicant expect(subject.idv_session.vendor_phone_confirmation).to eq true @@ -157,6 +185,8 @@ put :create, params: { idv_phone_form: { phone: good_phone } } + expect(response).to redirect_to idv_phone_path + get :new expect(response).to redirect_to idv_otp_delivery_method_path expect(subject.idv_session.vendor_phone_confirmation).to eq true @@ -186,6 +216,8 @@ ) put :create, params: { idv_phone_form: { phone: good_phone } } + expect(response).to redirect_to idv_phone_path + get :new end end @@ -194,9 +226,11 @@ user = build(:user, with: { phone: '+1 (415) 555-0130', phone_confirmed_at: Time.zone.now }) stub_verify_steps_one_and_two(user) - put :create, params: { idv_phone_form: { phone: '7035555555' } } + put :create, params: { idv_phone_form: { phone: bad_phone } } - expect(response).to redirect_to idv_phone_errors_warning_url + expect(response).to redirect_to idv_phone_path + get :new + expect(response).to redirect_to idv_phone_errors_warning_path expect(subject.idv_session.vendor_phone_confirmation).to be_falsy expect(subject.idv_session.user_phone_confirmation).to be_falsy @@ -221,11 +255,15 @@ expect(@analytics).to receive(:track_event).ordered.with( Analytics::IDV_PHONE_CONFIRMATION_FORM, hash_including(:success) ) + + put :create, params: { idv_phone_form: { phone: bad_phone } } + expect(@analytics).to receive(:track_event).ordered.with( Analytics::IDV_PHONE_CONFIRMATION_VENDOR, result ) + expect(response).to redirect_to idv_phone_path - put :create, params: { idv_phone_form: { phone: '7035555555' } } + get :new end end end diff --git a/spec/controllers/lambda_callback/address_proof_result_controller_spec.rb b/spec/controllers/lambda_callback/address_proof_result_controller_spec.rb index dd25ebde6b8..d5b4fb0ccce 100644 --- a/spec/controllers/lambda_callback/address_proof_result_controller_spec.rb +++ b/spec/controllers/lambda_callback/address_proof_result_controller_spec.rb @@ -12,19 +12,24 @@ it 'accepts and stores successful address proofing results' do applicant = { phone: Faker::PhoneNumber.cell_phone } document_capture_session.store_proofing_pii_from_doc(applicant) - proofer_result = AddressMock.new.proof(applicant) + Idv::Agent.new(applicant).proof_address(document_capture_session) + proofer_result = document_capture_session.load_proofing_result[:result] post :create, params: { result_id: document_capture_session.result_id, address_result: proofer_result.to_h } proofing_result = document_capture_session.load_proofing_result - expect(proofing_result.result).to eq({ exception: '', success: 'true' }) + expect(proofing_result.result).to include({ exception: '', success: 'true' }) end it 'accepts and stores unsuccessful address proofing results' do - applicant = { phone: '7035555555' } + applicant = { + phone: IdentityIdpFunctions::AddressMockClient::UNVERIFIABLE_PHONE_NUMBER, + } + document_capture_session.store_proofing_pii_from_doc(applicant) - proofer_result = AddressMock.new.proof(applicant) + Idv::Agent.new(applicant).proof_address(document_capture_session) + proofer_result = document_capture_session.load_proofing_result[:result] post :create, params: { result_id: document_capture_session.result_id, address_result: proofer_result.to_h } diff --git a/spec/services/idv/agent_spec.rb b/spec/services/idv/agent_spec.rb index f16ea841cb1..48f31878630 100644 --- a/spec/services/idv/agent_spec.rb +++ b/spec/services/idv/agent_spec.rb @@ -2,6 +2,9 @@ require 'ostruct' describe Idv::Agent do + let(:bad_phone) do + IdentityIdpFunctions::AddressMockClient::UNVERIFIABLE_PHONE_NUMBER + end describe 'instance' do let(:applicant) { { foo: 'bar' } } @@ -100,16 +103,20 @@ end describe '#proof_address' do + let(:document_capture_session) { DocumentCaptureSession.new(result_id: 'abc123') } + it 'proofs addresses successfully with valid information' do agent = Idv::Agent.new({ phone: Faker::PhoneNumber.cell_phone }) - result = agent.proof_address + agent.proof_address(document_capture_session) + result = document_capture_session.load_proofing_result[:result] expect(result[:context][:stages]).to include({ address: 'AddressMock' }) expect(result[:success]).to eq true end it 'fails to proof addresses with invalid information' do - agent = Idv::Agent.new({ phone: '7035555555' }) - result = agent.proof_address + agent = Idv::Agent.new(phone: bad_phone) + agent.proof_address(document_capture_session) + result = document_capture_session.load_proofing_result[:result] expect(result[:context][:stages]).to include({ address: 'AddressMock' }) expect(result[:success]).to eq false end diff --git a/spec/services/idv/phone_step_spec.rb b/spec/services/idv/phone_step_spec.rb index 1b3a5316b33..152146de8fa 100644 --- a/spec/services/idv/phone_step_spec.rb +++ b/spec/services/idv/phone_step_spec.rb @@ -17,9 +17,15 @@ idvs end let(:good_phone) { '2255555000' } - let(:bad_phone) { '7035555555' } - let(:fail_phone) { '7035555999' } - let(:timeout_phone) { '7035555888' } + let(:bad_phone) do + IdentityIdpFunctions::AddressMockClient::UNVERIFIABLE_PHONE_NUMBER + end + let(:fail_phone) do + IdentityIdpFunctions::AddressMockClient::FAILED_TO_CONTACT_PHONE_NUMBER + end + let(:timeout_phone) do + IdentityIdpFunctions::AddressMockClient::PROOFER_TIMEOUT_PHONE_NUMBER + end subject { described_class.new(idv_session: idv_session) } @@ -28,8 +34,10 @@ context = { stages: [{ address: 'AddressMock' }] } extra = { vendor: { messages: [], context: context, exception: nil, timed_out: false } } - result = subject.submit(phone: good_phone) + subject.submit(phone: good_phone) + expect(subject.async_state.status).to eq :done + result = subject.async_state_done(subject.async_state) expect(result).to be_kind_of(FormResponse) expect(result.success?).to eq(true) expect(result.errors).to be_empty @@ -44,7 +52,9 @@ context = { stages: [{ address: 'AddressMock' }] } extra = { vendor: { messages: [], context: context, exception: nil, timed_out: false } } - result = subject.submit(phone: bad_phone) + subject.submit(phone: bad_phone) + expect(subject.async_state.status).to eq :done + result = subject.async_state_done(subject.async_state) expect(result).to be_kind_of(FormResponse) expect(result.success?).to eq(false) @@ -59,6 +69,8 @@ original_step_attempts = idv_session.step_attempts[:phone] subject.submit(phone: bad_phone) + expect(subject.async_state.status).to eq :done + _result = subject.async_state_done(subject.async_state) expect(idv_session.step_attempts[:phone]).to eq(original_step_attempts + 1) end @@ -82,14 +94,19 @@ it 'marks the phone as confirmed if it matches 2FA phone' do user.phone_configurations = [build(:phone_configuration, user: user, phone: good_phone)] - result = subject.submit(phone: good_phone) + subject.submit(phone: good_phone) + expect(subject.async_state.status).to eq :done + result = subject.async_state_done(subject.async_state) + expect(result.success?).to eq(true) expect(idv_session.vendor_phone_confirmation).to eq(true) expect(idv_session.user_phone_confirmation).to eq(true) end it 'does not mark the phone as confirmed if it does not match 2FA phone' do - result = subject.submit(phone: good_phone) + subject.submit(phone: good_phone) + expect(subject.async_state.status).to eq :done + result = subject.async_state_done(subject.async_state) expect(result.success?).to eq(true) expect(idv_session.vendor_phone_confirmation).to eq(true) @@ -101,6 +118,8 @@ context 'when there are idv attempts remaining' do it 'returns :warning' do subject.submit(phone: bad_phone) + expect(subject.async_state.status).to eq :done + _result = subject.async_state_done(subject.async_state) expect(subject.failure_reason).to eq(:warning) end @@ -111,6 +130,8 @@ idv_session.step_attempts[:phone] = idv_max_attempts - 1 subject.submit(phone: bad_phone) + expect(subject.async_state.status).to eq :done + _result = subject.async_state_done(subject.async_state) expect(subject.failure_reason).to eq(:fail) end @@ -119,6 +140,8 @@ context 'when the vendor raises a timeout exception' do it 'returns :timeout' do subject.submit(phone: timeout_phone) + expect(subject.async_state.status).to eq :done + _result = subject.async_state_done(subject.async_state) expect(subject.failure_reason).to eq(:timeout) end @@ -127,6 +150,8 @@ context 'when the vendor raises an exception' do it 'returns :jobfail' do subject.submit(phone: fail_phone) + expect(subject.async_state.status).to eq :done + _result = subject.async_state_done(subject.async_state) expect(subject.failure_reason).to eq(:jobfail) end diff --git a/spec/services/idv/proofer_spec.rb b/spec/services/idv/proofer_spec.rb index a03f07bf34f..2cb299e9770 100644 --- a/spec/services/idv/proofer_spec.rb +++ b/spec/services/idv/proofer_spec.rb @@ -50,44 +50,13 @@ end end - describe '.address_vendor' do - context 'with mock proofers enabled' do - let(:proofer_mock_fallback) { 'true' } - - it 'returns the mock vendor' do - expect(subject.address_vendor).to eq(AddressMock) - end - end - - context 'with mock proofers disabled' do - before do - class_double('LexisNexis::PhoneFinder::Proofer', new: {}).as_stubbed_const - end - it 'returns the live vendor' do - expect(subject.address_vendor).to eq(LexisNexis::PhoneFinder::Proofer) - end - end - end - describe '.validate_vendors!' do let(:proofer_mock_fallback) { 'false' } - context 'with vendors configured for each stage' do - before do - class_double('LexisNexis::InstantVerify::Proofer', new: {}).as_stubbed_const - class_double('LexisNexis::PhoneFinder::Proofer', new: {}).as_stubbed_const - class_double('Aamva::Proofer', new: {}).as_stubbed_const - end - - it 'does not raise' do - expect { described_class.validate_vendors! }.to_not raise_error - end - end - context 'without vendors configured for each stage' do it 'does raise' do expect { described_class.validate_vendors! }.to raise_error( - NameError, + LoadError, ) end end diff --git a/spec/services/lambda_jobs/runner_spec.rb b/spec/services/lambda_jobs/runner_spec.rb index ce50fff8b91..0028eb11f20 100644 --- a/spec/services/lambda_jobs/runner_spec.rb +++ b/spec/services/lambda_jobs/runner_spec.rb @@ -56,7 +56,7 @@ it 'calls JobClass.handle' do expect(job_class).to receive(:handle).with( - event: { body: args.to_json }, + event: { 'body' => args.to_json }, context: nil, ) @@ -70,7 +70,7 @@ it 'calls JobClass.handle' do expect(job_class).to receive(:handle).with( - event: { body: args.to_json }, + event: { 'body' => args.to_json }, context: nil, ) @@ -82,7 +82,7 @@ result = Object.new expect(job_class).to receive(:handle).with( - event: { body: args.to_json }, + event: { 'body' => args.to_json }, context: nil, ).and_yield(result) diff --git a/spec/support/idv_examples/failed_idv_job.rb b/spec/support/idv_examples/failed_idv_job.rb index d813faa5bcf..e0f9e5037a4 100644 --- a/spec/support/idv_examples/failed_idv_job.rb +++ b/spec/support/idv_examples/failed_idv_job.rb @@ -46,7 +46,8 @@ def fill_out_idv_form_error end def fill_out_phone_form_error - fill_in :idv_phone_form_phone, with: '7035555999' + fill_in :idv_phone_form_phone, with: + IdentityIdpFunctions::AddressMockClient::FAILED_TO_CONTACT_PHONE_NUMBER end def fill_out_idv_form_timeout @@ -55,7 +56,8 @@ def fill_out_idv_form_timeout end def fill_out_phone_form_timeout - fill_in :idv_phone_form_phone, with: '7035555888' + fill_in :idv_phone_form_phone, with: + IdentityIdpFunctions::AddressMockClient::PROOFER_TIMEOUT_PHONE_NUMBER end def session_timeout_path