diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockStateProvider.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockStateProvider.kt index 51c05820dd..77d20585d1 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockStateProvider.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockStateProvider.kt @@ -23,17 +23,19 @@ open class PinUnlockStateProvider : PreviewParameterProvider { aPinUnlockState(showWrongPinTitle = true), aPinUnlockState(showSignOutPrompt = true), aPinUnlockState(showBiometricUnlock = false), - aPinUnlockState(showSignOutPrompt = true, remainingAttempts = 0), + aPinUnlockState(showSignOutPrompt = true, remainingAttempts = AsyncData.Success(0)), aPinUnlockState(signOutAction = AsyncAction.Loading), - aPinUnlockState(biometricUnlockResult = BiometricAuthenticator.AuthenticationResult.Failure( - BiometricUnlockError(BiometricPrompt.ERROR_LOCKOUT, "Biometric auth disabled") - )), + aPinUnlockState( + biometricUnlockResult = BiometricAuthenticator.AuthenticationResult.Failure( + BiometricUnlockError(BiometricPrompt.ERROR_LOCKOUT, "Biometric auth disabled") + ) + ), ) } fun aPinUnlockState( pinEntry: PinEntry = PinEntry.createEmpty(4), - remainingAttempts: Int = 3, + remainingAttempts: AsyncData = AsyncData.Success(3), showWrongPinTitle: Boolean = false, showSignOutPrompt: Boolean = false, showBiometricUnlock: Boolean = true, @@ -43,7 +45,7 @@ fun aPinUnlockState( ) = PinUnlockState( pinEntry = AsyncData.Success(pinEntry), showWrongPinTitle = showWrongPinTitle, - remainingAttempts = AsyncData.Success(remainingAttempts), + remainingAttempts = remainingAttempts, showSignOutPrompt = showSignOutPrompt, showBiometricUnlock = showBiometricUnlock, signOutAction = signOutAction, diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockStateTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockStateTest.kt new file mode 100644 index 0000000000..389ebf83c7 --- /dev/null +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockStateTest.kt @@ -0,0 +1,76 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.lockscreen.impl.unlock + +import androidx.biometric.BiometricPrompt +import com.google.common.truth.Truth.assertThat +import io.element.android.features.lockscreen.impl.biometric.BiometricAuthenticator +import io.element.android.features.lockscreen.impl.biometric.BiometricUnlockError +import io.element.android.libraries.architecture.AsyncData +import org.junit.Test + +class PinUnlockStateTest { + @Test + fun `isSignOutPromptCancellable should have expected values`() { + assertThat(aPinUnlockState(remainingAttempts = AsyncData.Uninitialized).isSignOutPromptCancellable).isTrue() + assertThat(aPinUnlockState(remainingAttempts = AsyncData.Success(1)).isSignOutPromptCancellable).isTrue() + assertThat(aPinUnlockState(remainingAttempts = AsyncData.Success(0)).isSignOutPromptCancellable).isFalse() + } + + @Test + fun `biometricUnlockErrorMessage and showBiometricUnlockError should have expected values`() { + listOf( + null, + BiometricAuthenticator.AuthenticationResult.Failure(), + BiometricAuthenticator.AuthenticationResult.Success, + ).forEach { biometricUnlockResult -> + aPinUnlockState( + biometricUnlockResult = biometricUnlockResult, + ).let { + assertThat(it.biometricUnlockErrorMessage).isNull() + assertThat(it.showBiometricUnlockError).isFalse() + } + } + listOf( + BiometricPrompt.ERROR_HW_UNAVAILABLE, + BiometricPrompt.ERROR_UNABLE_TO_PROCESS, + BiometricPrompt.ERROR_TIMEOUT, + BiometricPrompt.ERROR_NO_SPACE, + BiometricPrompt.ERROR_CANCELED, + BiometricPrompt.ERROR_VENDOR, + BiometricPrompt.ERROR_USER_CANCELED, + BiometricPrompt.ERROR_NO_BIOMETRICS, + BiometricPrompt.ERROR_HW_NOT_PRESENT, + BiometricPrompt.ERROR_NEGATIVE_BUTTON, + BiometricPrompt.ERROR_NO_DEVICE_CREDENTIAL, + BiometricPrompt.ERROR_SECURITY_UPDATE_REQUIRED, + ).forEach { code -> + aPinUnlockState( + biometricUnlockResult = BiometricAuthenticator.AuthenticationResult.Failure( + error = BiometricUnlockError(code, "Error message") + ), + ).let { + assertThat(it.biometricUnlockErrorMessage).isNull() + assertThat(it.showBiometricUnlockError).isFalse() + } + } + listOf( + BiometricPrompt.ERROR_LOCKOUT, + BiometricPrompt.ERROR_LOCKOUT_PERMANENT, + ).forEach { code -> + aPinUnlockState( + biometricUnlockResult = BiometricAuthenticator.AuthenticationResult.Failure( + error = BiometricUnlockError(code, "Error message") + ), + ).let { + assertThat(it.biometricUnlockErrorMessage).isEqualTo("Error message") + assertThat(it.showBiometricUnlockError).isTrue() + } + } + } +}