BIT-1411, BIT-1414: Add delete send confirmation dialog (#680)

This commit is contained in:
David Perez 2024-01-19 09:55:51 -06:00 committed by Álison Fernandes
parent a706db2b28
commit 2fa7851b42
4 changed files with 93 additions and 4 deletions

View file

@ -30,6 +30,7 @@ import com.x8bit.bitwarden.ui.platform.components.BitwardenOverflowActionItem
import com.x8bit.bitwarden.ui.platform.components.BitwardenScaffold
import com.x8bit.bitwarden.ui.platform.components.BitwardenSearchActionItem
import com.x8bit.bitwarden.ui.platform.components.BitwardenTopAppBar
import com.x8bit.bitwarden.ui.platform.components.BitwardenTwoButtonDialog
import com.x8bit.bitwarden.ui.platform.components.LoadingDialogState
import com.x8bit.bitwarden.ui.platform.components.OverflowMenuItemData
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
@ -92,6 +93,9 @@ fun VaultItemListingScreen(
VaultItemListingDialogs(
dialogState = state.dialogState,
onDeleteSendConfirm = remember(viewModel) {
{ viewModel.trySendAction(VaultItemListingsAction.DeleteSendConfirmClick(it)) }
},
onDismissRequest = remember(viewModel) {
{ viewModel.trySendAction(VaultItemListingsAction.DismissDialogClick) }
},
@ -108,9 +112,20 @@ fun VaultItemListingScreen(
@Composable
private fun VaultItemListingDialogs(
dialogState: VaultItemListingState.DialogState?,
onDeleteSendConfirm: (sendId: String) -> Unit,
onDismissRequest: () -> Unit,
) {
when (dialogState) {
is VaultItemListingState.DialogState.DeleteSendConfirmation -> BitwardenTwoButtonDialog(
title = stringResource(id = R.string.delete),
message = stringResource(id = R.string.are_you_sure_delete_send),
confirmButtonText = stringResource(id = R.string.yes),
dismissButtonText = stringResource(id = R.string.cancel),
onConfirmClick = { onDeleteSendConfirm(dialogState.sendId) },
onDismissClick = onDismissRequest,
onDismissRequest = onDismissRequest,
)
is VaultItemListingState.DialogState.Error -> BitwardenBasicDialog(
visibilityState = BasicDialogState.Shown(
title = dialogState.title,

View file

@ -86,6 +86,10 @@ class VaultItemListingViewModel @Inject constructor(
is VaultItemListingsAction.RefreshClick -> handleRefreshClick()
is VaultItemListingsAction.CopySendUrlClick -> handleCopySendUrlClick(action)
is VaultItemListingsAction.DeleteSendClick -> handleDeleteSendClick(action)
is VaultItemListingsAction.DeleteSendConfirmClick -> {
handleDeleteSendConfirmClick(action)
}
is VaultItemListingsAction.ShareSendUrlClick -> handleShareSendUrlClick(action)
is VaultItemListingsAction.RemoveSendPasswordClick -> {
handleRemoveSendPasswordClick(action)
@ -105,6 +109,18 @@ class VaultItemListingViewModel @Inject constructor(
}
private fun handleDeleteSendClick(action: VaultItemListingsAction.DeleteSendClick) {
mutableStateFlow.update {
it.copy(
dialogState = VaultItemListingState.DialogState.DeleteSendConfirmation(
sendId = action.sendId,
),
)
}
}
private fun handleDeleteSendConfirmClick(
action: VaultItemListingsAction.DeleteSendConfirmClick,
) {
mutableStateFlow.update {
it.copy(
dialogState = VaultItemListingState.DialogState.Loading(
@ -395,6 +411,14 @@ data class VaultItemListingState(
*/
sealed class DialogState : Parcelable {
/**
* Represents a dismissible dialog with the given error [message].
*/
@Parcelize
data class DeleteSendConfirmation(
val sendId: String,
) : DialogState()
/**
* Represents a dismissible dialog with the given error [message].
*/
@ -710,6 +734,11 @@ sealed class VaultItemListingsAction {
*/
data class DeleteSendClick(val sendId: String) : VaultItemListingsAction()
/**
* Click on the delete send confirmation button.
*/
data class DeleteSendConfirmClick(val sendId: String) : VaultItemListingsAction()
/**
* Models actions that the [VaultItemListingViewModel] itself might send.
*/

View file

@ -605,6 +605,36 @@ class VaultItemListingScreenTest : BaseComposeTest() {
}
}
@Suppress("MaxLineLength")
@Test
fun `delete send confirmation dialog should be displayed according to state and emits DeleteSendConfirmClick on confirmation`() {
val sendId = "sendId"
val message = "Are you sure you want to delete this Send?"
composeTestRule.onNode(isDialog()).assertDoesNotExist()
composeTestRule.onNodeWithText(message).assertDoesNotExist()
mutableStateFlow.update {
it.copy(
dialogState = VaultItemListingState.DialogState.DeleteSendConfirmation(
sendId = sendId,
),
)
}
composeTestRule
.onNodeWithText(message)
.assertIsDisplayed()
.assert(hasAnyAncestor(isDialog()))
composeTestRule
.onNodeWithText("Yes")
.assert(hasAnyAncestor(isDialog()))
.performClick()
verify(exactly = 1) {
viewModel.trySendAction(VaultItemListingsAction.DeleteSendConfirmClick(sendId))
}
}
@Test
fun `error dialog should be displayed according to state`() {
val errorMessage = "Fail"

View file

@ -200,14 +200,29 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
}
@Test
fun `DeleteSendClick with deleteSend error should display error dialog`() = runTest {
fun `DeleteSendClick should display delete confirmation dialog`() {
val sendId = "sendId"
val viewModel = createVaultItemListingViewModel()
viewModel.trySendAction(VaultItemListingsAction.DeleteSendClick(sendId))
assertEquals(
initialState.copy(
dialogState = VaultItemListingState.DialogState.DeleteSendConfirmation(
sendId = sendId,
),
),
viewModel.stateFlow.value,
)
}
@Test
fun `DeleteSendConfirmClick with deleteSend error should display error dialog`() = runTest {
val sendId = "sendId1234"
coEvery { vaultRepository.deleteSend(sendId) } returns DeleteSendResult.Error
val viewModel = createVaultItemListingViewModel()
viewModel.stateFlow.test {
assertEquals(initialState, awaitItem())
viewModel.trySendAction(VaultItemListingsAction.DeleteSendClick(sendId))
viewModel.trySendAction(VaultItemListingsAction.DeleteSendConfirmClick(sendId))
assertEquals(
initialState.copy(
dialogState = VaultItemListingState.DialogState.Loading(
@ -229,13 +244,13 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
}
@Test
fun `DeleteSendClick with deleteSend success should emit ShowToast`() = runTest {
fun `DeleteSendConfirmClick with deleteSend success should emit ShowToast`() = runTest {
val sendId = "sendId1234"
coEvery { vaultRepository.deleteSend(sendId) } returns DeleteSendResult.Success
val viewModel = createVaultItemListingViewModel()
viewModel.eventFlow.test {
viewModel.trySendAction(VaultItemListingsAction.DeleteSendClick(sendId))
viewModel.trySendAction(VaultItemListingsAction.DeleteSendConfirmClick(sendId))
assertEquals(
VaultItemListingEvent.ShowToast(R.string.send_deleted.asText()),
awaitItem(),