diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/account/BitwardenAccountSwitcher.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/account/BitwardenAccountSwitcher.kt index 235165250d..2dd3e2c526 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/account/BitwardenAccountSwitcher.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/account/BitwardenAccountSwitcher.kt @@ -49,6 +49,7 @@ import com.x8bit.bitwarden.ui.platform.base.util.scrolledContainerBackground import com.x8bit.bitwarden.ui.platform.base.util.toSafeOverlayColor import com.x8bit.bitwarden.ui.platform.base.util.toUnscaledTextUnit import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenLogoutConfirmationDialog +import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenRemovalConfirmationDialog import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenSelectionDialog import com.x8bit.bitwarden.ui.platform.components.dialog.row.BitwardenBasicDialogRow import com.x8bit.bitwarden.ui.platform.components.model.AccountSummary @@ -116,6 +117,7 @@ fun BitwardenAccountSwitcher( var lockOrLogoutAccount by remember { mutableStateOf(null) } var logoutConfirmationAccount by remember { mutableStateOf(null) } + var removeConfirmationAccount by remember { mutableStateOf(null) } when { isVisibleActual -> { // Can not show dialogs when the switcher itself is visible @@ -133,6 +135,10 @@ fun BitwardenAccountSwitcher( lockOrLogoutAccount = null logoutConfirmationAccount = it }, + onRemoveAccountClick = { + lockOrLogoutAccount = null + removeConfirmationAccount = it + }, ) } @@ -146,6 +152,17 @@ fun BitwardenAccountSwitcher( }, ) } + + removeConfirmationAccount != null -> { + BitwardenRemovalConfirmationDialog( + accountSummary = requireNotNull(removeConfirmationAccount), + onDismissRequest = { removeConfirmationAccount = null }, + onConfirmClick = { + onLogoutAccountClick(requireNotNull(removeConfirmationAccount)) + removeConfirmationAccount = null + }, + ) + } } Box(modifier = modifier) { @@ -337,6 +354,7 @@ private fun LockOrLogoutDialog( onDismissRequest: () -> Unit, onLockAccountClick: (AccountSummary) -> Unit, onLogoutAccountClick: (AccountSummary) -> Unit, + onRemoveAccountClick: (AccountSummary) -> Unit, ) { BitwardenSelectionDialog( title = "${accountSummary.email}\n${accountSummary.environmentLabel}", @@ -350,12 +368,21 @@ private fun LockOrLogoutDialog( }, ) } - BitwardenBasicDialogRow( - text = stringResource(id = R.string.log_out), - onClick = { - onLogoutAccountClick(accountSummary) - }, - ) + if (accountSummary.isLoggedIn) { + BitwardenBasicDialogRow( + text = stringResource(id = R.string.log_out), + onClick = { + onLogoutAccountClick(accountSummary) + }, + ) + } else { + BitwardenBasicDialogRow( + text = stringResource(id = R.string.remove_account), + onClick = { + onRemoveAccountClick(accountSummary) + }, + ) + } }, ) } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/dialog/BitwardenRemovalConfirmationDialog.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/dialog/BitwardenRemovalConfirmationDialog.kt new file mode 100644 index 0000000000..e5fd98a34e --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/dialog/BitwardenRemovalConfirmationDialog.kt @@ -0,0 +1,39 @@ +package com.x8bit.bitwarden.ui.platform.components.dialog + +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import com.x8bit.bitwarden.R +import com.x8bit.bitwarden.ui.platform.components.model.AccountSummary + +/** + * A reusable dialog for confirming whether or not the user wants to remove their account. + * + * @param onDismissRequest A callback for when the dialog is requesting dismissal. + * @param onConfirmClick A callback for when the log out confirmation button is clicked. + * @param accountSummary Optional account information that may be used to provide additional + * information. + */ +@Composable +fun BitwardenRemovalConfirmationDialog( + onDismissRequest: () -> Unit, + onConfirmClick: () -> Unit, + accountSummary: AccountSummary? = null, +) { + BitwardenTwoButtonDialog( + title = stringResource(id = R.string.remove_account), + message = removalConfirmationMessage(accountSummary = accountSummary), + confirmButtonText = stringResource(id = R.string.yes), + onConfirmClick = onConfirmClick, + dismissButtonText = stringResource(id = R.string.cancel), + onDismissClick = onDismissRequest, + onDismissRequest = onDismissRequest, + ) +} + +@Composable +private fun removalConfirmationMessage(accountSummary: AccountSummary?): String { + val baseConfirmationMessage = stringResource(id = R.string.remove_account_confirmation) + return accountSummary + ?.let { "$baseConfirmationMessage\n\n${it.email}\n${it.environmentLabel}" } + ?: baseConfirmationMessage +} diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingScreenTest.kt index a79bffedf2..a7816cd7ca 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingScreenTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingScreenTest.kt @@ -24,6 +24,7 @@ import com.x8bit.bitwarden.ui.platform.components.model.AccountSummary import com.x8bit.bitwarden.ui.util.assertLockOrLogoutDialogIsDisplayed import com.x8bit.bitwarden.ui.util.assertLogoutConfirmationDialogIsDisplayed import com.x8bit.bitwarden.ui.util.assertNoDialogExists +import com.x8bit.bitwarden.ui.util.assertRemovalConfirmationDialogIsDisplayed import com.x8bit.bitwarden.ui.util.assertSwitcherIsDisplayed import com.x8bit.bitwarden.ui.util.assertSwitcherIsNotDisplayed import com.x8bit.bitwarden.ui.util.performAccountClick @@ -31,7 +32,8 @@ import com.x8bit.bitwarden.ui.util.performAccountIconClick import com.x8bit.bitwarden.ui.util.performAccountLongClick import com.x8bit.bitwarden.ui.util.performLockAccountClick import com.x8bit.bitwarden.ui.util.performLogoutAccountClick -import com.x8bit.bitwarden.ui.util.performLogoutAccountConfirmationClick +import com.x8bit.bitwarden.ui.util.performRemoveAccountClick +import com.x8bit.bitwarden.ui.util.performYesDialogButtonClick import io.mockk.every import io.mockk.mockk import io.mockk.verify @@ -182,12 +184,46 @@ class LandingScreenTest : BaseComposeTest() { composeTestRule.performAccountLongClick(ACTIVE_ACCOUNT_SUMMARY) composeTestRule.performLogoutAccountClick() - composeTestRule.performLogoutAccountConfirmationClick() + composeTestRule.performYesDialogButtonClick() verify { viewModel.trySendAction(LandingAction.LogoutAccountClick(ACTIVE_ACCOUNT_SUMMARY)) } composeTestRule.assertNoDialogExists() } + @Suppress("MaxLineLength") + @Test + fun `remove account button click in the lock-or-logout dialog should show the remove account confirmation dialog and hide the lock-or-logout dialog`() { + // Show the lock-or-logout dialog + val activeAccountSummary = ACTIVE_ACCOUNT_SUMMARY.copy(isLoggedIn = false) + mutableStateFlow.update { + it.copy(accountSummaries = listOf(activeAccountSummary)) + } + composeTestRule.performAccountIconClick() + composeTestRule.performAccountLongClick(activeAccountSummary) + + composeTestRule.performRemoveAccountClick() + + composeTestRule.assertRemovalConfirmationDialogIsDisplayed(activeAccountSummary) + } + + @Suppress("MaxLineLength") + @Test + fun `remove account button click in the remove account confirmation dialog should send LogoutAccountClick action and close the dialog`() { + // Show the remove account confirmation dialog + val activeAccountSummary = ACTIVE_ACCOUNT_SUMMARY.copy(isLoggedIn = false) + mutableStateFlow.update { + it.copy(accountSummaries = listOf(activeAccountSummary)) + } + composeTestRule.performAccountIconClick() + composeTestRule.performAccountLongClick(activeAccountSummary) + composeTestRule.performRemoveAccountClick() + + composeTestRule.performYesDialogButtonClick() + + verify { viewModel.trySendAction(LandingAction.LogoutAccountClick(activeAccountSummary)) } + composeTestRule.assertNoDialogExists() + } + @Test fun `continue button should be enabled or disabled according to the state`() { composeTestRule.onNodeWithText("Continue").assertIsEnabled() diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreenTest.kt index 83b0e7d6cc..af39f683f4 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreenTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreenTest.kt @@ -21,6 +21,7 @@ import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager import com.x8bit.bitwarden.ui.util.assertLockOrLogoutDialogIsDisplayed import com.x8bit.bitwarden.ui.util.assertLogoutConfirmationDialogIsDisplayed import com.x8bit.bitwarden.ui.util.assertNoDialogExists +import com.x8bit.bitwarden.ui.util.assertRemovalConfirmationDialogIsDisplayed import com.x8bit.bitwarden.ui.util.assertSwitcherIsDisplayed import com.x8bit.bitwarden.ui.util.assertSwitcherIsNotDisplayed import com.x8bit.bitwarden.ui.util.performAccountClick @@ -29,7 +30,8 @@ import com.x8bit.bitwarden.ui.util.performAccountLongClick import com.x8bit.bitwarden.ui.util.performAddAccountClick import com.x8bit.bitwarden.ui.util.performLockAccountClick import com.x8bit.bitwarden.ui.util.performLogoutAccountClick -import com.x8bit.bitwarden.ui.util.performLogoutAccountConfirmationClick +import com.x8bit.bitwarden.ui.util.performRemoveAccountClick +import com.x8bit.bitwarden.ui.util.performYesDialogButtonClick import io.mockk.every import io.mockk.just import io.mockk.mockk @@ -206,12 +208,46 @@ class LoginScreenTest : BaseComposeTest() { composeTestRule.performAccountLongClick(ACTIVE_ACCOUNT_SUMMARY) composeTestRule.performLogoutAccountClick() - composeTestRule.performLogoutAccountConfirmationClick() + composeTestRule.performYesDialogButtonClick() verify { viewModel.trySendAction(LoginAction.LogoutAccountClick(ACTIVE_ACCOUNT_SUMMARY)) } composeTestRule.assertNoDialogExists() } + @Suppress("MaxLineLength") + @Test + fun `remove account button click in the lock-or-logout dialog should show the remove account confirmation dialog and hide the lock-or-logout dialog`() { + // Show the lock-or-logout dialog + val activeAccountSummary = ACTIVE_ACCOUNT_SUMMARY.copy(isLoggedIn = false) + mutableStateFlow.update { + it.copy(accountSummaries = listOf(activeAccountSummary)) + } + composeTestRule.performAccountIconClick() + composeTestRule.performAccountLongClick(activeAccountSummary) + + composeTestRule.performRemoveAccountClick() + + composeTestRule.assertRemovalConfirmationDialogIsDisplayed(activeAccountSummary) + } + + @Suppress("MaxLineLength") + @Test + fun `remove account button click in the remove account confirmation dialog should send LogoutAccountClick action and close the dialog`() { + // Show the remove account confirmation dialog + val activeAccountSummary = ACTIVE_ACCOUNT_SUMMARY.copy(isLoggedIn = false) + mutableStateFlow.update { + it.copy(accountSummaries = listOf(activeAccountSummary)) + } + composeTestRule.performAccountIconClick() + composeTestRule.performAccountLongClick(activeAccountSummary) + composeTestRule.performRemoveAccountClick() + + composeTestRule.performYesDialogButtonClick() + + verify { viewModel.trySendAction(LoginAction.LogoutAccountClick(activeAccountSummary)) } + composeTestRule.assertNoDialogExists() + } + @Test fun `log in with device button visibility should update according to state`() { val buttonText = "Log in with device" diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/vaultunlock/VaultUnlockScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/vaultunlock/VaultUnlockScreenTest.kt index e3cf9a481d..70a823a4e5 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/vaultunlock/VaultUnlockScreenTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/vaultunlock/VaultUnlockScreenTest.kt @@ -21,6 +21,7 @@ import com.x8bit.bitwarden.ui.platform.manager.biometrics.BiometricsManager import com.x8bit.bitwarden.ui.util.assertLockOrLogoutDialogIsDisplayed import com.x8bit.bitwarden.ui.util.assertLogoutConfirmationDialogIsDisplayed import com.x8bit.bitwarden.ui.util.assertNoDialogExists +import com.x8bit.bitwarden.ui.util.assertRemovalConfirmationDialogIsDisplayed import com.x8bit.bitwarden.ui.util.assertSwitcherIsDisplayed import com.x8bit.bitwarden.ui.util.assertSwitcherIsNotDisplayed import com.x8bit.bitwarden.ui.util.performAccountClick @@ -29,7 +30,8 @@ import com.x8bit.bitwarden.ui.util.performAccountLongClick import com.x8bit.bitwarden.ui.util.performAddAccountClick import com.x8bit.bitwarden.ui.util.performLockAccountClick import com.x8bit.bitwarden.ui.util.performLogoutAccountClick -import com.x8bit.bitwarden.ui.util.performLogoutAccountConfirmationClick +import com.x8bit.bitwarden.ui.util.performRemoveAccountClick +import com.x8bit.bitwarden.ui.util.performYesDialogButtonClick import io.mockk.every import io.mockk.just import io.mockk.mockk @@ -244,7 +246,7 @@ class VaultUnlockScreenTest : BaseComposeTest() { composeTestRule.performAccountLongClick(ACTIVE_ACCOUNT_SUMMARY) composeTestRule.performLogoutAccountClick() - composeTestRule.performLogoutAccountConfirmationClick() + composeTestRule.performYesDialogButtonClick() verify { viewModel.trySendAction(VaultUnlockAction.LogoutAccountClick(ACTIVE_ACCOUNT_SUMMARY)) @@ -252,6 +254,42 @@ class VaultUnlockScreenTest : BaseComposeTest() { composeTestRule.assertNoDialogExists() } + @Suppress("MaxLineLength") + @Test + fun `remove account button click in the lock-or-logout dialog should show the remove account confirmation dialog and hide the lock-or-logout dialog`() { + // Show the lock-or-logout dialog + val activeAccountSummary = ACTIVE_ACCOUNT_SUMMARY.copy(isLoggedIn = false) + mutableStateFlow.update { + it.copy(accountSummaries = listOf(activeAccountSummary)) + } + composeTestRule.performAccountIconClick() + composeTestRule.performAccountLongClick(activeAccountSummary) + + composeTestRule.performRemoveAccountClick() + + composeTestRule.assertRemovalConfirmationDialogIsDisplayed(activeAccountSummary) + } + + @Suppress("MaxLineLength") + @Test + fun `remove account button click in the remove account confirmation dialog should send LogoutAccountClick action and close the dialog`() { + // Show the remove account confirmation dialog + val activeAccountSummary = ACTIVE_ACCOUNT_SUMMARY.copy(isLoggedIn = false) + mutableStateFlow.update { + it.copy(accountSummaries = listOf(activeAccountSummary)) + } + composeTestRule.performAccountIconClick() + composeTestRule.performAccountLongClick(activeAccountSummary) + composeTestRule.performRemoveAccountClick() + + composeTestRule.performYesDialogButtonClick() + + verify { + viewModel.trySendAction(VaultUnlockAction.LogoutAccountClick(activeAccountSummary)) + } + composeTestRule.assertNoDialogExists() + } + @Test fun `logout click in the overflow menu should show the logout confirmation dialog`() { // Confirm neither the popup nor the dialog are showing diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/util/BitwardenAccountSwitcherTestHelpers.kt b/app/src/test/java/com/x8bit/bitwarden/ui/util/BitwardenAccountSwitcherTestHelpers.kt index 427331973a..dc52e9bd04 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/util/BitwardenAccountSwitcherTestHelpers.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/util/BitwardenAccountSwitcherTestHelpers.kt @@ -89,7 +89,7 @@ fun ComposeContentTestRule.assertLockOrLogoutDialogIsDisplayed( } /** - * Asserts the logoung confirmation dialog is currently displayed with information from the given + * Asserts the logout confirmation dialog is currently displayed with information from the given * [accountSummary]. */ fun ComposeContentTestRule.assertLogoutConfirmationDialogIsDisplayed( @@ -116,6 +116,34 @@ fun ComposeContentTestRule.assertLogoutConfirmationDialogIsDisplayed( .assertIsDisplayed() } +/** + * Asserts the account removal confirmation dialog is currently displayed with information from + * the given [accountSummary]. + */ +fun ComposeContentTestRule.assertRemovalConfirmationDialogIsDisplayed( + accountSummary: AccountSummary, +) { + this + .onNode(isDialog()) + .assertIsDisplayed() + this + .onAllNodesWithText("Remove account") + .filterToOne(hasAnyAncestor(isDialog())) + .assertIsDisplayed() + this + .onAllNodesWithText("Are you sure you want to remove this account?", substring = true) + .filterToOne(hasAnyAncestor(isDialog())) + .assertIsDisplayed() + this + .onAllNodesWithText(accountSummary.email, substring = true) + .filterToOne(hasAnyAncestor(isDialog())) + .assertIsDisplayed() + this + .onAllNodesWithText(accountSummary.environmentLabel, substring = true) + .filterToOne(hasAnyAncestor(isDialog())) + .assertIsDisplayed() +} + /** * Clicks on the given [accountSummary] in the account switcher. */ @@ -147,7 +175,7 @@ fun ComposeContentTestRule.performLockAccountClick() { } /** - * Clicks the "Lock" button in the "lock or logout" dialog. + * Clicks the "log out" button in the "lock or logout" dialog. */ fun ComposeContentTestRule.performLogoutAccountClick() { this @@ -157,9 +185,19 @@ fun ComposeContentTestRule.performLogoutAccountClick() { } /** - * Clicks the "Yes" button in the logout confirmation dialog to confirm the logout. + * Clicks the "Remove account" button in the "lock or logout" dialog. */ -fun ComposeContentTestRule.performLogoutAccountConfirmationClick() { +fun ComposeContentTestRule.performRemoveAccountClick() { + this + .onAllNodesWithText("Remove account") + .filterToOne(hasAnyAncestor(isDialog())) + .performClick() +} + +/** + * Clicks the "Yes" button in the account confirmation dialog to confirm the action. + */ +fun ComposeContentTestRule.performYesDialogButtonClick() { this .onAllNodesWithText("Yes") .filterToOne(hasAnyAncestor(isDialog())) diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingScreenTest.kt index 4f3b101ba4..4fe8f3e9d0 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingScreenTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingScreenTest.kt @@ -33,6 +33,7 @@ import com.x8bit.bitwarden.ui.util.assertLockOrLogoutDialogIsDisplayed import com.x8bit.bitwarden.ui.util.assertLogoutConfirmationDialogIsDisplayed import com.x8bit.bitwarden.ui.util.assertMasterPasswordDialogDisplayed import com.x8bit.bitwarden.ui.util.assertNoDialogExists +import com.x8bit.bitwarden.ui.util.assertRemovalConfirmationDialogIsDisplayed import com.x8bit.bitwarden.ui.util.assertSwitcherIsDisplayed import com.x8bit.bitwarden.ui.util.assertSwitcherIsNotDisplayed import com.x8bit.bitwarden.ui.util.isProgressBar @@ -42,7 +43,8 @@ import com.x8bit.bitwarden.ui.util.performAccountIconClick import com.x8bit.bitwarden.ui.util.performAccountLongClick import com.x8bit.bitwarden.ui.util.performLockAccountClick import com.x8bit.bitwarden.ui.util.performLogoutAccountClick -import com.x8bit.bitwarden.ui.util.performLogoutAccountConfirmationClick +import com.x8bit.bitwarden.ui.util.performRemoveAccountClick +import com.x8bit.bitwarden.ui.util.performYesDialogButtonClick import com.x8bit.bitwarden.ui.vault.feature.itemlisting.model.ListingItemOverflowAction import com.x8bit.bitwarden.ui.vault.feature.vault.model.VaultFilterType import com.x8bit.bitwarden.ui.vault.model.VaultItemCipherType @@ -261,7 +263,7 @@ class VaultItemListingScreenTest : BaseComposeTest() { composeTestRule.performAccountLongClick(ACTIVE_ACCOUNT_SUMMARY) composeTestRule.performLogoutAccountClick() - composeTestRule.performLogoutAccountConfirmationClick() + composeTestRule.performYesDialogButtonClick() verify { viewModel.trySendAction( @@ -271,6 +273,50 @@ class VaultItemListingScreenTest : BaseComposeTest() { composeTestRule.assertNoDialogExists() } + @Suppress("MaxLineLength") + @Test + fun `remove account button click in the lock-or-logout dialog should show the remove account confirmation dialog and hide the lock-or-logout dialog`() { + // Show the lock-or-logout dialog + val activeAccountSummary = ACTIVE_ACCOUNT_SUMMARY.copy(isLoggedIn = false) + mutableStateFlow.update { + it.copy( + accountSummaries = listOf(activeAccountSummary), + autofillSelectionData = AUTOFILL_SELECTION_DATA, + ) + } + composeTestRule.performAccountIconClick() + composeTestRule.performAccountLongClick(activeAccountSummary) + + composeTestRule.performRemoveAccountClick() + + composeTestRule.assertRemovalConfirmationDialogIsDisplayed(activeAccountSummary) + } + + @Suppress("MaxLineLength") + @Test + fun `remove account button click in the remove account confirmation dialog should send LogoutAccountClick action and close the dialog`() { + // Show the remove account confirmation dialog + val activeAccountSummary = ACTIVE_ACCOUNT_SUMMARY.copy(isLoggedIn = false) + mutableStateFlow.update { + it.copy( + accountSummaries = listOf(activeAccountSummary), + autofillSelectionData = AUTOFILL_SELECTION_DATA, + ) + } + composeTestRule.performAccountIconClick() + composeTestRule.performAccountLongClick(activeAccountSummary) + composeTestRule.performRemoveAccountClick() + + composeTestRule.performYesDialogButtonClick() + + verify { + viewModel.trySendAction( + VaultItemListingsAction.LogoutAccountClick(activeAccountSummary), + ) + } + composeTestRule.assertNoDialogExists() + } + @Test fun `NavigateBack event should invoke NavigateBack`() { mutableEventFlow.tryEmit(VaultItemListingEvent.NavigateBack) diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreenTest.kt index 835b1eb762..cbe5cab694 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreenTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreenTest.kt @@ -28,6 +28,7 @@ import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager import com.x8bit.bitwarden.ui.util.assertLockOrLogoutDialogIsDisplayed import com.x8bit.bitwarden.ui.util.assertLogoutConfirmationDialogIsDisplayed import com.x8bit.bitwarden.ui.util.assertNoDialogExists +import com.x8bit.bitwarden.ui.util.assertRemovalConfirmationDialogIsDisplayed import com.x8bit.bitwarden.ui.util.assertScrollableNodeDoesNotExist import com.x8bit.bitwarden.ui.util.assertSwitcherIsDisplayed import com.x8bit.bitwarden.ui.util.assertSwitcherIsNotDisplayed @@ -38,7 +39,8 @@ import com.x8bit.bitwarden.ui.util.performAccountLongClick import com.x8bit.bitwarden.ui.util.performAddAccountClick import com.x8bit.bitwarden.ui.util.performLockAccountClick import com.x8bit.bitwarden.ui.util.performLogoutAccountClick -import com.x8bit.bitwarden.ui.util.performLogoutAccountConfirmationClick +import com.x8bit.bitwarden.ui.util.performRemoveAccountClick +import com.x8bit.bitwarden.ui.util.performYesDialogButtonClick import com.x8bit.bitwarden.ui.vault.feature.vault.model.VaultFilterData import com.x8bit.bitwarden.ui.vault.feature.vault.model.VaultFilterType import com.x8bit.bitwarden.ui.vault.model.VaultItemListingType @@ -334,12 +336,46 @@ class VaultScreenTest : BaseComposeTest() { composeTestRule.performAccountLongClick(ACTIVE_ACCOUNT_SUMMARY) composeTestRule.performLogoutAccountClick() - composeTestRule.performLogoutAccountConfirmationClick() + composeTestRule.performYesDialogButtonClick() verify { viewModel.trySendAction(VaultAction.LogoutAccountClick(ACTIVE_ACCOUNT_SUMMARY)) } composeTestRule.assertNoDialogExists() } + @Suppress("MaxLineLength") + @Test + fun `remove account button click in the lock-or-logout dialog should show the remove account confirmation dialog and hide the lock-or-logout dialog`() { + // Show the lock-or-logout dialog + val activeAccountSummary = ACTIVE_ACCOUNT_SUMMARY.copy(isLoggedIn = false) + mutableStateFlow.update { + it.copy(accountSummaries = listOf(activeAccountSummary)) + } + composeTestRule.performAccountIconClick() + composeTestRule.performAccountLongClick(activeAccountSummary) + + composeTestRule.performRemoveAccountClick() + + composeTestRule.assertRemovalConfirmationDialogIsDisplayed(activeAccountSummary) + } + + @Suppress("MaxLineLength") + @Test + fun `remove account button click in the remove account confirmation dialog should send LogoutAccountClick action and close the dialog`() { + // Show the remove account confirmation dialog + val activeAccountSummary = ACTIVE_ACCOUNT_SUMMARY.copy(isLoggedIn = false) + mutableStateFlow.update { + it.copy(accountSummaries = listOf(activeAccountSummary)) + } + composeTestRule.performAccountIconClick() + composeTestRule.performAccountLongClick(activeAccountSummary) + composeTestRule.performRemoveAccountClick() + + composeTestRule.performYesDialogButtonClick() + + verify { viewModel.trySendAction(VaultAction.LogoutAccountClick(activeAccountSummary)) } + composeTestRule.assertNoDialogExists() + } + @Test fun `overflow button click should show the overflow menu`() { composeTestRule.onNode(isPopup()).assertDoesNotExist()