@smileid/usesmileid 12.0.0 → 12.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/README.md +1 -1
- package/dist/camera/camera_defaults.d.ts +2 -0
- package/dist/camera/camera_defaults.d.ts.map +1 -1
- package/dist/camera/camera_defaults.js +2 -0
- package/dist/camera/camera_defaults.js.map +1 -1
- package/dist/core/exception/agent_mode_with_enhanced_liveness_exception.d.ts +11 -0
- package/dist/core/exception/agent_mode_with_enhanced_liveness_exception.d.ts.map +1 -0
- package/dist/core/exception/agent_mode_with_enhanced_liveness_exception.js +17 -0
- package/dist/core/exception/agent_mode_with_enhanced_liveness_exception.js.map +1 -0
- package/dist/core/exception/capture_validation_exceptions.d.ts +1 -0
- package/dist/core/exception/capture_validation_exceptions.d.ts.map +1 -1
- package/dist/core/exception/capture_validation_exceptions.js +1 -0
- package/dist/core/exception/capture_validation_exceptions.js.map +1 -1
- package/dist/core/exception/flow_exceptions.d.ts +4 -2
- package/dist/core/exception/flow_exceptions.d.ts.map +1 -1
- package/dist/core/exception/flow_exceptions.js +3 -2
- package/dist/core/exception/flow_exceptions.js.map +1 -1
- package/dist/core/exception/index.d.ts +1 -0
- package/dist/core/exception/index.d.ts.map +1 -1
- package/dist/core/exception/index.js +1 -0
- package/dist/core/exception/index.js.map +1 -1
- package/dist/core/exception/missing_job_type_exception.d.ts +1 -3
- package/dist/core/exception/missing_job_type_exception.d.ts.map +1 -1
- package/dist/core/exception/missing_job_type_exception.js +2 -4
- package/dist/core/exception/missing_job_type_exception.js.map +1 -1
- package/dist/core/exception/use_smile_id_error_code.d.ts +1 -0
- package/dist/core/exception/use_smile_id_error_code.d.ts.map +1 -1
- package/dist/core/exception/use_smile_id_error_code.js +1 -0
- package/dist/core/exception/use_smile_id_error_code.js.map +1 -1
- package/dist/core/models/config.d.ts +19 -0
- package/dist/core/models/config.d.ts.map +1 -1
- package/dist/core/models/document_type.d.ts +1 -1
- package/dist/core/models/document_type.d.ts.map +1 -1
- package/dist/core/models/document_type.js +2 -2
- package/dist/core/models/document_type.js.map +1 -1
- package/dist/core/models/global_privacy_control.d.ts +36 -0
- package/dist/core/models/global_privacy_control.d.ts.map +1 -0
- package/dist/core/models/global_privacy_control.js +39 -0
- package/dist/core/models/global_privacy_control.js.map +1 -0
- package/dist/core/models/network_config.d.ts +2 -2
- package/dist/core/models/network_config.js +2 -2
- package/dist/data/api/interceptors/smile_auth_interceptor.d.ts.map +1 -1
- package/dist/data/api/interceptors/smile_auth_interceptor.js +3 -17
- package/dist/data/api/interceptors/smile_auth_interceptor.js.map +1 -1
- package/dist/data/api/smile_id_api.d.ts +5 -1
- package/dist/data/api/smile_id_api.d.ts.map +1 -1
- package/dist/data/api/smile_id_api.js +30 -27
- package/dist/data/api/smile_id_api.js.map +1 -1
- package/dist/data/dsl/builder/retry_config_builder.d.ts +4 -4
- package/dist/data/dsl/builder/retry_config_builder.d.ts.map +1 -1
- package/dist/data/dsl/builder/retry_config_builder.js +6 -6
- package/dist/data/dsl/builder/retry_config_builder.js.map +1 -1
- package/dist/data/model/job_request.d.ts +28 -12
- package/dist/data/model/job_request.d.ts.map +1 -1
- package/dist/data/model/token_payload.d.ts +78 -0
- package/dist/data/model/token_payload.d.ts.map +1 -0
- package/dist/data/model/token_payload.js +132 -0
- package/dist/data/model/token_payload.js.map +1 -0
- package/dist/data/model/user_details_payload.d.ts +39 -0
- package/dist/data/model/user_details_payload.d.ts.map +1 -0
- package/dist/data/model/user_details_payload.js +53 -0
- package/dist/data/model/user_details_payload.js.map +1 -0
- package/dist/data/smile_id_urls.d.ts +1 -1
- package/dist/data/smile_id_urls.js +1 -1
- package/dist/data/smile_id_urls.js.map +1 -1
- package/dist/data/util/retry_util.d.ts +1 -1
- package/dist/data/util/retry_util.d.ts.map +1 -1
- package/dist/data/util/retry_util.js +5 -0
- package/dist/data/util/retry_util.js.map +1 -1
- package/dist/data/util/use_smile_id_token_decoder.d.ts +15 -3
- package/dist/data/util/use_smile_id_token_decoder.d.ts.map +1 -1
- package/dist/data/util/use_smile_id_token_decoder.js +20 -8
- package/dist/data/util/use_smile_id_token_decoder.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/l10n/strings_en.d.ts +4 -1
- package/dist/l10n/strings_en.d.ts.map +1 -1
- package/dist/l10n/strings_en.js +4 -1
- package/dist/l10n/strings_en.js.map +1 -1
- package/dist/l10n/use_smile_id_localizations.d.ts +10 -0
- package/dist/l10n/use_smile_id_localizations.d.ts.map +1 -1
- package/dist/l10n/use_smile_id_localizations.js +59 -3
- package/dist/l10n/use_smile_id_localizations.js.map +1 -1
- package/dist/metadata/builder_configuration.d.ts +5 -0
- package/dist/metadata/builder_configuration.d.ts.map +1 -1
- package/dist/metadata/builder_configuration.js +1 -0
- package/dist/metadata/builder_configuration.js.map +1 -1
- package/dist/metadata/metadata_configuration_mappers.d.ts +2 -3
- package/dist/metadata/metadata_configuration_mappers.d.ts.map +1 -1
- package/dist/metadata/metadata_configuration_mappers.js +13 -6
- package/dist/metadata/metadata_configuration_mappers.js.map +1 -1
- package/dist/metadata/use_smile_id_metadata_factory.d.ts.map +1 -1
- package/dist/metadata/use_smile_id_metadata_factory.js +14 -5
- package/dist/metadata/use_smile_id_metadata_factory.js.map +1 -1
- package/dist/presentation/components/use_smile_id_button.d.ts.map +1 -1
- package/dist/presentation/components/use_smile_id_button.js +8 -2
- package/dist/presentation/components/use_smile_id_button.js.map +1 -1
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.d.ts +5 -2
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.d.ts.map +1 -1
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.js +8 -3
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.js.map +1 -1
- package/dist/presentation/components/use_smile_id_instructions_hero.d.ts.map +1 -1
- package/dist/presentation/components/use_smile_id_instructions_hero.js +8 -3
- package/dist/presentation/components/use_smile_id_instructions_hero.js.map +1 -1
- package/dist/presentation/flow/dsl/builder/config_builder.d.ts +16 -0
- package/dist/presentation/flow/dsl/builder/config_builder.d.ts.map +1 -1
- package/dist/presentation/flow/dsl/builder/config_builder.js +18 -0
- package/dist/presentation/flow/dsl/builder/config_builder.js.map +1 -1
- package/dist/presentation/flow/dsl/builder/screens_builder.d.ts +6 -12
- package/dist/presentation/flow/dsl/builder/screens_builder.d.ts.map +1 -1
- package/dist/presentation/flow/dsl/builder/screens_builder.js +7 -12
- package/dist/presentation/flow/dsl/builder/screens_builder.js.map +1 -1
- package/dist/presentation/flow/dsl/use_smile_id_flow_builder.d.ts.map +1 -1
- package/dist/presentation/flow/dsl/use_smile_id_flow_builder.js +23 -1
- package/dist/presentation/flow/dsl/use_smile_id_flow_builder.js.map +1 -1
- package/dist/presentation/flow/flow_navigation_manager.d.ts +22 -3
- package/dist/presentation/flow/flow_navigation_manager.d.ts.map +1 -1
- package/dist/presentation/flow/flow_navigation_manager.js +84 -46
- package/dist/presentation/flow/flow_navigation_manager.js.map +1 -1
- package/dist/presentation/flow/model/instructions_defaults.d.ts.map +1 -1
- package/dist/presentation/flow/model/instructions_defaults.js +1 -1
- package/dist/presentation/flow/model/instructions_defaults.js.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_capture_screen.d.ts.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_capture_screen.js +13 -3
- package/dist/presentation/flow/screen/orchestrated_capture_screen.js.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_consent_screen.d.ts.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_consent_screen.js +3 -1
- package/dist/presentation/flow/screen/orchestrated_consent_screen.js.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_preview_screen.d.ts.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_preview_screen.js +0 -8
- package/dist/presentation/flow/screen/orchestrated_preview_screen.js.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_processing_screen.d.ts.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_processing_screen.js +25 -5
- package/dist/presentation/flow/screen/orchestrated_processing_screen.js.map +1 -1
- package/dist/presentation/flow/use_smile_id_flow.d.ts.map +1 -1
- package/dist/presentation/flow/use_smile_id_flow.js +45 -12
- package/dist/presentation/flow/use_smile_id_flow.js.map +1 -1
- package/dist/presentation/flow/validation/flow_validator.d.ts +16 -2
- package/dist/presentation/flow/validation/flow_validator.d.ts.map +1 -1
- package/dist/presentation/flow/validation/flow_validator.js +61 -47
- package/dist/presentation/flow/validation/flow_validator.js.map +1 -1
- package/dist/presentation/flow/validation/job_type_validator.d.ts +7 -0
- package/dist/presentation/flow/validation/job_type_validator.d.ts.map +1 -1
- package/dist/presentation/flow/validation/job_type_validator.js +52 -27
- package/dist/presentation/flow/validation/job_type_validator.js.map +1 -1
- package/dist/presentation/flow/validation/user_details_validator.d.ts +9 -0
- package/dist/presentation/flow/validation/user_details_validator.d.ts.map +1 -0
- package/dist/presentation/flow/validation/user_details_validator.js +40 -0
- package/dist/presentation/flow/validation/user_details_validator.js.map +1 -0
- package/dist/presentation/screen/helpers/capture_screen_helpers.d.ts.map +1 -1
- package/dist/presentation/screen/helpers/capture_screen_helpers.js +1 -0
- package/dist/presentation/screen/helpers/capture_screen_helpers.js.map +1 -1
- package/dist/presentation/screen/helpers/capture_ui_state.d.ts +6 -6
- package/dist/presentation/screen/helpers/capture_ui_state.d.ts.map +1 -1
- package/dist/presentation/screen/helpers/capture_ui_state.js +19 -19
- package/dist/presentation/screen/helpers/capture_ui_state.js.map +1 -1
- package/dist/presentation/screen/helpers/ess_turn_haptics.d.ts +2 -2
- package/dist/presentation/screen/helpers/ess_turn_haptics.d.ts.map +1 -1
- package/dist/presentation/screen/helpers/ess_turn_haptics.js +6 -6
- package/dist/presentation/screen/helpers/ess_turn_haptics.js.map +1 -1
- package/dist/presentation/screen/helpers/scan_state_to_overlay_state.d.ts +5 -5
- package/dist/presentation/screen/helpers/scan_state_to_overlay_state.d.ts.map +1 -1
- package/dist/presentation/screen/helpers/scan_state_to_overlay_state.js +11 -11
- package/dist/presentation/screen/helpers/scan_state_to_overlay_state.js.map +1 -1
- package/dist/presentation/screen/helpers/use_capture_orientation_lock.d.ts +13 -3
- package/dist/presentation/screen/helpers/use_capture_orientation_lock.d.ts.map +1 -1
- package/dist/presentation/screen/helpers/use_capture_orientation_lock.js +48 -6
- package/dist/presentation/screen/helpers/use_capture_orientation_lock.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_capture_screen.d.ts +4 -2
- package/dist/presentation/screen/use_smile_id_capture_screen.d.ts.map +1 -1
- package/dist/presentation/screen/use_smile_id_capture_screen.js +90 -23
- package/dist/presentation/screen/use_smile_id_capture_screen.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_consent_screen.d.ts +7 -0
- package/dist/presentation/screen/use_smile_id_consent_screen.d.ts.map +1 -1
- package/dist/presentation/screen/use_smile_id_consent_screen.js +6 -5
- package/dist/presentation/screen/use_smile_id_consent_screen.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_document_back_instructions.d.ts.map +1 -1
- package/dist/presentation/screen/use_smile_id_document_back_instructions.js +5 -13
- package/dist/presentation/screen/use_smile_id_document_back_instructions.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_document_preview_screen.js +1 -1
- package/dist/presentation/screen/use_smile_id_document_preview_screen.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_preview_screen.d.ts +1 -21
- package/dist/presentation/screen/use_smile_id_preview_screen.d.ts.map +1 -1
- package/dist/presentation/screen/use_smile_id_preview_screen.js +3 -14
- package/dist/presentation/screen/use_smile_id_preview_screen.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_processing_screen.js +1 -1
- package/dist/presentation/screen/use_smile_id_processing_screen.js.map +1 -1
- package/dist/presentation/utils/locale_utils.d.ts +10 -4
- package/dist/presentation/utils/locale_utils.d.ts.map +1 -1
- package/dist/presentation/utils/locale_utils.js +13 -5
- package/dist/presentation/utils/locale_utils.js.map +1 -1
- package/dist/testing/fake_face_analyzer.d.ts +43 -0
- package/dist/testing/fake_face_analyzer.d.ts.map +1 -0
- package/dist/testing/fake_face_analyzer.js +52 -0
- package/dist/testing/fake_face_analyzer.js.map +1 -0
- package/dist/testing/index.d.ts +5 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +7 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/scenario_expectations.d.ts +28 -0
- package/dist/testing/scenario_expectations.d.ts.map +1 -0
- package/dist/testing/scenario_expectations.js +65 -0
- package/dist/testing/scenario_expectations.js.map +1 -0
- package/dist/testing/scenario_loader.d.ts +11 -0
- package/dist/testing/scenario_loader.d.ts.map +1 -0
- package/dist/testing/scenario_loader.js +64 -0
- package/dist/testing/scenario_loader.js.map +1 -0
- package/dist/testing/scripted_scan_results.d.ts +17 -0
- package/dist/testing/scripted_scan_results.d.ts.map +1 -0
- package/dist/testing/scripted_scan_results.js +52 -0
- package/dist/testing/scripted_scan_results.js.map +1 -0
- package/package.json +11 -4
- package/src/__tests__/dsl.test.ts +51 -1
- package/src/__tests__/react_native_mock.tsx +22 -0
- package/src/__tests__/setup_react_native.ts +17 -2
- package/src/__tests__/snapshots/__snapshots__/screens_structural.test.tsx.snap +5267 -0
- package/src/__tests__/snapshots/screens_structural.test.tsx +230 -0
- package/src/camera/__tests__/camera_permissions.test.ts +72 -0
- package/src/camera/__tests__/camera_system_focus.test.ts +173 -0
- package/src/camera/__tests__/use_smile_id_camera_preview.test.tsx +461 -0
- package/src/camera/__tests__/use_smile_id_camera_system.test.ts +103 -0
- package/src/camera/__tests__/use_smile_id_frame_stream_hook.test.tsx +229 -0
- package/src/camera/camera_defaults.ts +3 -0
- package/src/core/exception/__tests__/builder_validation_exceptions.test.ts +81 -0
- package/src/core/exception/agent_mode_with_enhanced_liveness_exception.ts +20 -0
- package/src/core/exception/capture_validation_exceptions.ts +1 -0
- package/src/core/exception/flow_exceptions.test.ts +10 -0
- package/src/core/exception/flow_exceptions.ts +3 -2
- package/src/core/exception/index.ts +1 -0
- package/src/core/exception/missing_job_type_exception.ts +2 -4
- package/src/core/exception/use_smile_id_error_code.ts +1 -0
- package/src/core/models/__tests__/document_type.test.ts +2 -2
- package/src/core/models/__tests__/flow_models.test.ts +26 -0
- package/src/core/models/config.ts +22 -0
- package/src/core/models/document_type.ts +2 -2
- package/src/core/models/global_privacy_control.ts +45 -0
- package/src/core/models/network_config.ts +2 -2
- package/src/data/api/__tests__/smile_id_api.test.ts +275 -1
- package/src/data/api/interceptors/__tests__/credential_header_redaction.test.ts +144 -0
- package/src/data/api/interceptors/__tests__/gzip_interceptor.test.ts +83 -0
- package/src/data/api/interceptors/smile_auth_interceptor.ts +3 -18
- package/src/data/api/smile_id_api.ts +36 -49
- package/src/data/compression/__tests__/payload_compressor_real_jpeg.test.ts +6 -2
- package/src/data/dsl/__tests__/use_smile_id_network_builder.test.ts +157 -0
- package/src/data/dsl/builder/__tests__/config_builders.test.ts +62 -0
- package/src/data/dsl/builder/retry_config_builder.ts +6 -6
- package/src/data/factory/__tests__/retry_gzip_mac_composition.test.ts +163 -0
- package/src/data/factory/__tests__/signed_job_submission_headers.test.ts +1 -1
- package/src/data/model/__tests__/token_payload.test.ts +224 -0
- package/src/data/model/__tests__/user_details_payload.test.ts +100 -0
- package/src/data/model/job_request.ts +27 -12
- package/src/data/model/token_payload.ts +182 -0
- package/src/data/model/user_details_payload.ts +84 -0
- package/src/data/repository/__tests__/network_retries.test.ts +1 -1
- package/src/data/repository/__tests__/repository_dispatch.test.ts +366 -0
- package/src/data/repository/__tests__/use_smile_id_repository.test.ts +1 -1
- package/src/data/security/__tests__/request_canonicalizer.test.ts +132 -0
- package/src/data/security/__tests__/signing_crypto.test.ts +203 -0
- package/src/data/smile_id_urls.ts +1 -1
- package/src/data/util/__tests__/retry_util.test.ts +25 -0
- package/src/data/util/__tests__/use_smile_id_token_decoder.test.ts +179 -0
- package/src/data/util/retry_util.ts +9 -1
- package/src/data/util/use_smile_id_token_decoder.ts +29 -8
- package/src/index.ts +6 -4
- package/src/l10n/__tests__/use_smile_id_localizations.test.ts +122 -5
- package/src/l10n/__tests__/use_smile_id_localizations_provider.test.tsx +112 -0
- package/src/l10n/__tests__/use_smile_id_localizations_surface.test.ts +231 -0
- package/src/l10n/strings_en.ts +5 -1
- package/src/l10n/use_smile_id_localizations.ts +80 -3
- package/src/metadata/__tests__/device_orientation_sampling.test.ts +165 -0
- package/src/metadata/__tests__/geolocation.test.ts +150 -0
- package/src/metadata/__tests__/metadata_configuration_mappers.test.ts +39 -0
- package/src/metadata/__tests__/metadata_configuration_objects.test.ts +2 -1
- package/src/metadata/__tests__/metadata_device_context.test.ts +3 -3
- package/src/metadata/__tests__/metadata_device_os_android.test.ts +18 -0
- package/src/metadata/__tests__/metadata_golden_fixture.json +1 -1
- package/src/metadata/__tests__/metadata_payload_golden.test.ts +4 -4
- package/src/metadata/__tests__/optional_native_modules.test.ts +234 -0
- package/src/metadata/__tests__/use_smile_id_metadata.test.ts +1 -1
- package/src/metadata/__tests__/use_smile_id_metadata_factory.test.ts +615 -0
- package/src/metadata/builder_configuration.ts +6 -0
- package/src/metadata/metadata_configuration_mappers.ts +21 -7
- package/src/metadata/use_smile_id_metadata_factory.ts +17 -6
- package/src/presentation/assets/si_document_green_book_hero_animation.json +1 -4668
- package/src/presentation/assets/si_document_hero_animation.json +1 -4799
- package/src/presentation/assets/si_document_hero_back_animation.json +1 -2039
- package/src/presentation/assets/si_document_passport_hero_animation.json +1 -14491
- package/src/presentation/assets/si_ess_all_directions_hero_animation.json +1 -0
- package/src/presentation/assets/si_ess_animation_all_directions.json +1 -6589
- package/src/presentation/assets/si_selfie_hero_animation.json +1 -1439
- package/src/presentation/assets/si_smile_to_capture_animation.json +1 -1439
- package/src/presentation/components/__tests__/use_smile_id_content_card.test.tsx +112 -0
- package/src/presentation/components/__tests__/use_smile_id_enhanced_smart_selfie_clip.test.tsx +9 -4
- package/src/presentation/components/__tests__/use_smile_id_face_oval_image.test.tsx +190 -0
- package/src/presentation/components/__tests__/use_smile_id_instructions_hero.test.tsx +44 -0
- package/src/presentation/components/__tests__/use_smile_id_learn_more_content.test.tsx +159 -0
- package/src/presentation/components/__tests__/use_smile_id_processing_center_indicator.test.tsx +88 -0
- package/src/presentation/components/use_smile_id_button.tsx +7 -2
- package/src/presentation/components/use_smile_id_enhanced_smart_selfie_clip.tsx +9 -3
- package/src/presentation/components/use_smile_id_instructions_hero.tsx +10 -0
- package/src/presentation/flow/__tests__/document_flow_navigation.test.ts +3 -3
- package/src/presentation/flow/__tests__/flow_navigation_manager.test.ts +372 -1
- package/src/presentation/flow/__tests__/use_smile_id_flow.test.tsx +651 -0
- package/src/presentation/flow/dsl/__tests__/use_smile_id_builder_component.test.tsx +120 -0
- package/src/presentation/flow/dsl/builder/__tests__/config_builder.test.ts +25 -0
- package/src/presentation/flow/dsl/builder/config_builder.ts +21 -0
- package/src/presentation/flow/dsl/builder/screens_builder.ts +7 -12
- package/src/presentation/flow/dsl/use_smile_id_flow_builder.ts +27 -1
- package/src/presentation/flow/flow_navigation_manager.ts +108 -93
- package/src/presentation/flow/graph/__tests__/screen_renderer.test.tsx +102 -0
- package/src/presentation/flow/model/instructions_defaults.ts +1 -1
- package/src/presentation/flow/screen/__tests__/orchestrated_capture_screen.test.tsx +836 -0
- package/src/presentation/flow/screen/__tests__/orchestrated_consent_screen.test.tsx +165 -0
- package/src/presentation/flow/screen/__tests__/orchestrated_instructions_screen.test.tsx +163 -0
- package/src/presentation/flow/screen/__tests__/orchestrated_preview_screen.test.tsx +224 -0
- package/src/presentation/flow/screen/__tests__/orchestrated_processing_screen.test.tsx +338 -0
- package/src/presentation/flow/screen/orchestrated_capture_screen.tsx +18 -3
- package/src/presentation/flow/screen/orchestrated_consent_screen.tsx +5 -0
- package/src/presentation/flow/screen/orchestrated_preview_screen.tsx +0 -12
- package/src/presentation/flow/screen/orchestrated_processing_screen.tsx +42 -5
- package/src/presentation/flow/use_smile_id_flow.tsx +63 -12
- package/src/presentation/flow/validation/__tests__/flow_validator.test.ts +219 -1
- package/src/presentation/flow/validation/__tests__/job_type_validator.test.ts +200 -0
- package/src/presentation/flow/validation/flow_validator.ts +85 -57
- package/src/presentation/flow/validation/job_type_validator.ts +73 -39
- package/src/presentation/flow/validation/user_details_validator.ts +53 -0
- package/src/presentation/screen/__tests__/capture_ui_state.test.ts +66 -47
- package/src/presentation/screen/__tests__/ess_turn_haptics.test.ts +15 -11
- package/src/presentation/screen/__tests__/feedback_copy_table.test.ts +145 -0
- package/src/presentation/screen/__tests__/scan_state_to_overlay_state.test.ts +47 -27
- package/src/presentation/screen/__tests__/use_smile_id_capture_screen.test.tsx +524 -14
- package/src/presentation/screen/__tests__/use_smile_id_document_back_instructions.test.tsx +4 -2
- package/src/presentation/screen/__tests__/use_smile_id_permission_screen.test.tsx +68 -0
- package/src/presentation/screen/__tests__/use_smile_id_preview_screen.test.tsx +10 -40
- package/src/presentation/screen/helpers/__tests__/use_capture_orientation_lock.test.tsx +212 -0
- package/src/presentation/screen/helpers/capture_screen_helpers.ts +1 -0
- package/src/presentation/screen/helpers/capture_ui_state.ts +27 -27
- package/src/presentation/screen/helpers/ess_turn_haptics.ts +9 -9
- package/src/presentation/screen/helpers/scan_state_to_overlay_state.ts +13 -13
- package/src/presentation/screen/helpers/use_capture_orientation_lock.ts +69 -7
- package/src/presentation/screen/use_smile_id_capture_screen.tsx +107 -28
- package/src/presentation/screen/use_smile_id_consent_screen.tsx +16 -5
- package/src/presentation/screen/use_smile_id_document_back_instructions.tsx +14 -23
- package/src/presentation/screen/use_smile_id_document_preview_screen.tsx +1 -1
- package/src/presentation/screen/use_smile_id_preview_screen.tsx +13 -45
- package/src/presentation/screen/use_smile_id_processing_screen.tsx +1 -1
- package/src/presentation/theme/__tests__/use_use_smile_id_fonts.test.tsx +166 -0
- package/src/presentation/utils/__tests__/locale_utils.test.ts +46 -5
- package/src/presentation/utils/locale_utils.ts +13 -4
- package/src/testing/__tests__/fake_face_analyzer.test.ts +42 -0
- package/src/testing/__tests__/scenario_expectations.test.ts +110 -0
- package/src/testing/__tests__/scenario_loader.test.ts +64 -0
- package/src/testing/fake_face_analyzer.ts +82 -0
- package/src/testing/index.ts +15 -0
- package/src/testing/scenario_expectations.ts +87 -0
- package/src/testing/scenario_loader.ts +83 -0
- package/src/testing/scripted_scan_results.ts +66 -0
- package/dist/presentation/components/use_smile_id_face_silhouette_overlay.d.ts +0 -15
- package/dist/presentation/components/use_smile_id_face_silhouette_overlay.d.ts.map +0 -1
- package/dist/presentation/components/use_smile_id_face_silhouette_overlay.js +0 -19
- package/dist/presentation/components/use_smile_id_face_silhouette_overlay.js.map +0 -1
- package/src/presentation/components/use_smile_id_face_silhouette_overlay.tsx +0 -27
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { create as createRenderer, act } from "react-test-renderer";
|
|
4
|
+
|
|
5
|
+
// `vi.mock` is hoisted above the imports, so anything its factory closes over
|
|
6
|
+
// must be created with `vi.hoisted` or it is still in the TDZ when the factory
|
|
7
|
+
// runs.
|
|
8
|
+
const { captureException, screenProps } = vi.hoisted(() => ({
|
|
9
|
+
captureException: vi.fn(),
|
|
10
|
+
screenProps: { current: {} as Record<string, unknown> },
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
vi.mock("@smileid/usesmileid_bridge", async () => {
|
|
14
|
+
const actual =
|
|
15
|
+
await vi.importActual<typeof import("@smileid/usesmileid_bridge")>(
|
|
16
|
+
"@smileid/usesmileid_bridge",
|
|
17
|
+
);
|
|
18
|
+
return {
|
|
19
|
+
...actual,
|
|
20
|
+
UseSmileIDCrashReporting: { captureException },
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Stand in for the leaf screen so these tests exercise the orchestration
|
|
25
|
+
// (consent storage, partner hook, navigation) rather than re-testing the
|
|
26
|
+
// consent UI, which has its own component suite.
|
|
27
|
+
vi.mock("../../../screen/use_smile_id_consent_screen", () => ({
|
|
28
|
+
UseSmileIDConsentScreen: (props: Record<string, unknown>) => {
|
|
29
|
+
screenProps.current = props;
|
|
30
|
+
return null;
|
|
31
|
+
},
|
|
32
|
+
}));
|
|
33
|
+
|
|
34
|
+
import { OrchestratedConsentScreen } from "../orchestrated_consent_screen";
|
|
35
|
+
import { FlowNavigationProvider } from "../../flow_navigation_context";
|
|
36
|
+
import { ConsentDeniedException } from "../../../../core/exception";
|
|
37
|
+
import { GlobalPrivacyControl } from "../../../../core/models/global_privacy_control";
|
|
38
|
+
import type { FlowNavigationManager } from "../../flow_navigation_manager";
|
|
39
|
+
import type { ConsentInformation } from "../../../../core/models/params";
|
|
40
|
+
|
|
41
|
+
function makeManager(overrides: Record<string, unknown> = {}) {
|
|
42
|
+
return {
|
|
43
|
+
setConsent: vi.fn(),
|
|
44
|
+
exit: vi.fn(),
|
|
45
|
+
navigateToNext: vi.fn(),
|
|
46
|
+
navigateBack: vi.fn(),
|
|
47
|
+
configuration: { config: {} },
|
|
48
|
+
...overrides,
|
|
49
|
+
} as unknown as FlowNavigationManager & {
|
|
50
|
+
setConsent: ReturnType<typeof vi.fn>;
|
|
51
|
+
exit: ReturnType<typeof vi.fn>;
|
|
52
|
+
navigateToNext: ReturnType<typeof vi.fn>;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function renderWith(
|
|
57
|
+
manager: FlowNavigationManager,
|
|
58
|
+
configuration: Record<string, unknown> = {},
|
|
59
|
+
) {
|
|
60
|
+
act(() => {
|
|
61
|
+
createRenderer(
|
|
62
|
+
<FlowNavigationProvider manager={manager}>
|
|
63
|
+
<OrchestratedConsentScreen
|
|
64
|
+
configuration={
|
|
65
|
+
configuration as React.ComponentProps<
|
|
66
|
+
typeof OrchestratedConsentScreen
|
|
67
|
+
>["configuration"]
|
|
68
|
+
}
|
|
69
|
+
/>
|
|
70
|
+
</FlowNavigationProvider>,
|
|
71
|
+
);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const consent: ConsentInformation = {
|
|
76
|
+
consentGrantedDate: "2026-07-30T00:00:00.000Z",
|
|
77
|
+
personalDetailsConsentGranted: true,
|
|
78
|
+
contactInformationConsentGranted: true,
|
|
79
|
+
documentInformationConsentGranted: true,
|
|
80
|
+
} as ConsentInformation;
|
|
81
|
+
|
|
82
|
+
describe("OrchestratedConsentScreen", () => {
|
|
83
|
+
beforeEach(() => {
|
|
84
|
+
captureException.mockClear();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("stores consent before advancing so the next screen can read it", () => {
|
|
88
|
+
const manager = makeManager();
|
|
89
|
+
const order: string[] = [];
|
|
90
|
+
(manager.setConsent as ReturnType<typeof vi.fn>).mockImplementation(() =>
|
|
91
|
+
order.push("setConsent"),
|
|
92
|
+
);
|
|
93
|
+
(manager.navigateToNext as ReturnType<typeof vi.fn>).mockImplementation(
|
|
94
|
+
() => order.push("navigateToNext"),
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
renderWith(manager, { partnerName: "Acme" });
|
|
98
|
+
(screenProps.current.onAllow as (c: ConsentInformation) => void)(consent);
|
|
99
|
+
|
|
100
|
+
expect(manager.setConsent).toHaveBeenCalledWith(consent);
|
|
101
|
+
expect(order).toEqual(["setConsent", "navigateToNext"]);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("fires the partner onConsentGranted hook with the consent payload", () => {
|
|
105
|
+
const manager = makeManager();
|
|
106
|
+
const onConsentGranted = vi.fn();
|
|
107
|
+
|
|
108
|
+
renderWith(manager, { partnerName: "Acme", onConsentGranted });
|
|
109
|
+
(screenProps.current.onAllow as (c: ConsentInformation) => void)(consent);
|
|
110
|
+
|
|
111
|
+
expect(onConsentGranted).toHaveBeenCalledWith(consent);
|
|
112
|
+
expect(manager.navigateToNext).toHaveBeenCalled();
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("a throwing partner hook is captured and still advances the flow", () => {
|
|
116
|
+
const manager = makeManager();
|
|
117
|
+
const boom = new Error("partner analytics is down");
|
|
118
|
+
const onConsentGranted = vi.fn(() => {
|
|
119
|
+
throw boom;
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
renderWith(manager, { partnerName: "Acme", onConsentGranted });
|
|
123
|
+
expect(() =>
|
|
124
|
+
(screenProps.current.onAllow as (c: ConsentInformation) => void)(consent),
|
|
125
|
+
).not.toThrow();
|
|
126
|
+
|
|
127
|
+
expect(captureException).toHaveBeenCalledWith(boom);
|
|
128
|
+
expect(manager.navigateToNext).toHaveBeenCalled();
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("deny exits with a typed ConsentDeniedException", () => {
|
|
132
|
+
const manager = makeManager();
|
|
133
|
+
|
|
134
|
+
renderWith(manager, { partnerName: "Acme" });
|
|
135
|
+
(screenProps.current.onDeny as () => void)();
|
|
136
|
+
|
|
137
|
+
expect(manager.navigateToNext).not.toHaveBeenCalled();
|
|
138
|
+
const [[arg]] = (manager.exit as ReturnType<typeof vi.fn>).mock.calls;
|
|
139
|
+
expect(arg.kind).toBe("failed");
|
|
140
|
+
expect(arg.error).toBeInstanceOf(ConsentDeniedException);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it("defaults globalPrivacyControl to OptOut when the flow config omits it", () => {
|
|
144
|
+
renderWith(makeManager(), { partnerName: "Acme" });
|
|
145
|
+
expect(screenProps.current.globalPrivacyControl).toBe(
|
|
146
|
+
GlobalPrivacyControl.OptOut,
|
|
147
|
+
);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it("honours an explicit globalPrivacyControl from the flow config", () => {
|
|
151
|
+
const manager = makeManager({
|
|
152
|
+
configuration: { config: { globalPrivacyControl: GlobalPrivacyControl.OptIn } },
|
|
153
|
+
});
|
|
154
|
+
renderWith(manager, { partnerName: "Acme" });
|
|
155
|
+
expect(screenProps.current.globalPrivacyControl).toBe(
|
|
156
|
+
GlobalPrivacyControl.OptIn,
|
|
157
|
+
);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it("omits optional partner props entirely when unset", () => {
|
|
161
|
+
renderWith(makeManager(), { partnerName: "Acme" });
|
|
162
|
+
expect("partnerIcon" in screenProps.current).toBe(false);
|
|
163
|
+
expect("partnerPrivacyPolicyUrl" in screenProps.current).toBe(false);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { create as createRenderer, act } from "react-test-renderer";
|
|
4
|
+
|
|
5
|
+
// `vi.mock` hoists above the imports, so its captured values must come from
|
|
6
|
+
// `vi.hoisted` or they are still in the TDZ when the factory runs.
|
|
7
|
+
const { getStatus, requestPermission, screenProps } = vi.hoisted(() => ({
|
|
8
|
+
getStatus: vi.fn(),
|
|
9
|
+
requestPermission: vi.fn(),
|
|
10
|
+
screenProps: { current: {} as Record<string, unknown> },
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
vi.mock("../../../../camera/camera_permissions", () => ({
|
|
14
|
+
getCameraPermissionStatus: getStatus,
|
|
15
|
+
requestCameraPermission: requestPermission,
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
// Stand in for the leaf screen: these tests cover the permission gate and the
|
|
19
|
+
// config resolution, not the instructions UI (which has its own suite).
|
|
20
|
+
vi.mock("../../../screen/use_smile_id_instructions_screen", () => ({
|
|
21
|
+
UseSmileIDInstructionsScreen: (props: Record<string, unknown>) => {
|
|
22
|
+
screenProps.current = props;
|
|
23
|
+
return null;
|
|
24
|
+
},
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
import { OrchestratedInstructionsScreen } from "../orchestrated_instructions_screen";
|
|
28
|
+
import { FlowNavigationProvider } from "../../flow_navigation_context";
|
|
29
|
+
import type { FlowNavigationManager } from "../../flow_navigation_manager";
|
|
30
|
+
|
|
31
|
+
const onNavigateNext = vi.fn();
|
|
32
|
+
const onBack = vi.fn();
|
|
33
|
+
|
|
34
|
+
function makeManager(overrides: Record<string, unknown> = {}) {
|
|
35
|
+
return {
|
|
36
|
+
navigateToNext: onNavigateNext,
|
|
37
|
+
navigateBack: onBack,
|
|
38
|
+
enhancedLivenessEnabled: false,
|
|
39
|
+
documentType: undefined,
|
|
40
|
+
configuration: { config: {} },
|
|
41
|
+
...overrides,
|
|
42
|
+
} as unknown as FlowNavigationManager;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function renderWith(
|
|
46
|
+
manager: FlowNavigationManager,
|
|
47
|
+
configuration: Record<string, unknown> = {},
|
|
48
|
+
) {
|
|
49
|
+
act(() => {
|
|
50
|
+
createRenderer(
|
|
51
|
+
<FlowNavigationProvider manager={manager}>
|
|
52
|
+
<OrchestratedInstructionsScreen
|
|
53
|
+
configuration={
|
|
54
|
+
configuration as React.ComponentProps<
|
|
55
|
+
typeof OrchestratedInstructionsScreen
|
|
56
|
+
>["configuration"]
|
|
57
|
+
}
|
|
58
|
+
/>
|
|
59
|
+
</FlowNavigationProvider>,
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function pressContinue() {
|
|
65
|
+
await act(async () => {
|
|
66
|
+
await (screenProps.current.onContinue as () => Promise<void>)();
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
describe("OrchestratedInstructionsScreen permission gate", () => {
|
|
71
|
+
beforeEach(() => {
|
|
72
|
+
getStatus.mockReset();
|
|
73
|
+
requestPermission.mockReset();
|
|
74
|
+
onNavigateNext.mockReset();
|
|
75
|
+
onBack.mockReset();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("advances without prompting when permission is already granted", async () => {
|
|
79
|
+
getStatus.mockResolvedValue("granted");
|
|
80
|
+
renderWith(makeManager());
|
|
81
|
+
|
|
82
|
+
await pressContinue();
|
|
83
|
+
|
|
84
|
+
expect(requestPermission).not.toHaveBeenCalled();
|
|
85
|
+
expect(onNavigateNext).toHaveBeenCalledTimes(1);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("prompts and advances when the user grants on request", async () => {
|
|
89
|
+
getStatus.mockResolvedValue("undetermined");
|
|
90
|
+
requestPermission.mockResolvedValue("granted");
|
|
91
|
+
renderWith(makeManager());
|
|
92
|
+
|
|
93
|
+
await pressContinue();
|
|
94
|
+
|
|
95
|
+
expect(requestPermission).toHaveBeenCalledTimes(1);
|
|
96
|
+
expect(onNavigateNext).toHaveBeenCalledTimes(1);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("stays on the screen when the user denies — never enters a camera screen without permission", async () => {
|
|
100
|
+
getStatus.mockResolvedValue("undetermined");
|
|
101
|
+
requestPermission.mockResolvedValue("denied");
|
|
102
|
+
renderWith(makeManager());
|
|
103
|
+
|
|
104
|
+
await pressContinue();
|
|
105
|
+
|
|
106
|
+
expect(requestPermission).toHaveBeenCalledTimes(1);
|
|
107
|
+
expect(onNavigateNext).not.toHaveBeenCalled();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("re-prompts rather than advancing when the status is already denied", async () => {
|
|
111
|
+
getStatus.mockResolvedValue("denied");
|
|
112
|
+
requestPermission.mockResolvedValue("denied");
|
|
113
|
+
renderWith(makeManager());
|
|
114
|
+
|
|
115
|
+
await pressContinue();
|
|
116
|
+
|
|
117
|
+
expect(requestPermission).toHaveBeenCalledTimes(1);
|
|
118
|
+
expect(onNavigateNext).not.toHaveBeenCalled();
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
describe("OrchestratedInstructionsScreen config resolution", () => {
|
|
123
|
+
beforeEach(() => {
|
|
124
|
+
getStatus.mockResolvedValue("granted");
|
|
125
|
+
onNavigateNext.mockReset();
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("suppresses the hero oval progress ring when enhanced liveness is on", () => {
|
|
129
|
+
renderWith(makeManager({ enhancedLivenessEnabled: true }));
|
|
130
|
+
expect(screenProps.current.showHeroOvalProgress).toBe(false);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("keeps the hero oval progress ring for the standard selfie flow", () => {
|
|
134
|
+
renderWith(makeManager({ enhancedLivenessEnabled: false }));
|
|
135
|
+
expect(screenProps.current.showHeroOvalProgress).toBe(true);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it("passes onBack straight through to the leaf screen", () => {
|
|
139
|
+
renderWith(makeManager());
|
|
140
|
+
expect(typeof screenProps.current.onBack).toBe("function");
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it("omits the continueButton slot when the partner supplies none", () => {
|
|
144
|
+
renderWith(makeManager());
|
|
145
|
+
expect("continueButton" in screenProps.current).toBe(false);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("adapts a partner continueButton slot to the leaf screen's shape", () => {
|
|
149
|
+
const continueButton = vi.fn(() => null);
|
|
150
|
+
renderWith(makeManager(), { continueButton });
|
|
151
|
+
|
|
152
|
+
const onClick = vi.fn();
|
|
153
|
+
(
|
|
154
|
+
screenProps.current.continueButton as (args: {
|
|
155
|
+
onClick: () => void;
|
|
156
|
+
}) => unknown
|
|
157
|
+
)({ onClick });
|
|
158
|
+
|
|
159
|
+
// The config slot takes `{ onClick, enabled }`; Continue is always
|
|
160
|
+
// actionable, so the adapter fills `enabled: true`.
|
|
161
|
+
expect(continueButton).toHaveBeenCalledWith({ onClick, enabled: true });
|
|
162
|
+
});
|
|
163
|
+
});
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { create as createRenderer, act } from "react-test-renderer";
|
|
4
|
+
|
|
5
|
+
// `vi.mock` is hoisted above the imports, so anything its factory closes over
|
|
6
|
+
// must be created with `vi.hoisted` or it is still in the TDZ when the factory
|
|
7
|
+
// runs.
|
|
8
|
+
const { selfieProps, documentProps } = vi.hoisted(() => ({
|
|
9
|
+
selfieProps: { current: undefined as Record<string, unknown> | undefined },
|
|
10
|
+
documentProps: { current: undefined as Record<string, unknown> | undefined },
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
// Stand in for the leaf screens so these tests exercise the orchestration
|
|
14
|
+
// (which preview to show, accept/reject routing, retake opt-in) rather than
|
|
15
|
+
// re-testing the preview UI, which has its own component suite.
|
|
16
|
+
vi.mock("../../../screen/use_smile_id_preview_screen", () => ({
|
|
17
|
+
UseSmileIDPreviewScreen: (props: Record<string, unknown>) => {
|
|
18
|
+
selfieProps.current = props;
|
|
19
|
+
return null;
|
|
20
|
+
},
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
vi.mock("../../../screen/use_smile_id_document_preview_screen", () => ({
|
|
24
|
+
UseSmileIDDocumentPreviewScreen: (props: Record<string, unknown>) => {
|
|
25
|
+
documentProps.current = props;
|
|
26
|
+
return null;
|
|
27
|
+
},
|
|
28
|
+
}));
|
|
29
|
+
|
|
30
|
+
import { OrchestratedPreviewScreen } from "../orchestrated_preview_screen";
|
|
31
|
+
import { FlowNavigationProvider } from "../../flow_navigation_context";
|
|
32
|
+
import { PreviewConfigBuilder } from "../../dsl/builder/screens_builder";
|
|
33
|
+
import type { FlowNavigationManager } from "../../flow_navigation_manager";
|
|
34
|
+
|
|
35
|
+
type Fn = ReturnType<typeof vi.fn>;
|
|
36
|
+
|
|
37
|
+
type FakeManager = FlowNavigationManager & {
|
|
38
|
+
navigateToNext: Fn;
|
|
39
|
+
navigateBack: Fn;
|
|
40
|
+
exit: Fn;
|
|
41
|
+
retakeCurrentDocumentSide: Fn;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
type ManagerOverrides = {
|
|
45
|
+
readonly isDocument?: boolean;
|
|
46
|
+
readonly documentPreviewPath?: string;
|
|
47
|
+
readonly selfiePath?: string;
|
|
48
|
+
readonly documentFrameAspectRatio?: number;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
function makeManager(overrides: ManagerOverrides = {}): FakeManager {
|
|
52
|
+
return {
|
|
53
|
+
navigateToNext: vi.fn(),
|
|
54
|
+
navigateBack: vi.fn(),
|
|
55
|
+
exit: vi.fn(),
|
|
56
|
+
retakeCurrentDocumentSide: vi.fn(),
|
|
57
|
+
currentPreviewIsDocument: () => overrides.isDocument ?? false,
|
|
58
|
+
currentDocumentPreviewPath: () => overrides.documentPreviewPath,
|
|
59
|
+
documentFrameAspectRatio: overrides.documentFrameAspectRatio,
|
|
60
|
+
captured: {
|
|
61
|
+
...(overrides.selfiePath !== undefined
|
|
62
|
+
? { selfiePath: overrides.selfiePath }
|
|
63
|
+
: {}),
|
|
64
|
+
},
|
|
65
|
+
} as unknown as FakeManager;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function makeConfiguration(
|
|
69
|
+
overrides: Partial<PreviewConfigBuilder> = {},
|
|
70
|
+
): PreviewConfigBuilder {
|
|
71
|
+
return Object.assign(new PreviewConfigBuilder(), overrides);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function renderWith(
|
|
75
|
+
manager: FlowNavigationManager,
|
|
76
|
+
configuration: PreviewConfigBuilder = makeConfiguration(),
|
|
77
|
+
) {
|
|
78
|
+
act(() => {
|
|
79
|
+
createRenderer(
|
|
80
|
+
<FlowNavigationProvider manager={manager}>
|
|
81
|
+
<OrchestratedPreviewScreen configuration={configuration} />
|
|
82
|
+
</FlowNavigationProvider>,
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function readSelfieProps(): Record<string, unknown> {
|
|
88
|
+
const props = selfieProps.current;
|
|
89
|
+
if (!props) throw new Error("UseSmileIDPreviewScreen was not rendered");
|
|
90
|
+
return props;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function readDocumentProps(): Record<string, unknown> {
|
|
94
|
+
const props = documentProps.current;
|
|
95
|
+
if (!props) {
|
|
96
|
+
throw new Error("UseSmileIDDocumentPreviewScreen was not rendered");
|
|
97
|
+
}
|
|
98
|
+
return props;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
beforeEach(() => {
|
|
102
|
+
selfieProps.current = undefined;
|
|
103
|
+
documentProps.current = undefined;
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
describe("OrchestratedPreviewScreen — selfie preview", () => {
|
|
107
|
+
it("shows the selfie preview when the step is not a document preview", () => {
|
|
108
|
+
renderWith(makeManager({ selfiePath: "file:///selfie.jpg" }));
|
|
109
|
+
|
|
110
|
+
expect(documentProps.current).toBeUndefined();
|
|
111
|
+
expect(readSelfieProps().capturedSelfiePath).toBe("file:///selfie.jpg");
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("omits the selfie path entirely when nothing was captured", () => {
|
|
115
|
+
renderWith(makeManager());
|
|
116
|
+
|
|
117
|
+
expect("capturedSelfiePath" in readSelfieProps()).toBe(false);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("accept advances the flow", () => {
|
|
121
|
+
const manager = makeManager({ selfiePath: "file:///selfie.jpg" });
|
|
122
|
+
renderWith(manager);
|
|
123
|
+
|
|
124
|
+
(readSelfieProps().onAccept as () => void)();
|
|
125
|
+
|
|
126
|
+
expect(manager.navigateToNext).toHaveBeenCalledTimes(1);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("reject rewinds to the capture screen when retake is allowed", () => {
|
|
130
|
+
const manager = makeManager({ selfiePath: "file:///selfie.jpg" });
|
|
131
|
+
renderWith(manager, makeConfiguration({ allowRetake: true }));
|
|
132
|
+
|
|
133
|
+
(readSelfieProps().onReject as () => void)();
|
|
134
|
+
|
|
135
|
+
expect(manager.navigateBack).toHaveBeenCalledTimes(1);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it("reject is inert when the partner disallowed retakes", () => {
|
|
139
|
+
const manager = makeManager({ selfiePath: "file:///selfie.jpg" });
|
|
140
|
+
renderWith(manager, makeConfiguration({ allowRetake: false }));
|
|
141
|
+
|
|
142
|
+
expect(readSelfieProps().allowRetake).toBe(false);
|
|
143
|
+
(readSelfieProps().onReject as () => void)();
|
|
144
|
+
|
|
145
|
+
expect(manager.navigateBack).not.toHaveBeenCalled();
|
|
146
|
+
expect(manager.navigateToNext).not.toHaveBeenCalled();
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it("forwards the attribution switch", () => {
|
|
150
|
+
renderWith(makeManager(), makeConfiguration({ showAttribution: false }));
|
|
151
|
+
|
|
152
|
+
expect(readSelfieProps().showAttribution).toBe(false);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
describe("OrchestratedPreviewScreen — document preview", () => {
|
|
157
|
+
it("shows the side the manager's per-side loop is currently on", () => {
|
|
158
|
+
renderWith(
|
|
159
|
+
makeManager({
|
|
160
|
+
isDocument: true,
|
|
161
|
+
documentPreviewPath: "file:///back.jpg",
|
|
162
|
+
documentFrameAspectRatio: 1.586,
|
|
163
|
+
}),
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
expect(selfieProps.current).toBeUndefined();
|
|
167
|
+
expect(readDocumentProps().capturedDocumentPath).toBe("file:///back.jpg");
|
|
168
|
+
expect(readDocumentProps().documentAspectRatio).toBeCloseTo(1.586, 5);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it("falls back to the landscape default frame when no ratio is known", () => {
|
|
172
|
+
renderWith(makeManager({ isDocument: true }));
|
|
173
|
+
|
|
174
|
+
expect(readDocumentProps().documentAspectRatio).toBeCloseTo(1.586, 5);
|
|
175
|
+
expect("capturedDocumentPath" in readDocumentProps()).toBe(false);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it("accept advances the flow", () => {
|
|
179
|
+
const manager = makeManager({
|
|
180
|
+
isDocument: true,
|
|
181
|
+
documentPreviewPath: "file:///front.jpg",
|
|
182
|
+
});
|
|
183
|
+
renderWith(manager);
|
|
184
|
+
|
|
185
|
+
(readDocumentProps().onAccept as () => void)();
|
|
186
|
+
|
|
187
|
+
expect(manager.navigateToNext).toHaveBeenCalledTimes(1);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it("reject discards that side and rewinds when retake is allowed", () => {
|
|
191
|
+
const manager = makeManager({
|
|
192
|
+
isDocument: true,
|
|
193
|
+
documentPreviewPath: "file:///front.jpg",
|
|
194
|
+
});
|
|
195
|
+
renderWith(manager, makeConfiguration({ allowRetake: true }));
|
|
196
|
+
|
|
197
|
+
(readDocumentProps().onReject as () => void)();
|
|
198
|
+
|
|
199
|
+
expect(manager.retakeCurrentDocumentSide).toHaveBeenCalledTimes(1);
|
|
200
|
+
expect(manager.navigateBack).toHaveBeenCalledTimes(1);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it("reject keeps the capture when the partner disallowed retakes", () => {
|
|
204
|
+
const manager = makeManager({
|
|
205
|
+
isDocument: true,
|
|
206
|
+
documentPreviewPath: "file:///front.jpg",
|
|
207
|
+
});
|
|
208
|
+
renderWith(manager, makeConfiguration({ allowRetake: false }));
|
|
209
|
+
|
|
210
|
+
(readDocumentProps().onReject as () => void)();
|
|
211
|
+
|
|
212
|
+
expect(manager.retakeCurrentDocumentSide).not.toHaveBeenCalled();
|
|
213
|
+
expect(manager.navigateBack).not.toHaveBeenCalled();
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it("close exits the flow", () => {
|
|
217
|
+
const manager = makeManager({ isDocument: true });
|
|
218
|
+
renderWith(manager);
|
|
219
|
+
|
|
220
|
+
(readDocumentProps().onClose as () => void)();
|
|
221
|
+
|
|
222
|
+
expect(manager.exit).toHaveBeenCalledTimes(1);
|
|
223
|
+
});
|
|
224
|
+
});
|