@smileid/usesmileid 12.0.0 → 12.0.1
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 +4 -0
- 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/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/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 +1 -1
- package/dist/data/api/smile_id_api.d.ts.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/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/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/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_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 +3 -6
- package/dist/presentation/flow/dsl/builder/screens_builder.d.ts.map +1 -1
- package/dist/presentation/flow/dsl/builder/screens_builder.js +3 -6
- package/dist/presentation/flow/dsl/builder/screens_builder.js.map +1 -1
- package/dist/presentation/flow/flow_navigation_manager.d.ts +5 -1
- package/dist/presentation/flow/flow_navigation_manager.d.ts.map +1 -1
- package/dist/presentation/flow/flow_navigation_manager.js +7 -1
- 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/use_smile_id_flow.d.ts.map +1 -1
- package/dist/presentation/flow/use_smile_id_flow.js +10 -4
- package/dist/presentation/flow/use_smile_id_flow.js.map +1 -1
- package/dist/presentation/flow/validation/flow_validator.d.ts.map +1 -1
- package/dist/presentation/flow/validation/flow_validator.js +42 -20
- package/dist/presentation/flow/validation/flow_validator.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 +36 -15
- 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__/setup_react_native.ts +17 -2
- package/src/__tests__/snapshots/__snapshots__/screens_structural.test.tsx.snap +5261 -0
- package/src/__tests__/snapshots/screens_structural.test.tsx +230 -0
- package/src/camera/__tests__/use_smile_id_camera_system.test.ts +103 -0
- package/src/core/exception/__tests__/builder_validation_exceptions.test.ts +67 -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/index.ts +1 -0
- 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 +1 -1
- 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/compression/__tests__/payload_compressor_real_jpeg.test.ts +6 -2
- 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/repository/__tests__/network_retries.test.ts +1 -1
- 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/smile_id_urls.ts +1 -1
- package/src/data/util/__tests__/retry_util.test.ts +25 -0
- package/src/data/util/retry_util.ts +9 -1
- package/src/index.ts +6 -4
- 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__/use_smile_id_metadata.test.ts +1 -1
- 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_enhanced_smart_selfie_clip.test.tsx +9 -4
- package/src/presentation/components/__tests__/use_smile_id_instructions_hero.test.tsx +44 -0
- 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 +49 -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 +3 -6
- package/src/presentation/flow/flow_navigation_manager.ts +6 -1
- package/src/presentation/flow/model/instructions_defaults.ts +1 -1
- 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/use_smile_id_flow.tsx +11 -4
- package/src/presentation/flow/validation/__tests__/flow_validator.test.ts +61 -1
- package/src/presentation/flow/validation/flow_validator.ts +55 -26
- 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__/scan_state_to_overlay_state.test.ts +47 -27
- package/src/presentation/screen/__tests__/use_smile_id_capture_screen.test.tsx +176 -14
- package/src/presentation/screen/__tests__/use_smile_id_document_back_instructions.test.tsx +1 -1
- 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_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 +47 -19
- 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/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
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { GlobalPrivacyControl } from "../../core/models/global_privacy_control";
|
|
1
2
|
const EU_COUNTRY_CODES = new Set([
|
|
2
3
|
"AT",
|
|
3
4
|
"BE",
|
|
@@ -55,12 +56,19 @@ export function isDeviceLocaleInEU(locale = getDeviceLocale()) {
|
|
|
55
56
|
return country !== undefined && EU_COUNTRY_CODES.has(country);
|
|
56
57
|
}
|
|
57
58
|
/**
|
|
58
|
-
* Returns the default consent checkbox state
|
|
59
|
+
* Returns the default consent checkbox state for the partner-declared
|
|
60
|
+
* `GlobalPrivacyControl` posture.
|
|
59
61
|
*
|
|
60
|
-
* -
|
|
61
|
-
* -
|
|
62
|
+
* - `GlobalPrivacyControl.OptOut` (default): ticked (`true`) universally —
|
|
63
|
+
* the opt-out layout is enforced for every session and the device region
|
|
64
|
+
* is never consulted.
|
|
65
|
+
* - `GlobalPrivacyControl.OptIn`: legacy regional mechanics — EU locales
|
|
66
|
+
* start unticked (`false`, explicit opt-in per GDPR), everywhere else
|
|
67
|
+
* starts ticked (`true`).
|
|
62
68
|
*/
|
|
63
|
-
export function getDefaultConsentState(locale = getDeviceLocale()) {
|
|
64
|
-
return
|
|
69
|
+
export function getDefaultConsentState(globalPrivacyControl = GlobalPrivacyControl.OptOut, locale = getDeviceLocale()) {
|
|
70
|
+
return globalPrivacyControl === GlobalPrivacyControl.OptOut
|
|
71
|
+
? true
|
|
72
|
+
: !isDeviceLocaleInEU(locale);
|
|
65
73
|
}
|
|
66
74
|
//# sourceMappingURL=locale_utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locale_utils.js","sourceRoot":"","sources":["../../../src/presentation/utils/locale_utils.ts"],"names":[],"mappings":"AAAA,MAAM,gBAAgB,GAAwB,IAAI,GAAG,CAAC;IACpD,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;CACL,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC,MAAM,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAChC,SAAiB,eAAe,EAAE;IAElC,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;IACpD,OAAO,OAAO,KAAK,SAAS,IAAI,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAChE,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"locale_utils.js","sourceRoot":"","sources":["../../../src/presentation/utils/locale_utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,0CAA0C,CAAC;AAChF,MAAM,gBAAgB,GAAwB,IAAI,GAAG,CAAC;IACpD,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;CACL,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC,MAAM,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAChC,SAAiB,eAAe,EAAE;IAElC,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;IACpD,OAAO,OAAO,KAAK,SAAS,IAAI,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAChE,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CACpC,uBAA6C,oBAAoB,CAAC,MAAM,EACxE,SAAiB,eAAe,EAAE;IAElC,OAAO,oBAAoB,KAAK,oBAAoB,CAAC,MAAM;QACzD,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { FaceAnalyzer } from "@smileid/usesmileid_platform_interface";
|
|
2
|
+
import { AnalyzerFactoryKey } from "@smileid/usesmileid_bridge";
|
|
3
|
+
/**
|
|
4
|
+
* Deterministic fake face analyzer for scripted-scenario E2E runs. Exported
|
|
5
|
+
* only behind the `@smileid/usesmileid/testing` subpath so it cannot leak into
|
|
6
|
+
* partner production bundles.
|
|
7
|
+
*
|
|
8
|
+
* Per-frame detection runs in the provider's native frame-processor plugin
|
|
9
|
+
* (pixels never cross into JS), so `frameProcessorPluginName` points at a
|
|
10
|
+
* plugin that does not exist — the capture screen surfaces that as its
|
|
11
|
+
* camera-unavailable state. This fake covers the DSL registration seam and the
|
|
12
|
+
* capture-free flows; capture progression is driven via `onResult` instead.
|
|
13
|
+
*/
|
|
14
|
+
export interface ScriptedScenarioStep {
|
|
15
|
+
readonly emit: string;
|
|
16
|
+
readonly holdFrames?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface ScriptedScenario {
|
|
19
|
+
readonly name: string;
|
|
20
|
+
readonly captureType: string;
|
|
21
|
+
readonly steps: readonly ScriptedScenarioStep[];
|
|
22
|
+
}
|
|
23
|
+
export declare class FakeFaceAnalyzer implements FaceAnalyzer {
|
|
24
|
+
private readonly scenario;
|
|
25
|
+
readonly kind: "face";
|
|
26
|
+
readonly key: AnalyzerFactoryKey;
|
|
27
|
+
readonly frameProcessorPluginName = "e2e-fake-face";
|
|
28
|
+
configureCallCount: number;
|
|
29
|
+
resetCallCount: number;
|
|
30
|
+
flushCallCount: number;
|
|
31
|
+
closeCallCount: number;
|
|
32
|
+
private stepIndex;
|
|
33
|
+
private framesLeftInStep;
|
|
34
|
+
constructor(scenario: ScriptedScenario);
|
|
35
|
+
/** Frame-by-frame cursor; the final step repeats indefinitely. */
|
|
36
|
+
nextEmit(): string;
|
|
37
|
+
configure(): Promise<void>;
|
|
38
|
+
reset(): Promise<void>;
|
|
39
|
+
flush(): Promise<void>;
|
|
40
|
+
close(): Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
export declare function makeFakeFaceAnalyzer(scenario: ScriptedScenario): FakeFaceAnalyzer;
|
|
43
|
+
//# sourceMappingURL=fake_face_analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fake_face_analyzer.d.ts","sourceRoot":"","sources":["../../src/testing/fake_face_analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE;;;;;;;;;;GAUG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,oBAAoB,EAAE,CAAC;CACjD;AAED,qBAAa,gBAAiB,YAAW,YAAY;IAavC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAZrC,QAAQ,CAAC,IAAI,EAAG,MAAM,CAAU;IAChC,QAAQ,CAAC,GAAG,EAAE,kBAAkB,CAAgC;IAChE,QAAQ,CAAC,wBAAwB,mBAAmB;IAEpD,kBAAkB,SAAK;IACvB,cAAc,SAAK;IACnB,cAAc,SAAK;IACnB,cAAc,SAAK;IAEnB,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,gBAAgB,CAAS;gBAEJ,QAAQ,EAAE,gBAAgB;IAIvD,kEAAkE;IAClE,QAAQ,IAAI,MAAM;IAalB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAK1B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAKtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAKtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAIvB;AAED,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,gBAAgB,GACzB,gBAAgB,CAElB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { AnalyzerFactoryKey } from "@smileid/usesmileid_bridge";
|
|
2
|
+
export class FakeFaceAnalyzer {
|
|
3
|
+
scenario;
|
|
4
|
+
kind = "face";
|
|
5
|
+
key = AnalyzerFactoryKey.MLKitFace;
|
|
6
|
+
frameProcessorPluginName = "e2e-fake-face";
|
|
7
|
+
configureCallCount = 0;
|
|
8
|
+
resetCallCount = 0;
|
|
9
|
+
flushCallCount = 0;
|
|
10
|
+
closeCallCount = 0;
|
|
11
|
+
stepIndex = 0;
|
|
12
|
+
framesLeftInStep;
|
|
13
|
+
constructor(scenario) {
|
|
14
|
+
this.scenario = scenario;
|
|
15
|
+
this.framesLeftInStep = scenario.steps[0]?.holdFrames ?? 1;
|
|
16
|
+
}
|
|
17
|
+
/** Frame-by-frame cursor; the final step repeats indefinitely. */
|
|
18
|
+
nextEmit() {
|
|
19
|
+
const steps = this.scenario.steps;
|
|
20
|
+
const step = steps[this.stepIndex];
|
|
21
|
+
if (step === undefined)
|
|
22
|
+
return "noFace";
|
|
23
|
+
if (this.stepIndex === steps.length - 1)
|
|
24
|
+
return step.emit;
|
|
25
|
+
this.framesLeftInStep -= 1;
|
|
26
|
+
if (this.framesLeftInStep <= 0) {
|
|
27
|
+
this.stepIndex += 1;
|
|
28
|
+
this.framesLeftInStep = steps[this.stepIndex]?.holdFrames ?? 1;
|
|
29
|
+
}
|
|
30
|
+
return step.emit;
|
|
31
|
+
}
|
|
32
|
+
configure() {
|
|
33
|
+
this.configureCallCount += 1;
|
|
34
|
+
return Promise.resolve();
|
|
35
|
+
}
|
|
36
|
+
reset() {
|
|
37
|
+
this.resetCallCount += 1;
|
|
38
|
+
return Promise.resolve();
|
|
39
|
+
}
|
|
40
|
+
flush() {
|
|
41
|
+
this.flushCallCount += 1;
|
|
42
|
+
return Promise.resolve();
|
|
43
|
+
}
|
|
44
|
+
close() {
|
|
45
|
+
this.closeCallCount += 1;
|
|
46
|
+
return Promise.resolve();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export function makeFakeFaceAnalyzer(scenario) {
|
|
50
|
+
return new FakeFaceAnalyzer(scenario);
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=fake_face_analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fake_face_analyzer.js","sourceRoot":"","sources":["../../src/testing/fake_face_analyzer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAwBhE,MAAM,OAAO,gBAAgB;IAaE;IAZpB,IAAI,GAAG,MAAe,CAAC;IACvB,GAAG,GAAuB,kBAAkB,CAAC,SAAS,CAAC;IACvD,wBAAwB,GAAG,eAAe,CAAC;IAEpD,kBAAkB,GAAG,CAAC,CAAC;IACvB,cAAc,GAAG,CAAC,CAAC;IACnB,cAAc,GAAG,CAAC,CAAC;IACnB,cAAc,GAAG,CAAC,CAAC;IAEX,SAAS,GAAG,CAAC,CAAC;IACd,gBAAgB,CAAS;IAEjC,YAA6B,QAA0B;QAA1B,aAAQ,GAAR,QAAQ,CAAkB;QACrD,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,UAAU,IAAI,CAAC,CAAC;IAC7D,CAAC;IAED,kEAAkE;IAClE,QAAQ;QACN,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAClC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACnC,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,QAAQ,CAAC;QACxC,IAAI,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC,IAAI,CAAC;QAC1D,IAAI,CAAC,gBAAgB,IAAI,CAAC,CAAC;QAC3B,IAAI,IAAI,CAAC,gBAAgB,IAAI,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC;YACpB,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,IAAI,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,SAAS;QACP,IAAI,CAAC,kBAAkB,IAAI,CAAC,CAAC;QAC7B,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,cAAc,IAAI,CAAC,CAAC;QACzB,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,cAAc,IAAI,CAAC,CAAC;QACzB,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,cAAc,IAAI,CAAC,CAAC;QACzB,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;CACF;AAED,MAAM,UAAU,oBAAoB,CAClC,QAA0B;IAE1B,OAAO,IAAI,gBAAgB,CAAC,QAAQ,CAAC,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { FakeFaceAnalyzer, makeFakeFaceAnalyzer, type ScriptedScenario, type ScriptedScenarioStep, } from "./fake_face_analyzer";
|
|
2
|
+
export { scriptedFaceScanResults } from "./scripted_scan_results";
|
|
3
|
+
export { parseScriptedScenario } from "./scenario_loader";
|
|
4
|
+
export { type ScenarioExpectations, parseScenarioExpectations, expectSubsetInOrder, } from "./scenario_expectations";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EACL,KAAK,oBAAoB,EACzB,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Test-support entry — exported behind the `@smileid/usesmileid/testing`
|
|
2
|
+
// subpath only. Nothing here may be re-exported from the main index.
|
|
3
|
+
export { FakeFaceAnalyzer, makeFakeFaceAnalyzer, } from "./fake_face_analyzer";
|
|
4
|
+
export { scriptedFaceScanResults } from "./scripted_scan_results";
|
|
5
|
+
export { parseScriptedScenario } from "./scenario_loader";
|
|
6
|
+
export { parseScenarioExpectations, expectSubsetInOrder, } from "./scenario_expectations";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,qEAAqE;AACrE,OAAO,EACL,gBAAgB,EAChB,oBAAoB,GAGrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAEL,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capture-scoped expectations from the shared `e2e-scenarios` schema's `expected`
|
|
3
|
+
* block (screen + analytics-event names, terminal state). Framework-agnostic (no
|
|
4
|
+
* vitest/jest import) so a partner app's own e2e runner can reuse it.
|
|
5
|
+
*/
|
|
6
|
+
export interface ScenarioExpectations {
|
|
7
|
+
/** Ordered `screen_viewed` sequence for the canonical consent-first flow. */
|
|
8
|
+
readonly screens: readonly string[];
|
|
9
|
+
/** Ordered analytics event types that must fire (subset-in-order). */
|
|
10
|
+
readonly events: readonly string[];
|
|
11
|
+
/** How the capture session ends. */
|
|
12
|
+
readonly terminal?: "submitted" | "timeout" | "unsatisfied";
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Extracts and validates the `expected` block from an already-parsed shared
|
|
16
|
+
* scenario JSON object. Returns empty screen/event arrays when the block is
|
|
17
|
+
* absent (older scenarios), and throws on a malformed block so drift fails
|
|
18
|
+
* loudly rather than silently weakening the contract.
|
|
19
|
+
*/
|
|
20
|
+
export declare function parseScenarioExpectations(raw: unknown): ScenarioExpectations;
|
|
21
|
+
/**
|
|
22
|
+
* Asserts that every element of [expected] appears in [recorded] in the same
|
|
23
|
+
* relative order (a minimal ordered-subset match — unlisted items may
|
|
24
|
+
* interleave, exact-match is deliberately NOT required). Throws a descriptive
|
|
25
|
+
* Error on failure so it works under any test runner.
|
|
26
|
+
*/
|
|
27
|
+
export declare function expectSubsetInOrder(recorded: readonly string[], expected: readonly string[], label?: string): void;
|
|
28
|
+
//# sourceMappingURL=scenario_expectations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scenario_expectations.d.ts","sourceRoot":"","sources":["../../src/testing/scenario_expectations.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,sEAAsE;IACtE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,WAAW,GAAG,SAAS,GAAG,aAAa,CAAC;CAC7D;AAQD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,OAAO,GAAG,oBAAoB,CA4B5E;AAUD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,KAAK,SAAa,GACjB,IAAI,CAYN"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const TERMINALS = new Set([
|
|
2
|
+
"submitted",
|
|
3
|
+
"timeout",
|
|
4
|
+
"unsatisfied",
|
|
5
|
+
]);
|
|
6
|
+
/**
|
|
7
|
+
* Extracts and validates the `expected` block from an already-parsed shared
|
|
8
|
+
* scenario JSON object. Returns empty screen/event arrays when the block is
|
|
9
|
+
* absent (older scenarios), and throws on a malformed block so drift fails
|
|
10
|
+
* loudly rather than silently weakening the contract.
|
|
11
|
+
*/
|
|
12
|
+
export function parseScenarioExpectations(raw) {
|
|
13
|
+
if (typeof raw !== "object" || raw === null) {
|
|
14
|
+
throw new Error("scenario must be a JSON object");
|
|
15
|
+
}
|
|
16
|
+
const expected = raw.expected;
|
|
17
|
+
if (expected === undefined) {
|
|
18
|
+
return { screens: [], events: [] };
|
|
19
|
+
}
|
|
20
|
+
if (typeof expected !== "object" || expected === null) {
|
|
21
|
+
throw new Error("scenario.expected must be an object when present");
|
|
22
|
+
}
|
|
23
|
+
const record = expected;
|
|
24
|
+
const screens = readStringArray(record.screens, "scenario.expected.screens");
|
|
25
|
+
const events = readStringArray(record.events, "scenario.expected.events");
|
|
26
|
+
const terminal = record.terminal;
|
|
27
|
+
if (terminal === undefined) {
|
|
28
|
+
return { screens, events };
|
|
29
|
+
}
|
|
30
|
+
if (typeof terminal !== "string" || !TERMINALS.has(terminal)) {
|
|
31
|
+
throw new Error(`scenario.expected.terminal must be one of ${[...TERMINALS].join(", ")}, got ${String(terminal)}`);
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
screens,
|
|
35
|
+
events,
|
|
36
|
+
terminal: terminal,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function readStringArray(value, label) {
|
|
40
|
+
if (value === undefined)
|
|
41
|
+
return [];
|
|
42
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) {
|
|
43
|
+
throw new Error(`${label} must be an array of strings`);
|
|
44
|
+
}
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Asserts that every element of [expected] appears in [recorded] in the same
|
|
49
|
+
* relative order (a minimal ordered-subset match — unlisted items may
|
|
50
|
+
* interleave, exact-match is deliberately NOT required). Throws a descriptive
|
|
51
|
+
* Error on failure so it works under any test runner.
|
|
52
|
+
*/
|
|
53
|
+
export function expectSubsetInOrder(recorded, expected, label = "sequence") {
|
|
54
|
+
let cursor = 0;
|
|
55
|
+
for (const item of recorded) {
|
|
56
|
+
if (cursor < expected.length && item === expected[cursor])
|
|
57
|
+
cursor += 1;
|
|
58
|
+
}
|
|
59
|
+
if (cursor !== expected.length) {
|
|
60
|
+
throw new Error(`${label}: expected [${expected
|
|
61
|
+
.slice(cursor)
|
|
62
|
+
.join(", ")}] to appear in order within [${recorded.join(", ")}]`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=scenario_expectations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scenario_expectations.js","sourceRoot":"","sources":["../../src/testing/scenario_expectations.ts"],"names":[],"mappings":"AAcA,MAAM,SAAS,GAAwB,IAAI,GAAG,CAAC;IAC7C,WAAW;IACX,SAAS;IACT,aAAa;CACd,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CAAC,GAAY;IACpD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;IACD,MAAM,QAAQ,GAAI,GAA+B,CAAC,QAAQ,CAAC;IAC3D,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACrC,CAAC;IACD,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IACD,MAAM,MAAM,GAAG,QAAmC,CAAC;IACnD,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,OAAO,EAAE,2BAA2B,CAAC,CAAC;IAC7E,MAAM,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;IAC1E,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IACjC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAC7B,CAAC;IACD,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7D,MAAM,IAAI,KAAK,CACb,6CAA6C,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,QAAQ,CAAC,EAAE,CAClG,CAAC;IACJ,CAAC;IACD,OAAO;QACL,OAAO;QACP,MAAM;QACN,QAAQ,EAAE,QAAmD;KAC9D,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,KAAc,EAAE,KAAa;IACpD,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACnC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,EAAE,CAAC;QAC5E,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,8BAA8B,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,KAAiB,CAAC;AAC3B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAA2B,EAC3B,QAA2B,EAC3B,KAAK,GAAG,UAAU;IAElB,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,MAAM,GAAG,QAAQ,CAAC,MAAM,IAAI,IAAI,KAAK,QAAQ,CAAC,MAAM,CAAC;YAAE,MAAM,IAAI,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,MAAM,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CACb,GAAG,KAAK,eAAe,QAAQ;aAC5B,KAAK,CAAC,MAAM,CAAC;aACb,IAAI,CAAC,IAAI,CAAC,gCAAgC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CACpE,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ScriptedScenario } from "./fake_face_analyzer";
|
|
2
|
+
/**
|
|
3
|
+
* Validates a parsed shared-scenario JSON object and returns the typed
|
|
4
|
+
* [ScriptedScenario]. Kept I/O-free (takes an already-parsed object) so the
|
|
5
|
+
* `@smileid/usesmileid/testing` subpath stays environment-agnostic — the caller
|
|
6
|
+
* owns how the JSON is read. Throws with a specific message on any shape drift
|
|
7
|
+
* so a malformed or vocabulary-drifted script fails loudly at load time instead
|
|
8
|
+
* of producing a misleading capture sequence.
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseScriptedScenario(raw: unknown): ScriptedScenario;
|
|
11
|
+
//# sourceMappingURL=scenario_loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scenario_loader.d.ts","sourceRoot":"","sources":["../../src/testing/scenario_loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAEjB,MAAM,sBAAsB,CAAC;AAuB9B;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CAgDpE"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Emission vocabulary of the shared `e2e-scenarios` schema (`schema.json` in
|
|
3
|
+
* every repo's scenario folder). A step whose `emit` is outside this set is a
|
|
4
|
+
* drift bug — the loader rejects it rather than letting the fake silently treat
|
|
5
|
+
* it as "no detection".
|
|
6
|
+
*/
|
|
7
|
+
const KNOWN_EMITS = new Set([
|
|
8
|
+
"noFace",
|
|
9
|
+
"faceTooFar",
|
|
10
|
+
"faceCentered",
|
|
11
|
+
"headTurnLeft",
|
|
12
|
+
"headTurnRight",
|
|
13
|
+
"headTurnUp",
|
|
14
|
+
"satisfied",
|
|
15
|
+
"noDocument",
|
|
16
|
+
"documentFound",
|
|
17
|
+
"documentUnstable",
|
|
18
|
+
]);
|
|
19
|
+
const CAPTURE_TYPES = new Set(["selfie", "document"]);
|
|
20
|
+
/**
|
|
21
|
+
* Validates a parsed shared-scenario JSON object and returns the typed
|
|
22
|
+
* [ScriptedScenario]. Kept I/O-free (takes an already-parsed object) so the
|
|
23
|
+
* `@smileid/usesmileid/testing` subpath stays environment-agnostic — the caller
|
|
24
|
+
* owns how the JSON is read. Throws with a specific message on any shape drift
|
|
25
|
+
* so a malformed or vocabulary-drifted script fails loudly at load time instead
|
|
26
|
+
* of producing a misleading capture sequence.
|
|
27
|
+
*/
|
|
28
|
+
export function parseScriptedScenario(raw) {
|
|
29
|
+
if (typeof raw !== "object" || raw === null) {
|
|
30
|
+
throw new Error("scenario must be a JSON object");
|
|
31
|
+
}
|
|
32
|
+
const record = raw;
|
|
33
|
+
const name = record.name;
|
|
34
|
+
if (typeof name !== "string" || name.length === 0) {
|
|
35
|
+
throw new Error("scenario.name must be a non-empty string");
|
|
36
|
+
}
|
|
37
|
+
const captureType = record.captureType;
|
|
38
|
+
if (typeof captureType !== "string" || !CAPTURE_TYPES.has(captureType)) {
|
|
39
|
+
throw new Error(`scenario.captureType must be one of ${[...CAPTURE_TYPES].join(", ")}, got ${String(captureType)}`);
|
|
40
|
+
}
|
|
41
|
+
if (!Array.isArray(record.steps) || record.steps.length === 0) {
|
|
42
|
+
throw new Error(`scenario.steps must be a non-empty array in ${name}`);
|
|
43
|
+
}
|
|
44
|
+
const steps = record.steps.map((step, index) => {
|
|
45
|
+
if (typeof step !== "object" || step === null) {
|
|
46
|
+
throw new Error(`scenario.steps[${index}] must be an object in ${name}`);
|
|
47
|
+
}
|
|
48
|
+
const stepRecord = step;
|
|
49
|
+
const emit = stepRecord.emit;
|
|
50
|
+
if (typeof emit !== "string" || !KNOWN_EMITS.has(emit)) {
|
|
51
|
+
throw new Error(`scenario.steps[${index}].emit "${String(emit)}" is not a known emission in ${name}`);
|
|
52
|
+
}
|
|
53
|
+
const holdFrames = stepRecord.holdFrames;
|
|
54
|
+
if (holdFrames !== undefined &&
|
|
55
|
+
(typeof holdFrames !== "number" ||
|
|
56
|
+
!Number.isInteger(holdFrames) ||
|
|
57
|
+
holdFrames < 1)) {
|
|
58
|
+
throw new Error(`scenario.steps[${index}].holdFrames must be a positive integer in ${name}`);
|
|
59
|
+
}
|
|
60
|
+
return holdFrames === undefined ? { emit } : { emit, holdFrames };
|
|
61
|
+
});
|
|
62
|
+
return { name, captureType, steps };
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=scenario_loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scenario_loader.js","sourceRoot":"","sources":["../../src/testing/scenario_loader.ts"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH,MAAM,WAAW,GAAwB,IAAI,GAAG,CAAC;IAC/C,QAAQ;IACR,YAAY;IACZ,cAAc;IACd,cAAc;IACd,eAAe;IACf,YAAY;IACZ,WAAW;IACX,YAAY;IACZ,eAAe;IACf,kBAAkB;CACnB,CAAC,CAAC;AAEH,MAAM,aAAa,GAAwB,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;AAE3E;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAY;IAChD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;IACD,MAAM,MAAM,GAAG,GAA8B,CAAC;IAE9C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IACzB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;IACvC,IAAI,OAAO,WAAW,KAAK,QAAQ,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;QACvE,MAAM,IAAI,KAAK,CACb,uCAAuC,CAAC,GAAG,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,WAAW,CAAC,EAAE,CACnG,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,KAAK,CAAC,+CAA+C,IAAI,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,KAAK,GAA2B,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QACrE,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,kBAAkB,KAAK,0BAA0B,IAAI,EAAE,CAAC,CAAC;QAC3E,CAAC;QACD,MAAM,UAAU,GAAG,IAA+B,CAAC;QACnD,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC;QAC7B,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACvD,MAAM,IAAI,KAAK,CACb,kBAAkB,KAAK,WAAW,MAAM,CAAC,IAAI,CAAC,gCAAgC,IAAI,EAAE,CACrF,CAAC;QACJ,CAAC;QACD,MAAM,UAAU,GAAG,UAAU,CAAC,UAAU,CAAC;QACzC,IACE,UAAU,KAAK,SAAS;YACxB,CAAC,OAAO,UAAU,KAAK,QAAQ;gBAC7B,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC;gBAC7B,UAAU,GAAG,CAAC,CAAC,EACjB,CAAC;YACD,MAAM,IAAI,KAAK,CACb,kBAAkB,KAAK,8CAA8C,IAAI,EAAE,CAC5E,CAAC;QACJ,CAAC;QACD,OAAO,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { FaceScanResult } from "@smileid/usesmileid_bridge";
|
|
2
|
+
import type { ScriptedScenario } from "./fake_face_analyzer";
|
|
3
|
+
/**
|
|
4
|
+
* Turns a shared E2E scenario into the `FaceScanResult` sequence a capture
|
|
5
|
+
* screen receives frame-by-frame, so a headless test can replay the shared
|
|
6
|
+
* script through the frame stream's `onResult` seam (per-frame detection is a
|
|
7
|
+
* native frame-processor concern; pixels never reach JS).
|
|
8
|
+
*
|
|
9
|
+
* `noFace` → `initial`; `faceTooFar` / `faceCentered` → `found`; the terminal
|
|
10
|
+
* `satisfied` → one `finished` result carrying a `selfie` event plus
|
|
11
|
+
* [livenessCount] `liveness` events at opaque `file://` URLs the screen never
|
|
12
|
+
* reads. Exported only behind the `@smileid/usesmileid/testing` subpath.
|
|
13
|
+
*/
|
|
14
|
+
export declare function scriptedFaceScanResults(scenario: ScriptedScenario, options?: {
|
|
15
|
+
readonly livenessCount?: number;
|
|
16
|
+
}): FaceScanResult[];
|
|
17
|
+
//# sourceMappingURL=scripted_scan_results.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scripted_scan_results.d.ts","sourceRoot":"","sources":["../../src/testing/scripted_scan_results.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,cAAc,EACf,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,GAAE;IAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAO,GAChD,cAAc,EAAE,CAuBlB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { CaptureReadyEventKind, UseSmileIDScanStateType, } from "@smileid/usesmileid_bridge";
|
|
2
|
+
/**
|
|
3
|
+
* Turns a shared E2E scenario into the `FaceScanResult` sequence a capture
|
|
4
|
+
* screen receives frame-by-frame, so a headless test can replay the shared
|
|
5
|
+
* script through the frame stream's `onResult` seam (per-frame detection is a
|
|
6
|
+
* native frame-processor concern; pixels never reach JS).
|
|
7
|
+
*
|
|
8
|
+
* `noFace` → `initial`; `faceTooFar` / `faceCentered` → `found`; the terminal
|
|
9
|
+
* `satisfied` → one `finished` result carrying a `selfie` event plus
|
|
10
|
+
* [livenessCount] `liveness` events at opaque `file://` URLs the screen never
|
|
11
|
+
* reads. Exported only behind the `@smileid/usesmileid/testing` subpath.
|
|
12
|
+
*/
|
|
13
|
+
export function scriptedFaceScanResults(scenario, options = {}) {
|
|
14
|
+
const livenessCount = options.livenessCount ?? 2;
|
|
15
|
+
const output = { faces: [], brightness: 128 };
|
|
16
|
+
const results = [];
|
|
17
|
+
for (const step of scenario.steps) {
|
|
18
|
+
if (step.emit === "satisfied") {
|
|
19
|
+
results.push({
|
|
20
|
+
output,
|
|
21
|
+
state: { type: UseSmileIDScanStateType.Finished },
|
|
22
|
+
capturedEvents: captureEvents(livenessCount),
|
|
23
|
+
});
|
|
24
|
+
return results;
|
|
25
|
+
}
|
|
26
|
+
const type = step.emit === "noFace"
|
|
27
|
+
? UseSmileIDScanStateType.Initial
|
|
28
|
+
: UseSmileIDScanStateType.Found;
|
|
29
|
+
for (let frame = 0; frame < (step.holdFrames ?? 1); frame++) {
|
|
30
|
+
results.push({ output, state: { type }, capturedEvents: [] });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return results;
|
|
34
|
+
}
|
|
35
|
+
function captureEvents(livenessCount) {
|
|
36
|
+
const events = [
|
|
37
|
+
{
|
|
38
|
+
kind: CaptureReadyEventKind.Selfie,
|
|
39
|
+
captureIndex: 0,
|
|
40
|
+
url: "file://selfie-0.jpg",
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
for (let index = 1; index <= livenessCount; index++) {
|
|
44
|
+
events.push({
|
|
45
|
+
kind: CaptureReadyEventKind.Liveness,
|
|
46
|
+
captureIndex: index,
|
|
47
|
+
url: `file://liveness-${index}.jpg`,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return events;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=scripted_scan_results.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scripted_scan_results.js","sourceRoot":"","sources":["../../src/testing/scripted_scan_results.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,4BAA4B,CAAC;AAOpC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,uBAAuB,CACrC,QAA0B,EAC1B,UAA+C,EAAE;IAEjD,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,CAAC,CAAC;IACjD,MAAM,MAAM,GAA6B,EAAE,KAAK,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC;IACxE,MAAM,OAAO,GAAqB,EAAE,CAAC;IAErC,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QAClC,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC;gBACX,MAAM;gBACN,KAAK,EAAE,EAAE,IAAI,EAAE,uBAAuB,CAAC,QAAQ,EAAE;gBACjD,cAAc,EAAE,aAAa,CAAC,aAAa,CAAC;aAC7C,CAAC,CAAC;YACH,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,MAAM,IAAI,GACR,IAAI,CAAC,IAAI,KAAK,QAAQ;YACpB,CAAC,CAAC,uBAAuB,CAAC,OAAO;YACjC,CAAC,CAAC,uBAAuB,CAAC,KAAK,CAAC;QACpC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;YAC5D,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC,CAAC;QAChE,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,aAAa,CAAC,aAAqB;IAC1C,MAAM,MAAM,GAAwB;QAClC;YACE,IAAI,EAAE,qBAAqB,CAAC,MAAM;YAClC,YAAY,EAAE,CAAC;YACf,GAAG,EAAE,qBAAqB;SAC3B;KACF,CAAC;IACF,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,IAAI,aAAa,EAAE,KAAK,EAAE,EAAE,CAAC;QACpD,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,qBAAqB,CAAC,QAAQ;YACpC,YAAY,EAAE,KAAK;YACnB,GAAG,EAAE,mBAAmB,KAAK,MAAM;SACpC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smileid/usesmileid",
|
|
3
|
-
"version": "12.0.
|
|
3
|
+
"version": "12.0.1",
|
|
4
4
|
"description": "Official Smile ID React Native (Expo) SDK for identity verification: selfie capture, liveness checks, and document verification powered by on-device ML.",
|
|
5
5
|
"homepage": "https://usesmileid.com",
|
|
6
6
|
"repository": {
|
|
@@ -33,6 +33,12 @@
|
|
|
33
33
|
"react-native": "./src/index.ts",
|
|
34
34
|
"import": "./dist/index.js",
|
|
35
35
|
"require": "./dist/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./testing": {
|
|
38
|
+
"types": "./dist/testing/index.d.ts",
|
|
39
|
+
"react-native": "./src/testing/index.ts",
|
|
40
|
+
"import": "./dist/testing/index.js",
|
|
41
|
+
"require": "./dist/testing/index.js"
|
|
36
42
|
}
|
|
37
43
|
},
|
|
38
44
|
"files": [
|
|
@@ -43,9 +49,10 @@
|
|
|
43
49
|
"CHANGELOG.md"
|
|
44
50
|
],
|
|
45
51
|
"dependencies": {
|
|
46
|
-
"axios": "^1.
|
|
47
|
-
"
|
|
48
|
-
"@smileid/
|
|
52
|
+
"axios": "^1.18.1",
|
|
53
|
+
"zod": "^4.4.3",
|
|
54
|
+
"@smileid/usesmileid_bridge": "12.0.1",
|
|
55
|
+
"@smileid/usesmileid_platform_interface": "12.0.1"
|
|
49
56
|
},
|
|
50
57
|
"peerDependencies": {
|
|
51
58
|
"@react-native-async-storage/async-storage": ">=1.21.0",
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { GlobalPrivacyControl } from "../core/models/global_privacy_control";
|
|
1
2
|
import { describe, expect, it, vi } from "vitest";
|
|
2
3
|
import { AnalyzerFactoryKey } from "@smileid/usesmileid_bridge";
|
|
3
4
|
import type {
|
|
@@ -146,6 +147,28 @@ describe("useSmileIDBuilder — closure-based DSL", () => {
|
|
|
146
147
|
});
|
|
147
148
|
|
|
148
149
|
describe("config block", () => {
|
|
150
|
+
it("global privacy control defaults to opt-out", () => {
|
|
151
|
+
const config = buildOk((b) => {
|
|
152
|
+
withMinimalScreens(b);
|
|
153
|
+
b.config(() => {});
|
|
154
|
+
});
|
|
155
|
+
expect(config.config?.globalPrivacyControl).toBe(
|
|
156
|
+
GlobalPrivacyControl.OptOut,
|
|
157
|
+
);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it("global privacy control opt-in flows from the config block", () => {
|
|
161
|
+
const config = buildOk((b) => {
|
|
162
|
+
withMinimalScreens(b);
|
|
163
|
+
b.config((c) => {
|
|
164
|
+
c.globalPrivacyControl = GlobalPrivacyControl.OptIn;
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
expect(config.config?.globalPrivacyControl).toBe(
|
|
168
|
+
GlobalPrivacyControl.OptIn,
|
|
169
|
+
);
|
|
170
|
+
});
|
|
171
|
+
|
|
149
172
|
it("captures enableCrashReporting through the closure", () => {
|
|
150
173
|
const config = buildOk((b) => {
|
|
151
174
|
withMinimalScreens(b);
|
|
@@ -385,9 +408,9 @@ describe("useSmileIDBuilder — closure-based DSL", () => {
|
|
|
385
408
|
b.screens((screens) => {
|
|
386
409
|
screens.capture((cap) => {
|
|
387
410
|
cap.captureType = CaptureType.selfie;
|
|
411
|
+
// Mutually exclusive, so the closure is exercised one flag at a time.
|
|
388
412
|
cap.selfie((sel) => {
|
|
389
413
|
sel.allowAgentMode = true;
|
|
390
|
-
sel.enableEnhancedLiveness = true;
|
|
391
414
|
});
|
|
392
415
|
});
|
|
393
416
|
});
|
|
@@ -396,9 +419,36 @@ describe("useSmileIDBuilder — closure-based DSL", () => {
|
|
|
396
419
|
expect(captureStep?.kind).toBe("capture");
|
|
397
420
|
if (captureStep?.kind === "capture") {
|
|
398
421
|
expect(captureStep.config.selfieConfig?.allowAgentMode).toBe(true);
|
|
422
|
+
expect(captureStep.config.selfieConfig?.enableEnhancedLiveness).toBe(
|
|
423
|
+
false,
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
it("capture(...) plumbs enableEnhancedLiveness through the selfie closure", () => {
|
|
429
|
+
const config = buildOk((b) => {
|
|
430
|
+
b.ml((m) => {
|
|
431
|
+
m.analyzers((a) => {
|
|
432
|
+
a.forCaptureType(CaptureType.selfie, (face) =>
|
|
433
|
+
face.add(stubFaceAnalyzer),
|
|
434
|
+
);
|
|
435
|
+
});
|
|
436
|
+
});
|
|
437
|
+
b.screens((screens) => {
|
|
438
|
+
screens.capture((cap) => {
|
|
439
|
+
cap.captureType = CaptureType.selfie;
|
|
440
|
+
cap.selfie((sel) => {
|
|
441
|
+
sel.enableEnhancedLiveness = true;
|
|
442
|
+
});
|
|
443
|
+
});
|
|
444
|
+
});
|
|
445
|
+
});
|
|
446
|
+
const captureStep = config.screens.steps[0];
|
|
447
|
+
if (captureStep?.kind === "capture") {
|
|
399
448
|
expect(captureStep.config.selfieConfig?.enableEnhancedLiveness).toBe(
|
|
400
449
|
true,
|
|
401
450
|
);
|
|
451
|
+
expect(captureStep.config.selfieConfig?.allowAgentMode).toBe(false);
|
|
402
452
|
}
|
|
403
453
|
});
|
|
404
454
|
});
|
|
@@ -102,14 +102,26 @@ vi.mock("react-native-safe-area-context", () => {
|
|
|
102
102
|
// permission so the capture screen renders the preview branch in
|
|
103
103
|
// tests. Tests that exercise the undetermined / denied branches
|
|
104
104
|
// reset the mock per-test via `vi.mocked(useCameraPermission)`.
|
|
105
|
+
// Stand-in for `CameraRef.takePhoto`, so tests can drive the manual shutter.
|
|
106
|
+
// Reset per test by the shared `vi.clearAllMocks()`/`resetAllMocks()` hooks.
|
|
107
|
+
export const mockedTakePhoto = vi.fn(async () => ({
|
|
108
|
+
path: "/tmp/manual-shutter.jpg",
|
|
109
|
+
width: 1600,
|
|
110
|
+
height: 1200,
|
|
111
|
+
}));
|
|
112
|
+
|
|
105
113
|
vi.mock("react-native-vision-camera", () => {
|
|
106
|
-
function Camera(
|
|
114
|
+
const Camera = React.forwardRef(function Camera(
|
|
107
115
|
props: AnyProps & {
|
|
108
116
|
device?: unknown;
|
|
109
117
|
isActive?: boolean;
|
|
110
118
|
photo?: boolean;
|
|
111
119
|
},
|
|
120
|
+
ref: React.Ref<unknown>,
|
|
112
121
|
) {
|
|
122
|
+
// The screen reaches `takePhoto` through this ref; without it the manual
|
|
123
|
+
// shutter handler bails on a null camera and can't be tested.
|
|
124
|
+
React.useImperativeHandle(ref, () => ({ takePhoto: mockedTakePhoto }), []);
|
|
113
125
|
return React.createElement("Camera", {
|
|
114
126
|
testID: props.testID,
|
|
115
127
|
style: props.style,
|
|
@@ -117,7 +129,7 @@ vi.mock("react-native-vision-camera", () => {
|
|
|
117
129
|
isActive: props.isActive,
|
|
118
130
|
photo: props.photo,
|
|
119
131
|
});
|
|
120
|
-
}
|
|
132
|
+
});
|
|
121
133
|
const fakeDevice = {
|
|
122
134
|
id: "test-front",
|
|
123
135
|
position: "front",
|
|
@@ -237,6 +249,9 @@ vi.mock("expo-screen-orientation", () => ({
|
|
|
237
249
|
lockAsync: vi.fn(async (_lock: number) => {}),
|
|
238
250
|
unlockAsync: vi.fn(async () => {}),
|
|
239
251
|
getOrientationAsync: vi.fn(async () => 1),
|
|
252
|
+
// Defaults to a permissive host build; the lock preflight's unsupported
|
|
253
|
+
// path is opted into per-test.
|
|
254
|
+
supportsOrientationLockAsync: vi.fn(async (_lock: number) => true),
|
|
240
255
|
}));
|
|
241
256
|
|
|
242
257
|
// `expo-image-picker` backs the document gallery-upload control. Defaults to
|