From 3e655da2a84f770ceb895c2a3aae0389b19cddc1 Mon Sep 17 00:00:00 2001 From: alex Date: Mon, 15 Jun 2026 14:49:28 +0300 Subject: [PATCH] [MS-1470] Scanning noew checks that there are not enough captures before updating the scanning progress state --- .../ExternalCredentialScanOcrViewModel.kt | 3 +- .../ExternalCredentialScanOcrViewModelTest.kt | 47 +++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/feature/external-credential/src/main/java/com/simprints/feature/externalcredential/screens/scanocr/ExternalCredentialScanOcrViewModel.kt b/feature/external-credential/src/main/java/com/simprints/feature/externalcredential/screens/scanocr/ExternalCredentialScanOcrViewModel.kt index 7dd587cf55..b5df3475c8 100644 --- a/feature/external-credential/src/main/java/com/simprints/feature/externalcredential/screens/scanocr/ExternalCredentialScanOcrViewModel.kt +++ b/feature/external-credential/src/main/java/com/simprints/feature/externalcredential/screens/scanocr/ExternalCredentialScanOcrViewModel.kt @@ -147,7 +147,8 @@ internal class ExternalCredentialScanOcrViewModel @AssistedInject constructor( val scannedMfidDocument = scanMfidDocumentUseCase(bitmap = cropped, documentType = ocrDocumentType, config = mfidConfig) ?: return@launch Simber.d("Detected OCR") - if (isScanningInProgress) { + val notEnoughCaptures = scannedMfidDocuments.size < ocrConfig.capturesRequired + if (isScanningInProgress && notEnoughCaptures) { scannedMfidDocuments += scannedMfidDocument updateState { ScanOcrState.ScanningInProgress( diff --git a/feature/external-credential/src/test/java/com/simprints/feature/externalcredential/screens/scanocr/ExternalCredentialScanOcrViewModelTest.kt b/feature/external-credential/src/test/java/com/simprints/feature/externalcredential/screens/scanocr/ExternalCredentialScanOcrViewModelTest.kt index f111985589..44a7abc46b 100644 --- a/feature/external-credential/src/test/java/com/simprints/feature/externalcredential/screens/scanocr/ExternalCredentialScanOcrViewModelTest.kt +++ b/feature/external-credential/src/test/java/com/simprints/feature/externalcredential/screens/scanocr/ExternalCredentialScanOcrViewModelTest.kt @@ -325,6 +325,53 @@ internal class ExternalCredentialScanOcrViewModelTest { assertThat(result).isEqualTo(R.string.mfid_type_ghana_id_card) } + @Test + fun `processImage does not add documents or update state once required captures are reached`() = runTest { + val mockScannedDocument = mockk() + val mockNormalizedBitmap = mockk() + val mockCroppedBitmap = mockk() + + coEvery { normalizeBitmapToPreviewUseCase(bitmap, cropConfig) } returns mockNormalizedBitmap + coEvery { cropDocumentFromPreviewUseCase(mockNormalizedBitmap, any()) } returns mockCroppedBitmap + coEvery { scanMfidDocumentUseCase(mockCroppedBitmap, documentType, any()) } returns mockScannedDocument + + val observer = viewModel.scanOcrStateLiveData.test() + viewModel.startScanning() + + val capturesRequired = (observer.value() as ScanOcrState.ScanningInProgress).scansRequired + repeat(capturesRequired) { viewModel.processImage(bitmap, cropConfig) } + + val stateAtCapacity = observer.value() as ScanOcrState.ScanningInProgress + assertThat(stateAtCapacity.successfulCaptures).isEqualTo(capturesRequired) + + viewModel.processImage(bitmap, cropConfig) + + assertThat(observer.value()).isEqualTo(stateAtCapacity) + } + + @Test + fun `processImage emits ScanningInProgress with enough captures exactly once`() = runTest { + val mockScannedDocument = mockk() + val mockNormalizedBitmap = mockk() + val mockCroppedBitmap = mockk() + + coEvery { normalizeBitmapToPreviewUseCase(bitmap, cropConfig) } returns mockNormalizedBitmap + coEvery { cropDocumentFromPreviewUseCase(mockNormalizedBitmap, any()) } returns mockCroppedBitmap + coEvery { scanMfidDocumentUseCase(mockCroppedBitmap, documentType, any()) } returns mockScannedDocument + + val observer = viewModel.scanOcrStateLiveData.test() + viewModel.startScanning() + + val capturesRequired = (observer.value() as ScanOcrState.ScanningInProgress).scansRequired + repeat(capturesRequired + 2) { viewModel.processImage(bitmap, cropConfig) } + + val completionTriggers = observer + .valueHistory() + .filterIsInstance() + .count { it.successfulCaptures >= it.scansRequired } + assertThat(completionTriggers).isEqualTo(1) + } + @Test fun `processImage does not append documents or update state after scanning is complete`() = runTest { val mockScannedDocument = mockk()