diff --git a/app/forms/idv/api_image_upload_form.rb b/app/forms/idv/api_image_upload_form.rb index e697dca995f..da58035e1c1 100644 --- a/app/forms/idv/api_image_upload_form.rb +++ b/app/forms/idv/api_image_upload_form.rb @@ -207,7 +207,7 @@ def update_analytics(client_response) client_image_metrics: image_metadata, async: false, flow_path: params[:flow_path], - ).merge(native_camera_ab_test_data), + ).merge(native_camera_ab_test_data, acuant_sdk_upgrade_ab_test_data), ) pii_from_doc = client_response.pii_from_doc || {} store_encrypted_images_if_required @@ -250,6 +250,14 @@ def native_camera_ab_test_data } end + def acuant_sdk_upgrade_ab_test_data + return {} unless IdentityConfig.store.idv_acuant_sdk_upgrade_a_b_testing_enabled + { + acuant_sdk_upgrade_ab_test_bucket: + AbTests::ACUANT_SDK.bucket(document_capture_session.uuid), + } + end + def acuant_sdk_capture? image_metadata.dig(:front, :source) == Idp::Constants::Vendors::ACUANT && image_metadata.dig(:back, :source) == Idp::Constants::Vendors::ACUANT diff --git a/app/javascript/packages/document-capture/context/index.ts b/app/javascript/packages/document-capture/context/index.ts index 37e07f4a857..e3aaaf74af7 100644 --- a/app/javascript/packages/document-capture/context/index.ts +++ b/app/javascript/packages/document-capture/context/index.ts @@ -20,3 +20,7 @@ export { default as NativeCameraABTestContext, Provider as NativeCameraABTestContextProvider, } from './native-camera-a-b-test'; +export { + default as AcuantSdkUpgradeABTestContext, + Provider as AcuantSdkUpgradeABTestContextProvider, +} from './native-camera-a-b-test'; diff --git a/app/javascript/packs/document-capture.tsx b/app/javascript/packs/document-capture.tsx index 77c27c45334..1d86b87ca0b 100644 --- a/app/javascript/packs/document-capture.tsx +++ b/app/javascript/packs/document-capture.tsx @@ -30,6 +30,9 @@ interface AppRootData { maxAttemptsBeforeNativeCamera: string; nativeCameraABTestingEnabled: string; nativeCameraOnly: string; + acuantSdkUpgradeABTestingEnabled: string; + useNewerSdk: string; + acuantVersion: string; flowPath: FlowPath; cancelUrl: string; idvInPersonUrl?: string; @@ -67,8 +70,15 @@ function getMetaContent(name): string | null { const device: DeviceContextValue = { isMobile: isCameraCapableMobile() }; const trackEvent: typeof baseTrackEvent = (event, payload) => { - const { flowPath } = appRoot.dataset; - return baseTrackEvent(event, { ...payload, flow_path: flowPath }); + const { flowPath, acuantSdkUpgradeABTestingEnabled, useNewerSdk, acuantVersion } = + appRoot.dataset; + return baseTrackEvent(event, { + ...payload, + flow_path: flowPath, + acuant_sdk_upgrade_a_b_testing_enabled: acuantSdkUpgradeABTestingEnabled, + use_newer_sdk: useNewerSdk, + acuant_version: acuantVersion, + }); }; (async () => { @@ -110,6 +120,7 @@ const trackEvent: typeof baseTrackEvent = (event, payload) => { maxSubmissionAttemptsBeforeNativeCamera, nativeCameraABTestingEnabled, nativeCameraOnly, + acuantVersion, appName, flowPath, cancelUrl: cancelURL, @@ -125,6 +136,8 @@ const trackEvent: typeof baseTrackEvent = (event, payload) => { [ AcuantContextProvider, { + sdkSrc: acuantVersion && `/acuant/${acuantVersion}/AcuantJavascriptWebSdk.min.js`, + cameraSrc: acuantVersion && `/acuant/${acuantVersion}/AcuantCamera.min.js`, credentials: getMetaContent('acuant-sdk-initialization-creds'), endpoint: getMetaContent('acuant-sdk-initialization-endpoint'), glareThreshold, diff --git a/app/services/idv/steps/document_capture_step.rb b/app/services/idv/steps/document_capture_step.rb index 6768145303a..2f55173fbfe 100644 --- a/app/services/idv/steps/document_capture_step.rb +++ b/app/services/idv/steps/document_capture_step.rb @@ -29,7 +29,7 @@ def extra_view_variables image_type: 'back', transaction_id: flow_session[:document_capture_session_uuid], ), - }.merge(native_camera_ab_testing_variables) + }.merge(native_camera_ab_testing_variables, acuant_sdk_upgrade_a_b_testing_variables) end private @@ -44,6 +44,17 @@ def native_camera_ab_testing_variables } end + def acuant_sdk_upgrade_a_b_testing_variables + bucket = AbTests::ACUANT_SDK.bucket(flow_session[:document_capture_session_uuid]) + acuant_version = (bucket == :use_newer_sdk) ? '11.7.1' : '11.7.0' + { + acuant_sdk_upgrade_a_b_testing_enabled: + IdentityConfig.store.idv_acuant_sdk_upgrade_a_b_testing_enabled, + use_newer_sdk: (bucket == :use_newer_sdk), + acuant_version: acuant_version, + } + end + def handle_stored_result if stored_result&.success? save_proofing_components diff --git a/app/views/idv/capture_doc/document_capture.html.erb b/app/views/idv/capture_doc/document_capture.html.erb index 164a21290d4..1de574ab186 100644 --- a/app/views/idv/capture_doc/document_capture.html.erb +++ b/app/views/idv/capture_doc/document_capture.html.erb @@ -8,4 +8,7 @@ back_image_upload_url: back_image_upload_url, native_camera_a_b_testing_enabled: native_camera_a_b_testing_enabled, native_camera_only: native_camera_only, + acuant_sdk_upgrade_a_b_testing_enabled: acuant_sdk_upgrade_a_b_testing_enabled, + use_newer_sdk: use_newer_sdk, + acuant_version: acuant_version, ) %> diff --git a/app/views/idv/doc_auth/document_capture.html.erb b/app/views/idv/doc_auth/document_capture.html.erb index c4978d730fe..561f3d73f9f 100644 --- a/app/views/idv/doc_auth/document_capture.html.erb +++ b/app/views/idv/doc_auth/document_capture.html.erb @@ -8,4 +8,7 @@ back_image_upload_url: back_image_upload_url, native_camera_a_b_testing_enabled: native_camera_a_b_testing_enabled, native_camera_only: native_camera_only, + acuant_sdk_upgrade_a_b_testing_enabled: acuant_sdk_upgrade_a_b_testing_enabled, + use_newer_sdk: use_newer_sdk, + acuant_version: acuant_version, ) %> diff --git a/app/views/idv/shared/_document_capture.html.erb b/app/views/idv/shared/_document_capture.html.erb index 422fad97332..0fba2ebffdc 100644 --- a/app/views/idv/shared/_document_capture.html.erb +++ b/app/views/idv/shared/_document_capture.html.erb @@ -33,6 +33,9 @@ max_submission_attempts_before_native_camera: IdentityConfig.store.doc_auth_max_submission_attempts_before_native_camera, native_camera_a_b_testing_enabled: native_camera_a_b_testing_enabled, native_camera_only: native_camera_only, + acuant_sdk_upgrade_a_b_testing_enabled: acuant_sdk_upgrade_a_b_testing_enabled, + use_newer_sdk: use_newer_sdk, + acuant_version: acuant_version, sp_name: sp_name, flow_path: flow_path, cancel_url: idv_cancel_path, diff --git a/config/application.yml.default b/config/application.yml.default index 91df708da7d..0e6edaaba86 100644 --- a/config/application.yml.default +++ b/config/application.yml.default @@ -116,6 +116,8 @@ idv_max_attempts: 5 idv_min_age_years: 13 idv_native_camera_a_b_testing_enabled: false idv_native_camera_a_b_testing_percent: 10 +idv_acuant_sdk_upgrade_a_b_testing_enabled: false +idv_acuant_sdk_upgrade_a_b_testing_percent: 50 idv_send_link_attempt_window_in_minutes: 10 idv_send_link_max_attempts: 5 ie11_support_end_date: '2022-12-31' diff --git a/config/initializers/ab_tests.rb b/config/initializers/ab_tests.rb index b57d5a84526..6125a36e840 100644 --- a/config/initializers/ab_tests.rb +++ b/config/initializers/ab_tests.rb @@ -18,4 +18,11 @@ module AbTests nil, }.compact, ) + + ACUANT_SDK = AbTestBucket.new( + experiment_name: 'Acuant SDK Upgrade', + buckets: { + use_newer_sdk: IdentityConfig.store.idv_acuant_sdk_upgrade_a_b_testing_percent, + }, + ) end diff --git a/lib/identity_config.rb b/lib/identity_config.rb index e3a734946ae..01ecd4e571b 100644 --- a/lib/identity_config.rb +++ b/lib/identity_config.rb @@ -195,6 +195,8 @@ def self.build_store(config_map) config.add(:idv_min_age_years, type: :integer) config.add(:idv_native_camera_a_b_testing_enabled, type: :boolean) config.add(:idv_native_camera_a_b_testing_percent, type: :integer) + config.add(:idv_acuant_sdk_upgrade_a_b_testing_enabled, type: :boolean) + config.add(:idv_acuant_sdk_upgrade_a_b_testing_percent, type: :integer) config.add(:idv_send_link_attempt_window_in_minutes, type: :integer) config.add(:idv_send_link_max_attempts, type: :integer) config.add(:idv_sp_required, type: :boolean) diff --git a/spec/controllers/idv/image_uploads_controller_spec.rb b/spec/controllers/idv/image_uploads_controller_spec.rb index c9aa52b010b..15af7eaedbb 100644 --- a/spec/controllers/idv/image_uploads_controller_spec.rb +++ b/spec/controllers/idv/image_uploads_controller_spec.rb @@ -20,6 +20,8 @@ before do Funnel::DocAuth::RegisterStep.new(user.id, '').call('welcome', :view, true) + allow(IdentityConfig.store).to receive(:idv_acuant_sdk_upgrade_a_b_testing_enabled). + and_return(false) end context 'when fields are missing' do diff --git a/spec/features/idv/analytics_spec.rb b/spec/features/idv/analytics_spec.rb index 94860e939e0..0d2d5395f55 100644 --- a/spec/features/idv/analytics_spec.rb +++ b/spec/features/idv/analytics_spec.rb @@ -147,6 +147,8 @@ and_return(fake_analytics) allow(IdentityConfig.store).to receive(:idv_native_camera_a_b_testing_enabled). and_return(false) + allow(IdentityConfig.store).to receive(:idv_acuant_sdk_upgrade_a_b_testing_enabled). + and_return(false) end context 'Happy path' do diff --git a/spec/javascripts/packages/document-capture/components/acuant-capture-spec.jsx b/spec/javascripts/packages/document-capture/components/acuant-capture-spec.jsx index 757150649d8..05e48b828de 100644 --- a/spec/javascripts/packages/document-capture/components/acuant-capture-spec.jsx +++ b/spec/javascripts/packages/document-capture/components/acuant-capture-spec.jsx @@ -958,16 +958,16 @@ describe('document-capture/components/acuant-capture', () => { const upload = getByText('Upload'); fireEvent.click(upload); - expect(trackEvent).to.have.been.calledThrice(); - expect(trackEvent.getCall(0)).to.have.been.calledWith('IdV: test image clicked', { + expect(trackEvent.callCount).to.be.at.least(3); + expect(trackEvent).to.have.been.calledWith('IdV: test image clicked', { source: 'placeholder', isDrop: false, }); - expect(trackEvent.getCall(1)).to.have.been.calledWith('IdV: test image clicked', { + expect(trackEvent).to.have.been.calledWith('IdV: test image clicked', { source: 'button', isDrop: false, }); - expect(trackEvent.getCall(2)).to.have.been.calledWith('IdV: test image clicked', { + expect(trackEvent).to.have.been.calledWith('IdV: test image clicked', { source: 'upload', isDrop: false, }); @@ -986,7 +986,7 @@ describe('document-capture/components/acuant-capture', () => { const input = getByLabelText('Image'); fireEvent.drop(input); - expect(trackEvent.getCall(0)).to.have.been.calledWith('IdV: test image clicked', { + expect(trackEvent).to.have.been.calledWith('IdV: test image clicked', { source: 'placeholder', isDrop: true, }); diff --git a/spec/services/idv/steps/document_capture_step_spec.rb b/spec/services/idv/steps/document_capture_step_spec.rb index 5573ce4ed48..11ccd9a1ec1 100644 --- a/spec/services/idv/steps/document_capture_step_spec.rb +++ b/spec/services/idv/steps/document_capture_step_spec.rb @@ -75,5 +75,47 @@ expect(subject.extra_view_variables[:native_camera_only]).to eq(true) end end + + context 'with acuant sdk upgrade A/B testing enabled' do + let(:session_uuid) { SecureRandom.uuid } + + before do + allow(IdentityConfig.store). + to receive(:idv_acuant_sdk_upgrade_a_b_testing_enabled). + and_return(true) + + flow.flow_session[:document_capture_session_uuid] = session_uuid + end + + context 'and A/B test specifies the newer acuant version' do + before do + stub_const( + 'AbTests::ACUANT_SDK', + FakeAbTestBucket.new.tap { |ab| ab.assign(session_uuid => :use_newer_sdk) }, + ) + end + + it 'passes correct variables and acuant version when newer is specified' do + expect(subject.extra_view_variables[:acuant_sdk_upgrade_a_b_testing_enabled]).to eq(true) + expect(subject.extra_view_variables[:use_newer_sdk]).to eq(true) + expect(subject.extra_view_variables[:acuant_version]).to eq('11.7.1') + end + end + + context 'and A/B test specifies the older acuant version' do + before do + stub_const( + 'AbTests::ACUANT_SDK', + FakeAbTestBucket.new.tap { |ab| ab.assign(session_uuid => 0) }, + ) + end + + it 'passes correct variables and acuant version when older is specified' do + expect(subject.extra_view_variables[:acuant_sdk_upgrade_a_b_testing_enabled]).to eq(true) + expect(subject.extra_view_variables[:use_newer_sdk]).to eq(false) + expect(subject.extra_view_variables[:acuant_version]).to eq('11.7.0') + end + end + end end end diff --git a/spec/views/idv/shared/_document_capture.html.erb_spec.rb b/spec/views/idv/shared/_document_capture.html.erb_spec.rb index f8817ef4e6b..52d5b8e8259 100644 --- a/spec/views/idv/shared/_document_capture.html.erb_spec.rb +++ b/spec/views/idv/shared/_document_capture.html.erb_spec.rb @@ -15,6 +15,9 @@ let(:back_image_upload_url) { nil } let(:native_camera_a_b_testing_enabled) { false } let(:native_camera_only) { false } + let(:acuant_sdk_upgrade_a_b_testing_enabled) { false } + let(:use_newer_sdk) { false } + let(:acuant_version) { '11.7.1' } before do decorated_session = instance_double( @@ -48,6 +51,9 @@ back_image_upload_url: back_image_upload_url, native_camera_a_b_testing_enabled: native_camera_a_b_testing_enabled, native_camera_only: native_camera_only, + acuant_sdk_upgrade_a_b_testing_enabled: acuant_sdk_upgrade_a_b_testing_enabled, + use_newer_sdk: use_newer_sdk, + acuant_version: acuant_version, } end