[PM-13257] Checking if user is navigating from vault before showing prompt for biometrics (#4846)

This commit is contained in:
aj-rosado 2025-03-19 10:23:50 +00:00 committed by GitHub
parent f4f669683e
commit ad6bc883b8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 108 additions and 56 deletions

View File

@ -116,7 +116,10 @@ class AuthenticatorBridgeRepositoryImpl(
// Lock the user's vault if we unlocked it for this operation:
if (!isVaultAlreadyUnlocked) {
vaultRepository.lockVault(userId)
vaultRepository.lockVault(
userId = userId,
isUserInitiated = false,
)
}
SharedAccountData.Account(

View File

@ -22,6 +22,11 @@ interface VaultLockManager {
*/
val vaultStateEventFlow: Flow<VaultStateEvent>
/**
* Whether the user is coming from the lock flow or not.
*/
var isFromLockFlow: Boolean
/**
* Whether or not the vault is currently locked for the given [userId].
*/
@ -35,12 +40,12 @@ interface VaultLockManager {
/**
* Locks the vault for the user with the given [userId].
*/
fun lockVault(userId: String)
fun lockVault(userId: String, isUserInitiated: Boolean)
/**
* Locks the vault for the current user if currently unlocked.
*/
fun lockVaultForCurrentUser()
fun lockVaultForCurrentUser(isUserInitiated: Boolean)
/**
* Attempt to unlock the vault with the specified user information.

View File

@ -101,6 +101,8 @@ class VaultLockManagerImpl(
override val vaultStateEventFlow: Flow<VaultStateEvent>
get() = mutableVaultStateEventSharedFlow.asSharedFlow()
override var isFromLockFlow: Boolean = false
init {
observeAppCreationChanges()
observeAppForegroundChanges()
@ -119,13 +121,17 @@ class VaultLockManagerImpl(
override fun isVaultUnlocking(userId: String): Boolean =
mutableVaultUnlockDataStateFlow.value.statusFor(userId) == VaultUnlockData.Status.UNLOCKING
override fun lockVault(userId: String) {
override fun lockVault(userId: String, isUserInitiated: Boolean) {
isFromLockFlow = isUserInitiated
setVaultToLocked(userId = userId)
}
override fun lockVaultForCurrentUser() {
override fun lockVaultForCurrentUser(isUserInitiated: Boolean) {
activeUserId?.let {
lockVault(it)
lockVault(
userId = it,
isUserInitiated = isUserInitiated,
)
}
}

View File

@ -127,7 +127,7 @@ class LandingViewModel @Inject constructor(
}
private fun handleLockAccountClicked(action: LandingAction.LockAccountClick) {
vaultRepository.lockVault(userId = action.accountSummary.userId)
vaultRepository.lockVault(userId = action.accountSummary.userId, isUserInitiated = true)
}
private fun handleLogoutAccountClicked(action: LandingAction.LogoutAccountClick) {

View File

@ -108,7 +108,7 @@ class LoginViewModel @Inject constructor(
}
private fun handleLockAccountClicked(action: LoginAction.LockAccountClick) {
vaultRepository.lockVault(userId = action.accountSummary.userId)
vaultRepository.lockVault(userId = action.accountSummary.userId, isUserInitiated = true)
}
private fun handleLogoutAccountClicked(action: LoginAction.LogoutAccountClick) {

View File

@ -16,6 +16,7 @@ import com.x8bit.bitwarden.data.platform.manager.BiometricsEncryptionManager
import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManager
import com.x8bit.bitwarden.data.platform.manager.model.SpecialCircumstance
import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository
import com.x8bit.bitwarden.data.vault.manager.VaultLockManager
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockResult
import com.x8bit.bitwarden.ui.auth.feature.vaultunlock.model.UnlockType
@ -54,6 +55,7 @@ class VaultUnlockViewModel @Inject constructor(
private val specialCircumstanceManager: SpecialCircumstanceManager,
private val fido2CredentialManager: Fido2CredentialManager,
private val appResumeManager: AppResumeManager,
private val vaultLockManager: VaultLockManager,
environmentRepo: EnvironmentRepository,
savedStateHandle: SavedStateHandle,
) : BaseViewModel<VaultUnlockState, VaultUnlockEvent, VaultUnlockAction>(
@ -100,6 +102,7 @@ class VaultUnlockViewModel @Inject constructor(
// TODO: [PM-13076] Handle Fido2CredentialAssertionRequest special circumstance
fido2CredentialAssertionRequest = null,
hasMasterPassword = activeAccount.hasMasterPassword,
isFromLockFlow = vaultLockManager.isFromLockFlow,
)
},
) {
@ -120,6 +123,11 @@ class VaultUnlockViewModel @Inject constructor(
.launchIn(viewModelScope)
promptForBiometricsIfAvailable()
// only when navigating from vault to lock we should not display biometrics
// subsequent views of the lock screen should display biometrics if available
vaultLockManager.isFromLockFlow = false
mutableStateFlow.update { it.copy(isFromLockFlow = false) }
}
override fun onCleared() {
@ -209,7 +217,7 @@ class VaultUnlockViewModel @Inject constructor(
}
private fun handleLockAccountClick(action: VaultUnlockAction.LockAccountClick) {
vaultRepo.lockVault(userId = action.accountSummary.userId)
vaultRepo.lockVault(userId = action.accountSummary.userId, isUserInitiated = true)
}
private fun handleLogoutAccountClick(action: VaultUnlockAction.LogoutAccountClick) {
@ -425,7 +433,7 @@ class VaultUnlockViewModel @Inject constructor(
private fun promptForBiometricsIfAvailable() {
val cipher = biometricsEncryptionManager.getOrCreateCipher(state.userId)
if (state.showBiometricLogin && cipher != null) {
if (state.showBiometricLogin && cipher != null && !state.isFromLockFlow) {
sendEvent(
VaultUnlockEvent.PromptForBiometrics(
cipher = cipher,
@ -458,6 +466,7 @@ data class VaultUnlockState(
val fido2GetCredentialsRequest: Fido2GetCredentialsRequest? = null,
val fido2CredentialAssertionRequest: Fido2CredentialAssertionRequest? = null,
private val hasMasterPassword: Boolean,
val isFromLockFlow: Boolean,
) : Parcelable {
/**

View File

@ -265,7 +265,7 @@ class AccountSecurityViewModel @Inject constructor(
}
private fun handleLockNowClick() {
vaultRepository.lockVaultForCurrentUser()
vaultRepository.lockVaultForCurrentUser(isUserInitiated = true)
}
private fun handlePushNotificationConfirm() {

View File

@ -258,7 +258,7 @@ class SendViewModel @Inject constructor(
}
private fun handleLockClick() {
vaultRepo.lockVaultForCurrentUser()
vaultRepo.lockVaultForCurrentUser(isUserInitiated = true)
}
private fun handleRefreshClick() {

View File

@ -286,7 +286,7 @@ class VaultItemListingViewModel @Inject constructor(
//region VaultItemListing Handlers
private fun handleLockAccountClick(action: VaultItemListingsAction.LockAccountClick) {
vaultRepository.lockVault(userId = action.accountSummary.userId)
vaultRepository.lockVault(userId = action.accountSummary.userId, isUserInitiated = true)
}
private fun handleLogoutAccountClick(action: VaultItemListingsAction.LogoutAccountClick) {
@ -1023,7 +1023,7 @@ class VaultItemListingViewModel @Inject constructor(
}
private fun handleLockClick() {
vaultRepository.lockVaultForCurrentUser()
vaultRepository.lockVaultForCurrentUser(isUserInitiated = true)
}
private fun handleSyncClick() {

View File

@ -327,7 +327,7 @@ class VaultViewModel @Inject constructor(
}
private fun handleLockAccountClick(action: VaultAction.LockAccountClick) {
vaultRepository.lockVault(userId = action.accountSummary.userId)
vaultRepository.lockVault(userId = action.accountSummary.userId, isUserInitiated = true)
}
private fun handleLogoutAccountClick(action: VaultAction.LogoutAccountClick) {
@ -374,7 +374,7 @@ class VaultViewModel @Inject constructor(
}
private fun handleLockClick() {
vaultRepository.lockVaultForCurrentUser()
vaultRepository.lockVaultForCurrentUser(isUserInitiated = true)
}
private fun handleExitConfirmationClick() {

View File

@ -119,7 +119,7 @@ class VerificationCodeViewModel @Inject constructor(
}
private fun handleLockClick() {
vaultRepository.lockVaultForCurrentUser()
vaultRepository.lockVaultForCurrentUser(isUserInitiated = true)
}
private fun handleRefreshClick() {

View File

@ -88,7 +88,7 @@ class AuthenticatorBridgeRepositoryTest {
every { vaultRepository.isVaultUnlocked(USER_1_ID) } returns true
// But locked for user 2:
every { vaultRepository.isVaultUnlocked(USER_2_ID) } returns false
every { vaultRepository.lockVault(USER_2_ID) } returns Unit
every { vaultRepository.lockVault(USER_2_ID, isUserInitiated = false) } returns Unit
coEvery {
vaultRepository.unlockVaultWithDecryptedUserKey(
userId = USER_2_ID,
@ -147,7 +147,7 @@ class AuthenticatorBridgeRepositoryTest {
decryptedUserKey = USER_2_UNLOCK_KEY,
)
}
verify { vaultRepository.lockVault(USER_2_ID) }
verify { vaultRepository.lockVault(USER_2_ID, isUserInitiated = false) }
coVerify { vaultSdkSource.decryptCipher(USER_1_ID, USER_1_ENCRYPTED_SDK_TOTP_CIPHER) }
coVerify { vaultSdkSource.decryptCipher(USER_2_ID, USER_2_ENCRYPTED_SDK_TOTP_CIPHER) }
}
@ -185,7 +185,7 @@ class AuthenticatorBridgeRepositoryTest {
)
}
verify { vaultRepository.vaultUnlockDataStateFlow }
verify { vaultRepository.lockVault(USER_2_ID) }
verify { vaultRepository.lockVault(USER_2_ID, isUserInitiated = false) }
verify { vaultDiskSource.getCiphers(USER_2_ID) }
coVerify { vaultSdkSource.decryptCipher(USER_2_ID, USER_2_ENCRYPTED_SDK_TOTP_CIPHER) }
}
@ -198,7 +198,7 @@ class AuthenticatorBridgeRepositoryTest {
coEvery {
vaultRepository.unlockVaultWithDecryptedUserKey(USER_1_ID, USER_1_UNLOCK_KEY)
} returns VaultUnlockResult.Success
every { vaultRepository.lockVault(USER_1_ID) } returns Unit
every { vaultRepository.lockVault(USER_1_ID, isUserInitiated = false) } returns Unit
val sharedAccounts = authenticatorBridgeRepository.getSharedAccounts()
assertEquals(
@ -216,7 +216,7 @@ class AuthenticatorBridgeRepositoryTest {
decryptedUserKey = USER_1_UNLOCK_KEY,
)
}
verify { vaultRepository.lockVault(USER_1_ID) }
verify { vaultRepository.lockVault(USER_1_ID, isUserInitiated = false) }
verify { vaultRepository.isVaultUnlocked(USER_2_ID) }
coVerify {
vaultRepository.unlockVaultWithDecryptedUserKey(
@ -225,7 +225,7 @@ class AuthenticatorBridgeRepositoryTest {
)
}
verify { vaultRepository.vaultUnlockDataStateFlow }
verify { vaultRepository.lockVault(USER_2_ID) }
verify { vaultRepository.lockVault(USER_2_ID, isUserInitiated = false) }
verify { vaultDiskSource.getCiphers(USER_2_ID) }
coVerify { vaultSdkSource.decryptCipher(USER_2_ID, USER_2_ENCRYPTED_SDK_TOTP_CIPHER) }
}
@ -260,7 +260,7 @@ class AuthenticatorBridgeRepositoryTest {
)
}
verify { vaultRepository.vaultUnlockDataStateFlow }
verify { vaultRepository.lockVault(USER_2_ID) }
verify { vaultRepository.lockVault(USER_2_ID, isUserInitiated = false) }
verify { vaultDiskSource.getCiphers(USER_2_ID) }
coVerify { vaultSdkSource.decryptCipher(USER_2_ID, USER_2_ENCRYPTED_SDK_TOTP_CIPHER) }
}
@ -307,7 +307,7 @@ class AuthenticatorBridgeRepositoryTest {
decryptedUserKey = USER_2_UNLOCK_KEY,
)
}
verify { vaultRepository.lockVault(USER_2_ID) }
verify { vaultRepository.lockVault(USER_2_ID, isUserInitiated = false) }
coVerify { vaultSdkSource.decryptCipher(USER_1_ID, USER_1_ENCRYPTED_SDK_TOTP_CIPHER) }
coVerify { vaultSdkSource.decryptCipher(USER_2_ID, USER_2_ENCRYPTED_SDK_TOTP_CIPHER) }
}

View File

@ -165,7 +165,7 @@ class VaultLockManagerTest {
verifyUnlockedVault(userId = USER_ID)
vaultLockManager.vaultStateEventFlow.test {
vaultLockManager.lockVault(userId = USER_ID)
vaultLockManager.lockVault(userId = USER_ID, isUserInitiated = false)
assertEquals(VaultStateEvent.Locked(userId = USER_ID), awaitItem())
fakeAuthDiskSource.assertLastLockTimestamp(
userId = USER_ID,
@ -178,10 +178,10 @@ class VaultLockManagerTest {
fun `vaultStateEventFlow should not emit Locked event when vault state remains locked`() =
runTest {
// Ensure the vault is locked
vaultLockManager.lockVault(userId = USER_ID)
vaultLockManager.lockVault(userId = USER_ID, isUserInitiated = false)
vaultLockManager.vaultStateEventFlow.test {
vaultLockManager.lockVault(userId = USER_ID)
vaultLockManager.lockVault(userId = USER_ID, isUserInitiated = false)
expectNoEvents()
}
}
@ -190,7 +190,7 @@ class VaultLockManagerTest {
fun `vaultStateEventFlow should emit Unlocked event when vault state changes to unlocked`() =
runTest {
// Ensure the vault is locked
vaultLockManager.lockVault(userId = USER_ID)
vaultLockManager.lockVault(userId = USER_ID, isUserInitiated = false)
vaultLockManager.vaultStateEventFlow.test {
verifyUnlockedVault(userId = USER_ID)
@ -786,7 +786,7 @@ class VaultLockManagerTest {
vaultLockManager.vaultUnlockDataStateFlow.value,
)
vaultLockManager.lockVault(userId = USER_ID)
vaultLockManager.lockVault(userId = USER_ID, isUserInitiated = false)
assertEquals(
emptyList<VaultUnlockData>(),
@ -811,7 +811,7 @@ class VaultLockManagerTest {
vaultLockManager.vaultUnlockDataStateFlow.value,
)
vaultLockManager.lockVault(userId = USER_ID)
vaultLockManager.lockVault(userId = USER_ID, isUserInitiated = false)
assertEquals(
emptyList<VaultUnlockData>(),
@ -837,7 +837,7 @@ class VaultLockManagerTest {
vaultLockManager.vaultUnlockDataStateFlow.value,
)
vaultLockManager.lockVaultForCurrentUser()
vaultLockManager.lockVaultForCurrentUser(isUserInitiated = true)
assertEquals(
emptyList<VaultUnlockData>(),

View File

@ -191,8 +191,8 @@ class VaultRepositoryTest {
userId in mutableUnlockedUserIdsStateFlow.value
}
every { isVaultUnlocking(any()) } returns false
every { lockVault(any()) } just runs
every { lockVaultForCurrentUser() } just runs
every { lockVault(any(), any()) } just runs
every { lockVaultForCurrentUser(any()) } just runs
coEvery {
waitUntilUnlocked(any())
} coAnswers { call ->
@ -1156,8 +1156,8 @@ class VaultRepositoryTest {
@Test
fun `lockVaultForCurrentUser should delegate to the VaultLockManager`() {
vaultRepository.lockVaultForCurrentUser()
verify { vaultLockManager.lockVaultForCurrentUser() }
vaultRepository.lockVaultForCurrentUser(isUserInitiated = true)
verify { vaultLockManager.lockVaultForCurrentUser(isUserInitiated = true) }
}
@Test

View File

@ -35,7 +35,7 @@ class LandingViewModelTest : BaseViewModelTest() {
every { logout(any()) } just runs
}
private val vaultRepository: VaultRepository = mockk(relaxed = true) {
every { lockVault(any()) } just runs
every { lockVault(any(), any()) } just runs
}
private val fakeEnvironmentRepository = FakeEnvironmentRepository()
@ -126,7 +126,7 @@ class LandingViewModelTest : BaseViewModelTest() {
viewModel.trySendAction(LandingAction.LockAccountClick(accountSummary))
verify { vaultRepository.lockVault(userId = accountUserId) }
verify { vaultRepository.lockVault(userId = accountUserId, isUserInitiated = true) }
}
@Test

View File

@ -51,7 +51,7 @@ class LoginViewModelTest : BaseViewModelTest() {
every { logout(any()) } just runs
}
private val vaultRepository: VaultRepository = mockk(relaxed = true) {
every { lockVault(any()) } just runs
every { lockVault(any(), any()) } just runs
}
private val fakeEnvironmentRepository = FakeEnvironmentRepository()
@ -204,7 +204,7 @@ class LoginViewModelTest : BaseViewModelTest() {
viewModel.trySendAction(LoginAction.LockAccountClick(accountSummary))
verify { vaultRepository.lockVault(userId = accountUserId) }
verify { vaultRepository.lockVault(userId = accountUserId, isUserInitiated = true) }
}
@Test

View File

@ -646,4 +646,5 @@ private val DEFAULT_STATE: VaultUnlockState = VaultUnlockState(
userId = ACTIVE_ACCOUNT_SUMMARY.userId,
vaultUnlockType = VaultUnlockType.MASTER_PASSWORD,
hasMasterPassword = true,
isFromLockFlow = false,
)

View File

@ -21,6 +21,7 @@ import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository
import com.x8bit.bitwarden.data.platform.repository.model.Environment
import com.x8bit.bitwarden.data.platform.repository.util.FakeEnvironmentRepository
import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow
import com.x8bit.bitwarden.data.vault.manager.VaultLockManager
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockResult
import com.x8bit.bitwarden.ui.auth.feature.vaultunlock.model.UnlockType
@ -60,7 +61,7 @@ class VaultUnlockViewModelTest : BaseViewModelTest() {
every { switchAccount(any()) } returns SwitchAccountResult.AccountSwitched
}
private val vaultRepository: VaultRepository = mockk(relaxed = true) {
every { lockVault(any()) } just runs
every { lockVault(any(), any()) } just runs
}
private val encryptionManager: BiometricsEncryptionManager = mockk {
every { getOrCreateCipher(USER_ID) } returns CIPHER
@ -91,6 +92,10 @@ class VaultUnlockViewModelTest : BaseViewModelTest() {
every { getResumeSpecialCircumstance() } returns null
}
private val vaultLockManager: VaultLockManager = mockk(relaxed = true) {
every { isFromLockFlow } returns false
}
@Test
fun `on init with biometrics enabled and valid should emit PromptForBiometrics`() = runTest {
val initialState = DEFAULT_STATE.copy(
@ -502,6 +507,25 @@ class VaultUnlockViewModelTest : BaseViewModelTest() {
verify { encryptionManager.getOrCreateCipher(USER_ID) }
}
@Test
@Suppress("MaxLineLength")
fun `on BiometricsUnlockClick should not emit PromptForBiometrics when isFromLockFlow is true`() =
runTest {
val initialState =
DEFAULT_STATE.copy(
isBiometricsValid = true,
isBiometricEnabled = true,
isFromLockFlow = true,
)
val viewModel = createViewModel(
state = initialState,
)
viewModel.eventFlow.test {
expectNoEvents()
}
}
@Suppress("MaxLineLength")
@Test
fun `on BiometricsUnlockClick should disable isBiometricsValid and show message when cipher is null and integrity check returns false`() {
@ -629,7 +653,7 @@ class VaultUnlockViewModelTest : BaseViewModelTest() {
viewModel.trySendAction(VaultUnlockAction.LockAccountClick(accountSummary))
verify { vaultRepository.lockVault(userId = accountUserId) }
verify { vaultRepository.lockVault(userId = accountUserId, isUserInitiated = true) }
}
@Test
@ -1301,12 +1325,14 @@ class VaultUnlockViewModelTest : BaseViewModelTest() {
}
}
@Suppress("LongParameterList")
private fun createViewModel(
state: VaultUnlockState? = null,
unlockType: UnlockType = UnlockType.STANDARD,
environmentRepo: EnvironmentRepository = environmentRepository,
vaultRepo: VaultRepository = vaultRepository,
biometricsEncryptionManager: BiometricsEncryptionManager = encryptionManager,
lockManager: VaultLockManager = vaultLockManager,
): VaultUnlockViewModel = VaultUnlockViewModel(
savedStateHandle = SavedStateHandle().apply {
set("state", state)
@ -1319,6 +1345,7 @@ class VaultUnlockViewModelTest : BaseViewModelTest() {
fido2CredentialManager = fido2CredentialManager,
specialCircumstanceManager = specialCircumstanceManager,
appResumeManager = appResumeManager,
vaultLockManager = lockManager,
)
}
@ -1351,6 +1378,7 @@ private val DEFAULT_STATE: VaultUnlockState = VaultUnlockState(
userId = USER_ID,
vaultUnlockType = VaultUnlockType.MASTER_PASSWORD,
hasMasterPassword = true,
isFromLockFlow = false,
)
private val TRUSTED_DEVICE: UserState.TrustedDevice = UserState.TrustedDevice(

View File

@ -383,10 +383,10 @@ class AccountSecurityViewModelTest : BaseViewModelTest() {
@Test
fun `on LockNowClick should call lockVaultForCurrentUser`() {
every { vaultRepository.lockVaultForCurrentUser() } just runs
every { vaultRepository.lockVaultForCurrentUser(any()) } just runs
val viewModel = createViewModel()
viewModel.trySendAction(AccountSecurityAction.LockNowClick)
verify { vaultRepository.lockVaultForCurrentUser() }
verify { vaultRepository.lockVaultForCurrentUser(any()) }
}
@Test

View File

@ -102,12 +102,12 @@ class SendViewModelTest : BaseViewModelTest() {
@Test
fun `LockClick should lock the vault`() {
val viewModel = createViewModel()
every { vaultRepo.lockVaultForCurrentUser() } just runs
every { vaultRepo.lockVaultForCurrentUser(any()) } just runs
viewModel.trySendAction(SendAction.LockClick)
verify {
vaultRepo.lockVaultForCurrentUser()
vaultRepo.lockVaultForCurrentUser(isUserInitiated = true)
}
}

View File

@ -143,7 +143,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
private val vaultRepository: VaultRepository = mockk {
every { vaultFilterType } returns VaultFilterType.AllVaults
every { vaultDataStateFlow } returns mutableVaultDataStateFlow
every { lockVault(any()) } just runs
every { lockVault(any(), any()) } just runs
every { sync(forced = any()) } just runs
coEvery {
getDecryptedFido2CredentialAutofillViews(any())
@ -247,7 +247,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
viewModel.trySendAction(VaultItemListingsAction.LockAccountClick(accountSummary))
verify { vaultRepository.lockVault(userId = accountUserId) }
verify { vaultRepository.lockVault(userId = accountUserId, isUserInitiated = true) }
}
@Test
@ -360,13 +360,13 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
@Test
fun `LockClick should call lockVaultForCurrentUser`() {
every { vaultRepository.lockVaultForCurrentUser() } just runs
every { vaultRepository.lockVaultForCurrentUser(any()) } just runs
val viewModel = createVaultItemListingViewModel()
viewModel.trySendAction(VaultItemListingsAction.LockClick)
verify(exactly = 1) {
vaultRepository.lockVaultForCurrentUser()
vaultRepository.lockVaultForCurrentUser(isUserInitiated = true)
}
}

View File

@ -131,8 +131,8 @@ class VaultViewModelTest : BaseViewModelTest() {
every { vaultDataStateFlow } returns mutableVaultDataStateFlow
every { sync(forced = any()) } just runs
every { syncIfNecessary() } just runs
every { lockVaultForCurrentUser() } just runs
every { lockVault(any()) } just runs
every { lockVaultForCurrentUser(any()) } just runs
every { lockVault(any(), any()) } just runs
}
private val organizationEventManager = mockk<OrganizationEventManager> {
@ -382,7 +382,7 @@ class VaultViewModelTest : BaseViewModelTest() {
viewModel.trySendAction(VaultAction.LockAccountClick(accountSummary))
verify { vaultRepository.lockVault(userId = accountUserId) }
verify { vaultRepository.lockVault(userId = accountUserId, isUserInitiated = true) }
}
@Suppress("MaxLineLength")
@ -520,7 +520,7 @@ class VaultViewModelTest : BaseViewModelTest() {
val viewModel = createViewModel()
viewModel.trySendAction(VaultAction.LockClick)
verify {
vaultRepository.lockVaultForCurrentUser()
vaultRepository.lockVaultForCurrentUser(isUserInitiated = true)
}
}

View File

@ -131,13 +131,13 @@ class VerificationCodeViewModelTest : BaseViewModelTest() {
@Test
fun `LockClick should call lockVaultForCurrentUser`() {
every { vaultRepository.lockVaultForCurrentUser() } just runs
every { vaultRepository.lockVaultForCurrentUser(any()) } just runs
val viewModel = createViewModel()
viewModel.trySendAction(VerificationCodeAction.LockClick)
verify(exactly = 1) {
vaultRepository.lockVaultForCurrentUser()
vaultRepository.lockVaultForCurrentUser(isUserInitiated = true)
}
}