PM-19272 propagate errors from cipher results (#4876)

This commit is contained in:
Dave Severns authored and GitHub committed 2025-03-17 15:18:05 +00:00
1 parent dfcdc72499
commit 6c784d28eb
16 files changed
+132 -79

No files matched your search

@@ -50,7 +50,8 @@ class CipherManagerImpl(
private val activeUserId: String? get() = authDiskSource.userState?.activeUserId
override suspend fun createCipher(cipherView: CipherView): CreateCipherResult {
val userId = activeUserId ?: return CreateCipherResult.Error
val userId = activeUserId
?: return CreateCipherResult.Error(error = NoActiveUserException())
return vaultSdkSource
.encryptCipher(
userId = userId,
@@ -59,7 +60,7 @@ class CipherManagerImpl(
.flatMap { ciphersService.createCipher(body = it.toEncryptedNetworkCipher()) }
.onSuccess { vaultDiskSource.saveCipher(userId = userId, cipher = it) }
.fold(
onFailure = { CreateCipherResult.Error },
onFailure = { CreateCipherResult.Error(error = it) },
onSuccess = {
reviewPromptManager.registerAddCipherAction()
CreateCipherResult.Success
@@ -71,7 +72,8 @@ class CipherManagerImpl(
cipherView: CipherView,
collectionIds: List<String>,
): CreateCipherResult {
val userId = activeUserId ?: return CreateCipherResult.Error
val userId = activeUserId
?: return CreateCipherResult.Error(error = NoActiveUserException())
return vaultSdkSource
.encryptCipher(
userId = userId,
@@ -92,7 +94,7 @@ class CipherManagerImpl(
)
}
.fold(
onFailure = { CreateCipherResult.Error },
onFailure = { CreateCipherResult.Error(error = it) },
onSuccess = {
reviewPromptManager.registerAddCipherAction()
CreateCipherResult.Success
@@ -101,13 +103,14 @@ class CipherManagerImpl(
}
override suspend fun hardDeleteCipher(cipherId: String): DeleteCipherResult {
val userId = activeUserId ?: return DeleteCipherResult.Error
val userId = activeUserId
?: return DeleteCipherResult.Error(error = NoActiveUserException())
return ciphersService
.hardDeleteCipher(cipherId = cipherId)
.onSuccess { vaultDiskSource.deleteCipher(userId = userId, cipherId = cipherId) }
.fold(
onSuccess = { DeleteCipherResult.Success },
onFailure = { DeleteCipherResult.Error },
onFailure = { DeleteCipherResult.Error(error = it) },
)
}
@@ -115,7 +118,8 @@ class CipherManagerImpl(
cipherId: String,
cipherView: CipherView,
): DeleteCipherResult {
val userId = activeUserId ?: return DeleteCipherResult.Error
val userId = activeUserId
?: return DeleteCipherResult.Error(error = NoActiveUserException())
return cipherView
.encryptCipherAndCheckForMigration(userId = userId, cipherId = cipherId)
.flatMap { cipher ->
@@ -137,7 +141,7 @@ class CipherManagerImpl(
}
.fold(
onSuccess = { DeleteCipherResult.Success },
onFailure = { DeleteCipherResult.Error },
onFailure = { DeleteCipherResult.Error(error = it) },
)
}
@@ -188,7 +192,8 @@ class CipherManagerImpl(
cipherId: String,
cipherView: CipherView,
): RestoreCipherResult {
val userId = activeUserId ?: return RestoreCipherResult.Error
val userId = activeUserId
?: return RestoreCipherResult.Error(error = NoActiveUserException())
return ciphersService
.restoreCipher(cipherId = cipherId)
.onSuccess {
@@ -199,7 +204,7 @@ class CipherManagerImpl(
}
.fold(
onSuccess = { RestoreCipherResult.Success },
onFailure = { RestoreCipherResult.Error },
onFailure = { RestoreCipherResult.Error(error = it) },
)
}
@@ -207,7 +212,8 @@ class CipherManagerImpl(
cipherId: String,
cipherView: CipherView,
): UpdateCipherResult {
val userId = activeUserId ?: return UpdateCipherResult.Error(errorMessage = null)
val userId = activeUserId
?: return UpdateCipherResult.Error(errorMessage = null, error = NoActiveUserException())
return vaultSdkSource
.encryptCipher(
userId = userId,
@@ -222,7 +228,7 @@ class CipherManagerImpl(
.map { response ->
when (response) {
is UpdateCipherResponseJson.Invalid -> {
UpdateCipherResult.Error(errorMessage = response.message)
UpdateCipherResult.Error(errorMessage = response.message, error = null)
}
is UpdateCipherResponseJson.Success -> {
@@ -235,7 +241,7 @@ class CipherManagerImpl(
}
}
.fold(
onFailure = { UpdateCipherResult.Error(errorMessage = null) },
onFailure = { UpdateCipherResult.Error(errorMessage = null, error = it) },
onSuccess = { it },
)
}
@@ -246,7 +252,7 @@ class CipherManagerImpl(
cipherView: CipherView,
collectionIds: List<String>,
): ShareCipherResult {
val userId = activeUserId ?: return ShareCipherResult.Error
val userId = activeUserId ?: return ShareCipherResult.Error(error = NoActiveUserException())
return migrateAttachments(userId = userId, cipherView = cipherView)
.flatMap {
vaultSdkSource.moveToOrganization(
@@ -272,7 +278,7 @@ class CipherManagerImpl(
)
}
.fold(
onFailure = { ShareCipherResult.Error },
onFailure = { ShareCipherResult.Error(error = it) },
onSuccess = { ShareCipherResult.Success },
)
}
@@ -282,7 +288,7 @@ class CipherManagerImpl(
cipherView: CipherView,
collectionIds: List<String>,
): ShareCipherResult {
val userId = activeUserId ?: return ShareCipherResult.Error
val userId = activeUserId ?: return ShareCipherResult.Error(error = NoActiveUserException())
return ciphersService
.updateCipherCollections(
cipherId = cipherId,
@@ -302,7 +308,7 @@ class CipherManagerImpl(
}
.fold(
onSuccess = { ShareCipherResult.Success },
onFailure = { ShareCipherResult.Error },
onFailure = { ShareCipherResult.Error(error = it) },
)
}
@@ -13,5 +13,5 @@ sealed class CreateCipherResult {
/**
* Generic error while creating cipher.
*/
data object Error : CreateCipherResult()
data class Error(val error: Throwable) : CreateCipherResult()
}
@@ -13,5 +13,5 @@ sealed class DeleteCipherResult {
/**
* Generic error while deleting a cipher.
*/
data object Error : DeleteCipherResult()
data class Error(val error: Throwable) : DeleteCipherResult()
}
@@ -13,5 +13,5 @@ sealed class RestoreCipherResult {
/**
* Generic error while restoring a cipher.
*/
data object Error : RestoreCipherResult()
data class Error(val error: Throwable) : RestoreCipherResult()
}
@@ -12,5 +12,5 @@ sealed class ShareCipherResult {
/**
* Generic error while sharing cipher.
*/
data object Error : ShareCipherResult()
data class Error(val error: Throwable) : ShareCipherResult()
}
@@ -14,5 +14,5 @@ sealed class UpdateCipherResult {
* Generic error while updating cipher. The optional [errorMessage] may be displayed directly in
* the UI when present.
*/
data class Error(val errorMessage: String?) : UpdateCipherResult()
data class Error(val errorMessage: String?, val error: Throwable?) : UpdateCipherResult()
}
@@ -546,6 +546,7 @@ class SearchViewModel @Inject constructor(
title = null,
message = result.errorMessage?.asText()
?: R.string.generic_error_message.asText(),
throwable = result.error,
),
)
}
@@ -1554,9 +1554,14 @@ class VaultAddEditViewModel @Inject constructor(
) {
clearDialogState()
when (action.createCipherResult) {
when (val result = action.createCipherResult) {
is CreateCipherResult.Error -> {
showGenericErrorDialog()
showDialog(
dialogState = VaultAddEditState.DialogState.Generic(
message = R.string.generic_error_message.asText(),
error = result.error,
),
)
}
is CreateCipherResult.Success -> {
@@ -1581,11 +1586,15 @@ class VaultAddEditViewModel @Inject constructor(
clearDialogState()
when (val result = action.updateCipherResult) {
is UpdateCipherResult.Error -> {
showGenericErrorDialog(
message = result
.errorMessage
?.asText()
?: R.string.generic_error_message.asText(),
showDialog(
dialogState = VaultAddEditState.DialogState.Generic(
title = R.string.an_error_has_occurred.asText(),
message = result
.errorMessage
?.asText()
?: R.string.generic_error_message.asText(),
error = result.error,
),
)
}
@@ -1602,11 +1611,12 @@ class VaultAddEditViewModel @Inject constructor(
}
private fun handleDeleteCipherReceive(action: VaultAddEditAction.Internal.DeleteCipherReceive) {
when (action.result) {
DeleteCipherResult.Error -> {
when (val result = action.result) {
is DeleteCipherResult.Error -> {
showDialog(
dialogState = VaultAddEditState.DialogState.Generic(
message = R.string.generic_error_message.asText(),
error = result.error,
),
)
}
@@ -1245,11 +1245,12 @@ class VaultItemViewModel @Inject constructor(
}
private fun handleDeleteCipherReceive(action: VaultItemAction.Internal.DeleteCipherReceive) {
when (action.result) {
DeleteCipherResult.Error -> {
when (val result = action.result) {
is DeleteCipherResult.Error -> {
updateDialogState(
VaultItemState.DialogState.Generic(
message = R.string.generic_error_message.asText(),
error = result.error,
),
)
}
@@ -1271,11 +1272,12 @@ class VaultItemViewModel @Inject constructor(
}
private fun handleRestoreCipherReceive(action: VaultItemAction.Internal.RestoreCipherReceive) {
when (action.result) {
RestoreCipherResult.Error -> {
when (val result = action.result) {
is RestoreCipherResult.Error -> {
updateDialogState(
VaultItemState.DialogState.Generic(
message = R.string.generic_error_message.asText(),
error = result.error,
),
)
}
@@ -85,6 +85,7 @@ private fun VaultMoveToOrganizationScaffold(
title = stringResource(id = R.string.an_error_has_occurred),
message = dialog.message(),
onDismissRequest = dismissClick,
throwable = dialog.throwable,
)
}
@@ -151,12 +151,13 @@ class VaultMoveToOrganizationViewModel @Inject constructor(
action: VaultMoveToOrganizationAction.Internal.ShareCipherResultReceive,
) {
mutableStateFlow.update { it.copy(dialogState = null) }
when (action.shareCipherResult) {
when (val result = action.shareCipherResult) {
is ShareCipherResult.Error -> {
mutableStateFlow.update {
it.copy(
dialogState = VaultMoveToOrganizationState.DialogState.Error(
message = R.string.generic_error_message.asText(),
throwable = result.error,
),
)
}
@@ -358,6 +359,7 @@ data class VaultMoveToOrganizationState(
@Parcelize
data class Error(
val message: Text,
val throwable: Throwable? = null,
) : DialogState()
/**
@@ -115,7 +115,7 @@ class CipherManagerTest {
val result = cipherManager.createCipher(cipherView = mockk())
assertEquals(CreateCipherResult.Error, result)
assertEquals(CreateCipherResult.Error(error = NoActiveUserException()), result)
}
@Test
@@ -124,16 +124,17 @@ class CipherManagerTest {
fakeAuthDiskSource.userState = MOCK_USER_STATE
val userId = "mockId-1"
val mockCipherView = createMockCipherView(number = 1)
val error = IllegalStateException()
coEvery {
vaultSdkSource.encryptCipher(
userId = userId,
cipherView = mockCipherView,
)
} returns IllegalStateException().asFailure()
} returns error.asFailure()
val result = cipherManager.createCipher(cipherView = mockCipherView)
assertEquals(CreateCipherResult.Error, result)
assertEquals(CreateCipherResult.Error(error = error), result)
}
@Test
@@ -143,6 +144,7 @@ class CipherManagerTest {
fakeAuthDiskSource.userState = MOCK_USER_STATE
val userId = "mockId-1"
val mockCipherView = createMockCipherView(number = 1)
val error = IllegalStateException()
coEvery {
vaultSdkSource.encryptCipher(
userId = userId,
@@ -153,11 +155,11 @@ class CipherManagerTest {
ciphersService.createCipher(
body = createMockCipherJsonRequest(number = 1, hasNullUri = true),
)
} returns IllegalStateException().asFailure()
} returns error.asFailure()
val result = cipherManager.createCipher(cipherView = mockCipherView)
assertEquals(CreateCipherResult.Error, result)
assertEquals(CreateCipherResult.Error(error = error), result)
}
@Test
@@ -197,7 +199,7 @@ class CipherManagerTest {
collectionIds = mockk(),
)
assertEquals(CreateCipherResult.Error, result)
assertEquals(CreateCipherResult.Error(error = NoActiveUserException()), result)
}
@Test
@@ -207,19 +209,20 @@ class CipherManagerTest {
fakeAuthDiskSource.userState = MOCK_USER_STATE
val userId = "mockId-1"
val mockCipherView = createMockCipherView(number = 1)
val error = IllegalStateException()
coEvery {
vaultSdkSource.encryptCipher(
userId = userId,
cipherView = mockCipherView,
)
} returns IllegalStateException().asFailure()
} returns error.asFailure()
val result = cipherManager.createCipherInOrganization(
cipherView = mockCipherView,
collectionIds = mockk(),
)
assertEquals(CreateCipherResult.Error, result)
assertEquals(CreateCipherResult.Error(error = error), result)
}
@Test
@@ -229,6 +232,7 @@ class CipherManagerTest {
fakeAuthDiskSource.userState = MOCK_USER_STATE
val userId = "mockId-1"
val mockCipherView = createMockCipherView(number = 1)
val error = IllegalStateException()
coEvery {
vaultSdkSource.encryptCipher(
userId = userId,
@@ -242,14 +246,14 @@ class CipherManagerTest {
collectionIds = listOf("mockId-1"),
),
)
} returns IllegalStateException().asFailure()
} returns error.asFailure()
val result = cipherManager.createCipherInOrganization(
cipherView = mockCipherView,
collectionIds = listOf("mockId-1"),
)
assertEquals(CreateCipherResult.Error, result)
assertEquals(CreateCipherResult.Error(error = error), result)
}
@Test
@@ -299,7 +303,10 @@ class CipherManagerTest {
cipherView = mockk(),
)
assertEquals(UpdateCipherResult.Error(errorMessage = null), result)
assertEquals(
UpdateCipherResult.Error(errorMessage = null, error = NoActiveUserException()),
result,
)
}
@Test
@@ -309,19 +316,20 @@ class CipherManagerTest {
val userId = "mockId-1"
val cipherId = "cipherId1234"
val mockCipherView = createMockCipherView(number = 1)
val error = IllegalStateException()
coEvery {
vaultSdkSource.encryptCipher(
userId = userId,
cipherView = mockCipherView,
)
} returns IllegalStateException().asFailure()
} returns error.asFailure()
val result = cipherManager.updateCipher(
cipherId = cipherId,
cipherView = mockCipherView,
)
assertEquals(UpdateCipherResult.Error(errorMessage = null), result)
assertEquals(UpdateCipherResult.Error(errorMessage = null, error = error), result)
}
@Test
@@ -332,6 +340,7 @@ class CipherManagerTest {
val userId = "mockId-1"
val cipherId = "cipherId1234"
val mockCipherView = createMockCipherView(number = 1)
val error = IllegalStateException()
coEvery {
vaultSdkSource.encryptCipher(
userId = userId,
@@ -343,14 +352,14 @@ class CipherManagerTest {
cipherId = cipherId,
body = createMockCipherJsonRequest(number = 1, hasNullUri = true),
)
} returns IllegalStateException().asFailure()
} returns error.asFailure()
val result = cipherManager.updateCipher(
cipherId = cipherId,
cipherView = mockCipherView,
)
assertEquals(UpdateCipherResult.Error(errorMessage = null), result)
assertEquals(UpdateCipherResult.Error(errorMessage = null, error = error), result)
}
@Test
@@ -385,7 +394,10 @@ class CipherManagerTest {
)
assertEquals(
UpdateCipherResult.Error(errorMessage = "You do not have permission to edit this."),
UpdateCipherResult.Error(
errorMessage = "You do not have permission to edit this.",
error = null,
),
result,
)
}
@@ -436,7 +448,7 @@ class CipherManagerTest {
cipherId = "cipherId",
)
assertEquals(DeleteCipherResult.Error, result)
assertEquals(DeleteCipherResult.Error(error = NoActiveUserException()), result)
}
@Suppress("MaxLineLength")
@@ -445,13 +457,14 @@ class CipherManagerTest {
runTest {
fakeAuthDiskSource.userState = MOCK_USER_STATE
val cipherId = "mockId-1"
val error = Throwable("Fail")
coEvery {
ciphersService.hardDeleteCipher(cipherId = cipherId)
} returns Throwable("Fail").asFailure()
} returns error.asFailure()
val result = cipherManager.hardDeleteCipher(cipherId)
assertEquals(DeleteCipherResult.Error, result)
assertEquals(DeleteCipherResult.Error(error = error), result)
}
@Suppress("MaxLineLength")
@@ -478,7 +491,7 @@ class CipherManagerTest {
cipherView = mockk(),
)
assertEquals(DeleteCipherResult.Error, result)
assertEquals(DeleteCipherResult.Error(error = NoActiveUserException()), result)
}
@Suppress("MaxLineLength")
@@ -490,19 +503,20 @@ class CipherManagerTest {
val cipherId = "mockId-1"
val cipherView = createMockCipherView(number = 1)
val cipher = createMockSdkCipher(number = 1)
val error = Throwable("Fail")
coEvery {
vaultSdkSource.encryptCipher(userId = userId, cipherView = cipherView)
} returns cipher.asSuccess()
coEvery {
ciphersService.softDeleteCipher(cipherId = cipherId)
} returns Throwable("Fail").asFailure()
} returns error.asFailure()
val result = cipherManager.softDeleteCipher(
cipherId = cipherId,
cipherView = cipherView,
)
assertEquals(DeleteCipherResult.Error, result)
assertEquals(DeleteCipherResult.Error(error = error), result)
}
@Suppress("MaxLineLength")
@@ -700,7 +714,7 @@ class CipherManagerTest {
cipherView = createMockCipherView(number = 1),
)
assertEquals(RestoreCipherResult.Error, result)
assertEquals(RestoreCipherResult.Error(error = NoActiveUserException()), result)
}
@Suppress("MaxLineLength")
@@ -710,16 +724,17 @@ class CipherManagerTest {
fakeAuthDiskSource.userState = MOCK_USER_STATE
val cipherId = "mockId-1"
val cipherView = createMockCipherView(number = 1)
val error = Throwable("Fail")
coEvery {
ciphersService.restoreCipher(cipherId = cipherId)
} returns Throwable("Fail").asFailure()
} returns error.asFailure()
val result = cipherManager.restoreCipher(
cipherId = cipherId,
cipherView = cipherView,
)
assertEquals(RestoreCipherResult.Error, result)
assertEquals(RestoreCipherResult.Error(error = error), result)
}
@Suppress("MaxLineLength")
@@ -758,7 +773,7 @@ class CipherManagerTest {
collectionIds = emptyList(),
)
assertEquals(ShareCipherResult.Error, result)
assertEquals(ShareCipherResult.Error(error = NoActiveUserException()), result)
}
@Test
@@ -968,6 +983,7 @@ class CipherManagerTest {
coEvery {
vaultSdkSource.encryptCipher(userId = userId, cipherView = mockCipherView)
} returns createMockSdkCipher(number = 1, clock = clock).asSuccess()
val error = Throwable("Fail")
coEvery {
ciphersService.shareCipher(
cipherId = "mockId-1",
@@ -976,7 +992,7 @@ class CipherManagerTest {
collectionIds = listOf("mockId-1"),
),
)
} returns Throwable("Fail").asFailure()
} returns error.asFailure()
coEvery { vaultDiskSource.saveCipher(userId, createMockCipher(number = 1)) } just runs
val result = cipherManager.shareCipher(
@@ -986,7 +1002,7 @@ class CipherManagerTest {
collectionIds = listOf("mockId-1"),
)
assertEquals(ShareCipherResult.Error, result)
assertEquals(ShareCipherResult.Error(error = error), result)
}
@Test
@@ -996,13 +1012,14 @@ class CipherManagerTest {
fakeAuthDiskSource.userState = MOCK_USER_STATE
val userId = "mockId-1"
val organizationId = "organizationId"
val error = Throwable("Fail")
coEvery {
vaultSdkSource.moveToOrganization(
userId = userId,
organizationId = organizationId,
cipherView = createMockCipherView(number = 1),
)
} returns Throwable("Fail").asFailure()
} returns error.asFailure()
coEvery {
ciphersService.shareCipher(
cipherId = "mockId-1",
@@ -1021,7 +1038,7 @@ class CipherManagerTest {
collectionIds = listOf("mockId-1"),
)
assertEquals(ShareCipherResult.Error, result)
assertEquals(ShareCipherResult.Error(error = error), result)
}
@Test
@@ -1035,7 +1052,7 @@ class CipherManagerTest {
collectionIds = emptyList(),
)
assertEquals(ShareCipherResult.Error, result)
assertEquals(ShareCipherResult.Error(error = NoActiveUserException()), result)
}
@Test
@@ -1083,6 +1100,7 @@ class CipherManagerTest {
cipherView = createMockCipherView(number = 1),
)
} returns createMockSdkCipher(number = 1, clock = clock).asSuccess()
val error = Throwable("Fail")
coEvery {
ciphersService.updateCipherCollections(
cipherId = "mockId-1",
@@ -1090,7 +1108,7 @@ class CipherManagerTest {
collectionIds = listOf("mockId-1"),
),
)
} returns Throwable("Fail").asFailure()
} returns error.asFailure()
coEvery { vaultDiskSource.saveCipher(userId, any()) } just runs
val result = cipherManager.updateCipherCollections(
@@ -1101,7 +1119,7 @@ class CipherManagerTest {
collectionIds = listOf("mockId-1"),
)
assertEquals(ShareCipherResult.Error, result)
assertEquals(ShareCipherResult.Error(error = error), result)
}
@Test
@@ -1110,12 +1128,13 @@ class CipherManagerTest {
runTest {
fakeAuthDiskSource.userState = MOCK_USER_STATE
val userId = "mockId-1"
val error = Throwable("Fail")
coEvery {
vaultSdkSource.encryptCipher(
userId = userId,
cipherView = createMockCipherView(number = 1),
)
} returns Throwable("Fail").asFailure()
} returns error.asFailure()
coEvery {
ciphersService.updateCipherCollections(
cipherId = "mockId-1",
@@ -1134,7 +1153,7 @@ class CipherManagerTest {
collectionIds = listOf("mockId-1"),
)
assertEquals(ShareCipherResult.Error, result)
assertEquals(ShareCipherResult.Error(error = error), result)
}
@Test
@@ -275,6 +275,7 @@ class SearchViewModelTest : BaseViewModelTest() {
val cipherView = setupForAutofill()
val cipherId = CIPHER_ID
val errorMessage = "Server error"
val error = Throwable("Oof")
val updatedCipherView = cipherView.copy(
login = createMockLoginView(number = 1, clock = clock).copy(
uris = listOf(createMockUriView(number = 1)) +
@@ -291,7 +292,7 @@ class SearchViewModelTest : BaseViewModelTest() {
cipherId = cipherId,
cipherView = updatedCipherView,
)
} returns UpdateCipherResult.Error(errorMessage)
} returns UpdateCipherResult.Error(errorMessage = errorMessage, error = error)
viewModel.stateFlow.test {
assertEquals(INITIAL_STATE_FOR_AUTOFILL, awaitItem())
@@ -314,6 +315,7 @@ class SearchViewModelTest : BaseViewModelTest() {
dialogState = SearchState.DialogState.Error(
title = null,
message = errorMessage.asText(),
throwable = error,
),
),
awaitItem(),
@@ -592,12 +592,13 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
),
)
val error = Throwable("Oh dang.")
coEvery {
vaultRepository.softDeleteCipher(
cipherId = "mockId-1",
cipherView = cipherView,
)
} returns DeleteCipherResult.Error
} returns DeleteCipherResult.Error(error = error)
viewModel.trySendAction(VaultAddEditAction.Common.ConfirmDeleteClick)
@@ -606,6 +607,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
vaultAddEditType = vaultAddEditType,
dialogState = VaultAddEditState.DialogState.Generic(
message = R.string.generic_error_message.asText(),
error = error,
),
commonContentViewState = createCommonContentViewState(
name = "mockName-1",
@@ -1638,7 +1640,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
coEvery {
vaultRepository.createCipherInOrganization(any(), any())
} returns CreateCipherResult.Error
} returns CreateCipherResult.Error(error = Throwable("Oh dang"))
viewModel.trySendAction(VaultAddEditAction.Common.SaveClick)
assertEquals(
@@ -1772,9 +1774,10 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
canAssignToCollections = true,
)
} returns stateWithName.viewState
val error = Throwable("Oh dang.")
coEvery {
vaultRepository.updateCipher(DEFAULT_EDIT_ITEM_ID, any())
} returns UpdateCipherResult.Error(errorMessage = null)
} returns UpdateCipherResult.Error(errorMessage = null, error = error)
mutableVaultDataFlow.value = DataState.Loaded(
data = createVaultData(cipherView = cipherView),
)
@@ -1794,6 +1797,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
dialog = VaultAddEditState.DialogState.Generic(
title = R.string.an_error_has_occurred.asText(),
message = R.string.generic_error_message.asText(),
error = error,
),
),
viewModel.stateFlow.value,
@@ -1839,7 +1843,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
} returns stateWithName.viewState
coEvery {
vaultRepository.updateCipher(DEFAULT_EDIT_ITEM_ID, any())
} returns UpdateCipherResult.Error(errorMessage = errorMessage)
} returns UpdateCipherResult.Error(errorMessage = errorMessage, error = null)
mutableVaultDataFlow.value = DataState.Loaded(
createVaultData(cipherView = cipherView),
)
@@ -400,12 +400,13 @@ class VaultItemViewModelTest : BaseViewModelTest() {
mutableFoldersStateFlow.value = DataState.Loaded(emptyList())
val viewModel = createViewModel(state = DEFAULT_STATE)
val error = Throwable("Oh dang.")
coEvery {
vaultRepo.softDeleteCipher(
cipherId = VAULT_ITEM_ID,
cipherView = createMockCipherView(number = 1),
)
} returns DeleteCipherResult.Error
} returns DeleteCipherResult.Error(error = error)
viewModel.trySendAction(VaultItemAction.Common.ConfirmDeleteClick)
@@ -414,6 +415,7 @@ class VaultItemViewModelTest : BaseViewModelTest() {
viewState = loginViewState,
dialog = VaultItemState.DialogState.Generic(
message = R.string.generic_error_message.asText(),
error = error,
),
),
viewModel.stateFlow.value,
@@ -624,12 +626,13 @@ class VaultItemViewModelTest : BaseViewModelTest() {
mutableFoldersStateFlow.value = DataState.Loaded(emptyList())
val viewModel = createViewModel(state = DEFAULT_STATE)
val error = Throwable("Fail")
coEvery {
vaultRepo.restoreCipher(
cipherId = VAULT_ITEM_ID,
cipherView = createMockCipherView(number = 1),
)
} returns RestoreCipherResult.Error
} returns RestoreCipherResult.Error(error = error)
viewModel.trySendAction(VaultItemAction.Common.ConfirmRestoreClick)
@@ -638,6 +641,7 @@ class VaultItemViewModelTest : BaseViewModelTest() {
viewState = DEFAULT_VIEW_STATE,
dialog = VaultItemState.DialogState.Generic(
message = R.string.generic_error_message.asText(),
error = error,
),
),
viewModel.stateFlow.value,
@@ -303,6 +303,7 @@ class VaultMoveToOrganizationViewModelTest : BaseViewModelTest() {
val viewModel = createViewModel()
mutableCollectionFlow.tryEmit(value = DataState.Loaded(DEFAULT_COLLECTIONS))
mutableVaultItemFlow.tryEmit(value = DataState.Loaded(createMockCipherView(number = 1)))
val error = Throwable("Fail")
coEvery {
vaultRepository.shareCipher(
cipherId = "mockCipherId",
@@ -310,7 +311,7 @@ class VaultMoveToOrganizationViewModelTest : BaseViewModelTest() {
cipherView = createMockCipherView(number = 1),
collectionIds = listOf("mockId-1"),
)
} returns ShareCipherResult.Error
} returns ShareCipherResult.Error(error = error)
viewModel.stateFlow.test {
assertEquals(
initialState.copy(
@@ -340,6 +341,7 @@ class VaultMoveToOrganizationViewModelTest : BaseViewModelTest() {
initialState.copy(
dialogState = VaultMoveToOrganizationState.DialogState.Error(
message = R.string.generic_error_message.asText(),
throwable = error,
),
viewState = VaultMoveToOrganizationState.ViewState.Content(
organizations = createMockOrganizationList(),