mirror of
https://github.com/bitwarden/android.git
synced 2024-12-21 16:44:29 +03:00
All user input syncs should be forced (#4370)
This commit is contained in:
parent
a1881ce4d9
commit
366c86da41
16 changed files with 107 additions and 93 deletions
|
@ -109,7 +109,7 @@ interface VaultRepository : CipherManager, VaultLockManager {
|
||||||
* Unlike [syncIfNecessary], this will always perform the requested sync and should only be
|
* Unlike [syncIfNecessary], this will always perform the requested sync and should only be
|
||||||
* utilized in cases where the user specifically requested the action.
|
* utilized in cases where the user specifically requested the action.
|
||||||
*/
|
*/
|
||||||
fun sync()
|
fun sync(forced: Boolean = false)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if conditions have been met to perform a sync request and, if so, syncs the vault
|
* Checks if conditions have been met to perform a sync request and, if so, syncs the vault
|
||||||
|
|
|
@ -345,7 +345,7 @@ class VaultRepositoryImpl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun sync() {
|
override fun sync(forced: Boolean) {
|
||||||
val userId = activeUserId ?: return
|
val userId = activeUserId ?: return
|
||||||
if (!syncJob.isCompleted) return
|
if (!syncJob.isCompleted) return
|
||||||
mutableCiphersStateFlow.updateToPendingOrLoading()
|
mutableCiphersStateFlow.updateToPendingOrLoading()
|
||||||
|
@ -353,7 +353,7 @@ class VaultRepositoryImpl(
|
||||||
mutableFoldersStateFlow.updateToPendingOrLoading()
|
mutableFoldersStateFlow.updateToPendingOrLoading()
|
||||||
mutableCollectionsStateFlow.updateToPendingOrLoading()
|
mutableCollectionsStateFlow.updateToPendingOrLoading()
|
||||||
mutableSendDataStateFlow.updateToPendingOrLoading()
|
mutableSendDataStateFlow.updateToPendingOrLoading()
|
||||||
syncJob = ioScope.launch { syncInternal(userId) }
|
syncJob = ioScope.launch { syncInternal(userId = userId, forced = forced) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MagicNumber")
|
@Suppress("MagicNumber")
|
||||||
|
@ -374,10 +374,9 @@ class VaultRepositoryImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun syncForResult(): SyncVaultDataResult {
|
override suspend fun syncForResult(): SyncVaultDataResult {
|
||||||
val userId = activeUserId
|
val userId = activeUserId ?: return SyncVaultDataResult.Error(throwable = null)
|
||||||
?: return SyncVaultDataResult.Error(throwable = null)
|
|
||||||
syncJob = ioScope
|
syncJob = ioScope
|
||||||
.async { syncInternal(userId) }
|
.async { syncInternal(userId = userId, forced = false) }
|
||||||
.also {
|
.also {
|
||||||
return try {
|
return try {
|
||||||
it.await()
|
it.await()
|
||||||
|
@ -1339,51 +1338,53 @@ class VaultRepositoryImpl(
|
||||||
//endregion Push Notification helpers
|
//endregion Push Notification helpers
|
||||||
|
|
||||||
@Suppress("LongMethod")
|
@Suppress("LongMethod")
|
||||||
private suspend fun syncInternal(userId: String): SyncVaultDataResult {
|
private suspend fun syncInternal(
|
||||||
val lastSyncInstant = settingsDiskSource
|
userId: String,
|
||||||
.getLastSyncTime(userId = userId)
|
forced: Boolean,
|
||||||
?.toEpochMilli()
|
): SyncVaultDataResult {
|
||||||
?: 0
|
if (!forced) {
|
||||||
|
// Skip this check if we are forcing the request.
|
||||||
|
val lastSyncInstant = settingsDiskSource
|
||||||
|
.getLastSyncTime(userId = userId)
|
||||||
|
?.toEpochMilli()
|
||||||
|
?: 0
|
||||||
|
val lastDatabaseSchemeChangeInstant = databaseSchemeManager
|
||||||
|
.lastDatabaseSchemeChangeInstant
|
||||||
|
?.toEpochMilli()
|
||||||
|
?: 0
|
||||||
|
syncService
|
||||||
|
.getAccountRevisionDateMillis()
|
||||||
|
.fold(
|
||||||
|
onSuccess = { serverRevisionDate ->
|
||||||
|
if (serverRevisionDate < lastSyncInstant &&
|
||||||
|
lastDatabaseSchemeChangeInstant < lastSyncInstant
|
||||||
|
) {
|
||||||
|
// We can skip the actual sync call if there is no new data or database
|
||||||
|
// scheme changes since the last sync.
|
||||||
|
vaultDiskSource.resyncVaultData(userId = userId)
|
||||||
|
settingsDiskSource.storeLastSyncTime(
|
||||||
|
userId = userId,
|
||||||
|
lastSyncTime = clock.instant(),
|
||||||
|
)
|
||||||
|
val itemsAvailable = vaultDiskSource
|
||||||
|
.getCiphers(userId)
|
||||||
|
.firstOrNull()
|
||||||
|
?.isNotEmpty() == true
|
||||||
|
return SyncVaultDataResult.Success(itemsAvailable = itemsAvailable)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onFailure = {
|
||||||
|
updateVaultStateFlowsToError(throwable = it)
|
||||||
|
return SyncVaultDataResult.Error(throwable = it)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
val lastDatabaseSchemeChangeInstant = databaseSchemeManager
|
return syncService
|
||||||
.lastDatabaseSchemeChangeInstant
|
|
||||||
?.toEpochMilli()
|
|
||||||
?: 0
|
|
||||||
|
|
||||||
syncService
|
|
||||||
.getAccountRevisionDateMillis()
|
|
||||||
.fold(
|
|
||||||
onSuccess = { serverRevisionDate ->
|
|
||||||
if (serverRevisionDate < lastSyncInstant &&
|
|
||||||
lastDatabaseSchemeChangeInstant < lastSyncInstant
|
|
||||||
) {
|
|
||||||
// We can skip the actual sync call if there is no new data or database
|
|
||||||
// scheme changes since the last sync.
|
|
||||||
vaultDiskSource.resyncVaultData(userId)
|
|
||||||
settingsDiskSource.storeLastSyncTime(
|
|
||||||
userId = userId,
|
|
||||||
lastSyncTime = clock.instant(),
|
|
||||||
)
|
|
||||||
val itemsAvailable = vaultDiskSource
|
|
||||||
.getCiphers(userId)
|
|
||||||
.firstOrNull()
|
|
||||||
?.isNotEmpty()
|
|
||||||
?: false
|
|
||||||
return SyncVaultDataResult.Success(itemsAvailable = itemsAvailable)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onFailure = {
|
|
||||||
updateVaultStateFlowsToError(it)
|
|
||||||
return SyncVaultDataResult.Error(it)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
syncService
|
|
||||||
.sync()
|
.sync()
|
||||||
.fold(
|
.fold(
|
||||||
onSuccess = { syncResponse ->
|
onSuccess = { syncResponse ->
|
||||||
val localSecurityStamp =
|
val localSecurityStamp = authDiskSource.userState?.activeAccount?.profile?.stamp
|
||||||
authDiskSource.userState?.activeAccount?.profile?.stamp
|
|
||||||
val serverSecurityStamp = syncResponse.profile.securityStamp
|
val serverSecurityStamp = syncResponse.profile.securityStamp
|
||||||
|
|
||||||
// Log the user out if the stamps do not match
|
// Log the user out if the stamps do not match
|
||||||
|
@ -1395,11 +1396,9 @@ class VaultRepositoryImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update user information with additional information from sync response
|
// Update user information with additional information from sync response
|
||||||
authDiskSource.userState = authDiskSource
|
authDiskSource.userState = authDiskSource.userState?.toUpdatedUserStateJson(
|
||||||
.userState
|
syncResponse = syncResponse,
|
||||||
?.toUpdatedUserStateJson(
|
)
|
||||||
syncResponse = syncResponse,
|
|
||||||
)
|
|
||||||
|
|
||||||
unlockVaultForOrganizationsIfNecessary(syncResponse = syncResponse)
|
unlockVaultForOrganizationsIfNecessary(syncResponse = syncResponse)
|
||||||
storeProfileData(syncResponse = syncResponse)
|
storeProfileData(syncResponse = syncResponse)
|
||||||
|
@ -1414,12 +1413,12 @@ class VaultRepositoryImpl(
|
||||||
lastSyncTime = clock.instant(),
|
lastSyncTime = clock.instant(),
|
||||||
)
|
)
|
||||||
vaultDiskSource.replaceVaultData(userId = userId, vault = syncResponse)
|
vaultDiskSource.replaceVaultData(userId = userId, vault = syncResponse)
|
||||||
val itemsAvailable = syncResponse.ciphers?.isNotEmpty() ?: false
|
val itemsAvailable = syncResponse.ciphers?.isNotEmpty() == true
|
||||||
return SyncVaultDataResult.Success(itemsAvailable = itemsAvailable)
|
SyncVaultDataResult.Success(itemsAvailable = itemsAvailable)
|
||||||
},
|
},
|
||||||
onFailure = { throwable ->
|
onFailure = { throwable ->
|
||||||
updateVaultStateFlowsToError(throwable)
|
updateVaultStateFlowsToError(throwable = throwable)
|
||||||
return SyncVaultDataResult.Error(throwable)
|
SyncVaultDataResult.Error(throwable = throwable)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@ class OtherViewModel @Inject constructor(
|
||||||
mutableStateFlow.update {
|
mutableStateFlow.update {
|
||||||
it.copy(dialogState = OtherState.DialogState.Loading(R.string.syncing.asText()))
|
it.copy(dialogState = OtherState.DialogState.Loading(R.string.syncing.asText()))
|
||||||
}
|
}
|
||||||
vaultRepo.sync()
|
vaultRepo.sync(forced = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleInternalAction(action: OtherAction.Internal) {
|
private fun handleInternalAction(action: OtherAction.Internal) {
|
||||||
|
|
|
@ -255,7 +255,7 @@ class SendViewModel @Inject constructor(
|
||||||
|
|
||||||
private fun handleRefreshClick() {
|
private fun handleRefreshClick() {
|
||||||
// No need to update the view state, the vault repo will emit a new state during this time.
|
// No need to update the view state, the vault repo will emit a new state during this time.
|
||||||
vaultRepo.sync()
|
vaultRepo.sync(forced = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleSearchClick() {
|
private fun handleSearchClick() {
|
||||||
|
@ -266,7 +266,7 @@ class SendViewModel @Inject constructor(
|
||||||
mutableStateFlow.update {
|
mutableStateFlow.update {
|
||||||
it.copy(dialogState = SendState.DialogState.Loading(R.string.syncing.asText()))
|
it.copy(dialogState = SendState.DialogState.Loading(R.string.syncing.asText()))
|
||||||
}
|
}
|
||||||
vaultRepo.sync()
|
vaultRepo.sync(forced = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleCopyClick(action: SendAction.CopyClick) {
|
private fun handleCopyClick(action: SendAction.CopyClick) {
|
||||||
|
@ -321,7 +321,7 @@ class SendViewModel @Inject constructor(
|
||||||
mutableStateFlow.update { it.copy(isRefreshing = true) }
|
mutableStateFlow.update { it.copy(isRefreshing = true) }
|
||||||
// The Pull-To-Refresh composable is already in the refreshing state.
|
// The Pull-To-Refresh composable is already in the refreshing state.
|
||||||
// We will reset that state when sendDataStateFlow emits later on.
|
// We will reset that state when sendDataStateFlow emits later on.
|
||||||
vaultRepo.sync()
|
vaultRepo.sync(forced = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -255,7 +255,7 @@ class VaultItemViewModel @Inject constructor(
|
||||||
|
|
||||||
private fun handleRefreshClick() {
|
private fun handleRefreshClick() {
|
||||||
// No need to update the view state, the vault repo will emit a new state during this time
|
// No need to update the view state, the vault repo will emit a new state during this time
|
||||||
vaultRepository.sync()
|
vaultRepository.sync(forced = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleCopyCustomHiddenFieldClick(
|
private fun handleCopyCustomHiddenFieldClick(
|
||||||
|
|
|
@ -300,14 +300,14 @@ class VaultItemListingViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleRefreshClick() {
|
private fun handleRefreshClick() {
|
||||||
vaultRepository.sync()
|
vaultRepository.sync(forced = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleRefreshPull() {
|
private fun handleRefreshPull() {
|
||||||
mutableStateFlow.update { it.copy(isRefreshing = true) }
|
mutableStateFlow.update { it.copy(isRefreshing = true) }
|
||||||
// The Pull-To-Refresh composable is already in the refreshing state.
|
// The Pull-To-Refresh composable is already in the refreshing state.
|
||||||
// We will reset that state when sendDataStateFlow emits later on.
|
// We will reset that state when sendDataStateFlow emits later on.
|
||||||
vaultRepository.sync()
|
vaultRepository.sync(forced = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleConfirmOverwriteExistingPasskeyClick(
|
private fun handleConfirmOverwriteExistingPasskeyClick(
|
||||||
|
@ -877,7 +877,7 @@ class VaultItemListingViewModel @Inject constructor(
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
vaultRepository.sync()
|
vaultRepository.sync(forced = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleSearchIconClick() {
|
private fun handleSearchIconClick() {
|
||||||
|
|
|
@ -299,7 +299,7 @@ class VaultViewModel @Inject constructor(
|
||||||
mutableStateFlow.update {
|
mutableStateFlow.update {
|
||||||
it.copy(dialog = VaultState.DialogState.Syncing)
|
it.copy(dialog = VaultState.DialogState.Syncing)
|
||||||
}
|
}
|
||||||
vaultRepository.sync()
|
vaultRepository.sync(forced = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleLockClick() {
|
private fun handleLockClick() {
|
||||||
|
@ -346,7 +346,7 @@ class VaultViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleTryAgainClick() {
|
private fun handleTryAgainClick() {
|
||||||
vaultRepository.sync()
|
vaultRepository.sync(forced = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleDialogDismiss() {
|
private fun handleDialogDismiss() {
|
||||||
|
@ -359,7 +359,7 @@ class VaultViewModel @Inject constructor(
|
||||||
mutableStateFlow.update { it.copy(isRefreshing = true) }
|
mutableStateFlow.update { it.copy(isRefreshing = true) }
|
||||||
// The Pull-To-Refresh composable is already in the refreshing state.
|
// The Pull-To-Refresh composable is already in the refreshing state.
|
||||||
// We will reset that state when sendDataStateFlow emits later on.
|
// We will reset that state when sendDataStateFlow emits later on.
|
||||||
vaultRepository.sync()
|
vaultRepository.sync(forced = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleOverflowOptionClick(action: VaultAction.OverflowOptionClick) {
|
private fun handleOverflowOptionClick(action: VaultAction.OverflowOptionClick) {
|
||||||
|
|
|
@ -120,14 +120,14 @@ class VerificationCodeViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleRefreshClick() {
|
private fun handleRefreshClick() {
|
||||||
vaultRepository.sync()
|
vaultRepository.sync(forced = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleRefreshPull() {
|
private fun handleRefreshPull() {
|
||||||
mutableStateFlow.update { it.copy(isRefreshing = true) }
|
mutableStateFlow.update { it.copy(isRefreshing = true) }
|
||||||
// The Pull-To-Refresh composable is already in the refreshing state.
|
// The Pull-To-Refresh composable is already in the refreshing state.
|
||||||
// We will reset that state when sendDataStateFlow emits later on.
|
// We will reset that state when sendDataStateFlow emits later on.
|
||||||
vaultRepository.sync()
|
vaultRepository.sync(forced = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleSearchIconClick() {
|
private fun handleSearchIconClick() {
|
||||||
|
@ -144,7 +144,7 @@ class VerificationCodeViewModel @Inject constructor(
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
vaultRepository.sync()
|
vaultRepository.sync(forced = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleInternalAction(action: VerificationCodeAction.Internal) {
|
private fun handleInternalAction(action: VerificationCodeAction.Internal) {
|
||||||
|
|
|
@ -816,6 +816,21 @@ class VaultRepositoryTest {
|
||||||
coVerify(exactly = 0) { syncService.sync() }
|
coVerify(exactly = 0) { syncService.sync() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `sync with forced should skip checks and call the syncService sync`() {
|
||||||
|
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||||
|
coEvery { syncService.sync() } returns Throwable("failure").asFailure()
|
||||||
|
|
||||||
|
vaultRepository.sync(forced = true)
|
||||||
|
|
||||||
|
coVerify(exactly = 0) {
|
||||||
|
syncService.getAccountRevisionDateMillis()
|
||||||
|
}
|
||||||
|
coVerify(exactly = 1) {
|
||||||
|
syncService.sync()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
@Suppress("MaxLineLength")
|
||||||
@Test
|
@Test
|
||||||
fun `sync with syncService Success should unlock the vault for orgs if necessary and update AuthDiskSource and VaultDiskSource`() =
|
fun `sync with syncService Success should unlock the vault for orgs if necessary and update AuthDiskSource and VaultDiskSource`() =
|
||||||
|
|
|
@ -100,7 +100,6 @@ class SearchViewModelTest : BaseViewModelTest() {
|
||||||
private val vaultRepository: VaultRepository = mockk {
|
private val vaultRepository: VaultRepository = mockk {
|
||||||
every { vaultFilterType } returns VaultFilterType.AllVaults
|
every { vaultFilterType } returns VaultFilterType.AllVaults
|
||||||
every { vaultDataStateFlow } returns mutableVaultDataStateFlow
|
every { vaultDataStateFlow } returns mutableVaultDataStateFlow
|
||||||
every { sync() } just runs
|
|
||||||
}
|
}
|
||||||
private val mutableUserStateFlow = MutableStateFlow<UserState?>(DEFAULT_USER_STATE)
|
private val mutableUserStateFlow = MutableStateFlow<UserState?>(DEFAULT_USER_STATE)
|
||||||
private val authRepository: AuthRepository = mockk {
|
private val authRepository: AuthRepository = mockk {
|
||||||
|
|
|
@ -149,7 +149,7 @@ class OtherViewModelTest : BaseViewModelTest() {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `on SyncNowButtonClick should sync repo`() = runTest {
|
fun `on SyncNowButtonClick should sync repo`() = runTest {
|
||||||
every { vaultRepository.sync() } just runs
|
every { vaultRepository.sync(forced = true) } just runs
|
||||||
val viewModel = createViewModel()
|
val viewModel = createViewModel()
|
||||||
viewModel.stateFlow.test {
|
viewModel.stateFlow.test {
|
||||||
assertEquals(DEFAULT_STATE, awaitItem())
|
assertEquals(DEFAULT_STATE, awaitItem())
|
||||||
|
@ -163,7 +163,7 @@ class OtherViewModelTest : BaseViewModelTest() {
|
||||||
awaitItem(),
|
awaitItem(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
verify { vaultRepository.sync() }
|
verify { vaultRepository.sync(forced = true) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -105,12 +105,12 @@ class SendViewModelTest : BaseViewModelTest() {
|
||||||
@Test
|
@Test
|
||||||
fun `RefreshClick should call sync`() {
|
fun `RefreshClick should call sync`() {
|
||||||
val viewModel = createViewModel()
|
val viewModel = createViewModel()
|
||||||
every { vaultRepo.sync() } just runs
|
every { vaultRepo.sync(forced = true) } just runs
|
||||||
|
|
||||||
viewModel.trySendAction(SendAction.RefreshClick)
|
viewModel.trySendAction(SendAction.RefreshClick)
|
||||||
|
|
||||||
verify {
|
verify {
|
||||||
vaultRepo.sync()
|
vaultRepo.sync(forced = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +223,7 @@ class SendViewModelTest : BaseViewModelTest() {
|
||||||
@Test
|
@Test
|
||||||
fun `SyncClick should call sync`() {
|
fun `SyncClick should call sync`() {
|
||||||
val viewModel = createViewModel()
|
val viewModel = createViewModel()
|
||||||
every { vaultRepo.sync() } just runs
|
every { vaultRepo.sync(forced = true) } just runs
|
||||||
|
|
||||||
viewModel.trySendAction(SendAction.SyncClick)
|
viewModel.trySendAction(SendAction.SyncClick)
|
||||||
|
|
||||||
|
@ -234,7 +234,7 @@ class SendViewModelTest : BaseViewModelTest() {
|
||||||
viewModel.stateFlow.value,
|
viewModel.stateFlow.value,
|
||||||
)
|
)
|
||||||
verify {
|
verify {
|
||||||
vaultRepo.sync()
|
vaultRepo.sync(forced = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,13 +419,13 @@ class SendViewModelTest : BaseViewModelTest() {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `RefreshPull should call vault repository sync`() {
|
fun `RefreshPull should call vault repository sync`() {
|
||||||
every { vaultRepo.sync() } just runs
|
every { vaultRepo.sync(forced = true) } just runs
|
||||||
val viewModel = createViewModel()
|
val viewModel = createViewModel()
|
||||||
|
|
||||||
viewModel.trySendAction(SendAction.RefreshPull)
|
viewModel.trySendAction(SendAction.RefreshPull)
|
||||||
|
|
||||||
verify(exactly = 1) {
|
verify(exactly = 1) {
|
||||||
vaultRepo.sync()
|
vaultRepo.sync(forced = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -950,13 +950,13 @@ class VaultItemViewModelTest : BaseViewModelTest() {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `on RefreshClick should sync`() = runTest {
|
fun `on RefreshClick should sync`() = runTest {
|
||||||
every { vaultRepo.sync() } just runs
|
every { vaultRepo.sync(forced = true) } just runs
|
||||||
val viewModel = createViewModel(state = DEFAULT_STATE)
|
val viewModel = createViewModel(state = DEFAULT_STATE)
|
||||||
|
|
||||||
viewModel.trySendAction(VaultItemAction.Common.RefreshClick)
|
viewModel.trySendAction(VaultItemAction.Common.RefreshClick)
|
||||||
|
|
||||||
verify(exactly = 1) {
|
verify(exactly = 1) {
|
||||||
vaultRepo.sync()
|
vaultRepo.sync(forced = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -135,7 +135,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||||
every { vaultFilterType } returns VaultFilterType.AllVaults
|
every { vaultFilterType } returns VaultFilterType.AllVaults
|
||||||
every { vaultDataStateFlow } returns mutableVaultDataStateFlow
|
every { vaultDataStateFlow } returns mutableVaultDataStateFlow
|
||||||
every { lockVault(any()) } just runs
|
every { lockVault(any()) } just runs
|
||||||
every { sync() } just runs
|
every { sync(forced = true) } just runs
|
||||||
coEvery {
|
coEvery {
|
||||||
getDecryptedFido2CredentialAutofillViews(any())
|
getDecryptedFido2CredentialAutofillViews(any())
|
||||||
} returns DecryptFido2CredentialAutofillViewResult.Error
|
} returns DecryptFido2CredentialAutofillViewResult.Error
|
||||||
|
@ -351,7 +351,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||||
viewModel.stateFlow.value,
|
viewModel.stateFlow.value,
|
||||||
)
|
)
|
||||||
verify(exactly = 1) {
|
verify(exactly = 1) {
|
||||||
vaultRepository.sync()
|
vaultRepository.sync(forced = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1029,7 +1029,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||||
fun `RefreshClick should sync`() = runTest {
|
fun `RefreshClick should sync`() = runTest {
|
||||||
val viewModel = createVaultItemListingViewModel()
|
val viewModel = createVaultItemListingViewModel()
|
||||||
viewModel.trySendAction(VaultItemListingsAction.RefreshClick)
|
viewModel.trySendAction(VaultItemListingsAction.RefreshClick)
|
||||||
verify { vaultRepository.sync() }
|
verify { vaultRepository.sync(forced = true) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -2127,7 +2127,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||||
viewModel.trySendAction(VaultItemListingsAction.RefreshPull)
|
viewModel.trySendAction(VaultItemListingsAction.RefreshPull)
|
||||||
|
|
||||||
verify(exactly = 1) {
|
verify(exactly = 1) {
|
||||||
vaultRepository.sync()
|
vaultRepository.sync(forced = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,7 @@ class VaultViewModelTest : BaseViewModelTest() {
|
||||||
mockk {
|
mockk {
|
||||||
every { vaultFilterType = any() } just runs
|
every { vaultFilterType = any() } just runs
|
||||||
every { vaultDataStateFlow } returns mutableVaultDataStateFlow
|
every { vaultDataStateFlow } returns mutableVaultDataStateFlow
|
||||||
every { sync() } just runs
|
every { sync(forced = any()) } just runs
|
||||||
every { syncIfNecessary() } just runs
|
every { syncIfNecessary() } just runs
|
||||||
every { lockVaultForCurrentUser() } just runs
|
every { lockVaultForCurrentUser() } just runs
|
||||||
every { lockVault(any()) } just runs
|
every { lockVault(any()) } just runs
|
||||||
|
@ -478,7 +478,7 @@ class VaultViewModelTest : BaseViewModelTest() {
|
||||||
viewModel.stateFlow.value,
|
viewModel.stateFlow.value,
|
||||||
)
|
)
|
||||||
verify {
|
verify {
|
||||||
vaultRepository.sync()
|
vaultRepository.sync(forced = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1323,7 +1323,7 @@ class VaultViewModelTest : BaseViewModelTest() {
|
||||||
|
|
||||||
viewModel.trySendAction(VaultAction.TryAgainClick)
|
viewModel.trySendAction(VaultAction.TryAgainClick)
|
||||||
|
|
||||||
verify { vaultRepository.sync() }
|
verify { vaultRepository.sync(forced = true) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1365,7 +1365,7 @@ class VaultViewModelTest : BaseViewModelTest() {
|
||||||
viewModel.trySendAction(VaultAction.RefreshPull)
|
viewModel.trySendAction(VaultAction.RefreshPull)
|
||||||
|
|
||||||
verify(exactly = 1) {
|
verify(exactly = 1) {
|
||||||
vaultRepository.sync()
|
vaultRepository.sync(forced = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1830,6 +1830,7 @@ class VaultViewModelTest : BaseViewModelTest() {
|
||||||
snackbarRelayManager.clearRelayBuffer(SnackbarRelay.MY_VAULT_RELAY)
|
snackbarRelayManager.clearRelayBuffer(SnackbarRelay.MY_VAULT_RELAY)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createViewModel(): VaultViewModel =
|
private fun createViewModel(): VaultViewModel =
|
||||||
VaultViewModel(
|
VaultViewModel(
|
||||||
authRepository = authRepository,
|
authRepository = authRepository,
|
||||||
|
|
|
@ -47,7 +47,7 @@ class VerificationCodeViewModelTest : BaseViewModelTest() {
|
||||||
private val vaultRepository: VaultRepository = mockk {
|
private val vaultRepository: VaultRepository = mockk {
|
||||||
every { vaultFilterType } returns VaultFilterType.AllVaults
|
every { vaultFilterType } returns VaultFilterType.AllVaults
|
||||||
every { getAuthCodesFlow() } returns mutableAuthCodeFlow.asStateFlow()
|
every { getAuthCodesFlow() } returns mutableAuthCodeFlow.asStateFlow()
|
||||||
every { sync() } just runs
|
every { sync(forced = true) } just runs
|
||||||
}
|
}
|
||||||
|
|
||||||
private val environmentRepository: EnvironmentRepository = mockk {
|
private val environmentRepository: EnvironmentRepository = mockk {
|
||||||
|
@ -140,7 +140,7 @@ class VerificationCodeViewModelTest : BaseViewModelTest() {
|
||||||
fun `RefreshClick should sync`() = runTest {
|
fun `RefreshClick should sync`() = runTest {
|
||||||
val viewModel = createViewModel()
|
val viewModel = createViewModel()
|
||||||
viewModel.trySendAction(VerificationCodeAction.RefreshClick)
|
viewModel.trySendAction(VerificationCodeAction.RefreshClick)
|
||||||
verify { vaultRepository.sync() }
|
verify { vaultRepository.sync(forced = true) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -167,7 +167,7 @@ class VerificationCodeViewModelTest : BaseViewModelTest() {
|
||||||
viewModel.stateFlow.value,
|
viewModel.stateFlow.value,
|
||||||
)
|
)
|
||||||
verify(exactly = 1) {
|
verify(exactly = 1) {
|
||||||
vaultRepository.sync()
|
vaultRepository.sync(forced = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,7 +456,7 @@ class VerificationCodeViewModelTest : BaseViewModelTest() {
|
||||||
viewModel.trySendAction(VerificationCodeAction.RefreshPull)
|
viewModel.trySendAction(VerificationCodeAction.RefreshPull)
|
||||||
|
|
||||||
verify(exactly = 1) {
|
verify(exactly = 1) {
|
||||||
vaultRepository.sync()
|
vaultRepository.sync(forced = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue