BIT-1031: Add shell for the delete account UI (#241)

This commit is contained in:
David Perez 2023-11-13 13:17:16 -06:00 committed by Álison Fernandes
parent 028a2caa65
commit 715ff06dfc
18 changed files with 528 additions and 10 deletions

View file

@ -0,0 +1,72 @@
package com.x8bit.bitwarden.ui.platform.components
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
/**
* Represents a Bitwarden-styled filled [Button] for error scenarios.
*
* @param label The label for the button.
* @param onClick The callback when the button is clicked.
* @param modifier The [Modifier] to be applied to the button.
* @param isEnabled Whether or not the button is enabled.
*/
@Composable
fun BitwardenErrorButton(
label: String,
onClick: () -> Unit,
modifier: Modifier = Modifier,
isEnabled: Boolean = true,
) {
Button(
onClick = onClick,
modifier = modifier.semantics(mergeDescendants = true) {},
enabled = isEnabled,
contentPadding = PaddingValues(
vertical = 10.dp,
horizontal = 24.dp,
),
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.error,
contentColor = MaterialTheme.colorScheme.onError,
),
) {
Text(
text = label,
style = MaterialTheme.typography.labelLarge,
)
}
}
@Preview
@Composable
private fun BitwardenErrorButton_preview_isEnabled() {
BitwardenTheme {
BitwardenErrorButton(
label = "Label",
onClick = {},
isEnabled = true,
)
}
}
@Preview(showBackground = true)
@Composable
private fun BitwardenErrorButton_preview_isNotEnabled() {
BitwardenTheme {
BitwardenErrorButton(
label = "Label",
onClick = {},
isEnabled = false,
)
}
}

View file

@ -0,0 +1,65 @@
package com.x8bit.bitwarden.ui.platform.components
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
/**
* Represents a Bitwarden-styled filled [OutlinedButton].
*
* @param label The label for the button.
* @param onClick The callback when the button is clicked.
* @param modifier The [Modifier] to be applied to the button.
* @param isEnabled Whether or not the button is enabled.
*/
@Composable
fun BitwardenOutlinedButton(
label: String,
onClick: () -> Unit,
modifier: Modifier = Modifier,
isEnabled: Boolean = true,
) {
OutlinedButton(
onClick = onClick,
modifier = modifier
.semantics(mergeDescendants = true) { },
enabled = isEnabled,
contentPadding = PaddingValues(
vertical = 10.dp,
horizontal = 24.dp,
),
colors = ButtonDefaults.outlinedButtonColors(),
) {
Text(
text = label,
style = MaterialTheme.typography.labelLarge,
)
}
}
@Preview
@Composable
private fun BitwardenOutlinedButton_preview_isEnabled() {
BitwardenOutlinedButton(
label = "Label",
onClick = {},
isEnabled = true,
)
}
@Preview
@Composable
private fun BitwardenOutlinedButton_preview_isNotEnabled() {
BitwardenOutlinedButton(
label = "Label",
onClick = {},
isEnabled = false,
)
}

View file

@ -27,6 +27,7 @@ private const val SETTINGS_ROUTE: String = "settings"
*/
fun NavGraphBuilder.settingsGraph(
navController: NavController,
onNavigateToDeleteAccount: () -> Unit,
) {
navigation(
startDestination = SETTINGS_ROUTE,
@ -49,7 +50,10 @@ fun NavGraphBuilder.settingsGraph(
)
}
aboutDestination(onNavigateBack = { navController.popBackStack() })
accountSecurityDestination(onNavigateBack = { navController.popBackStack() })
accountSecurityDestination(
onNavigateBack = { navController.popBackStack() },
onNavigateToDeleteAccount = onNavigateToDeleteAccount,
)
appearanceDestination(onNavigateBack = { navController.popBackStack() })
autoFillDestination(onNavigateBack = { navController.popBackStack() })
otherDestination(onNavigateBack = { navController.popBackStack() })

View file

@ -13,6 +13,7 @@ private const val ACCOUNT_SECURITY_ROUTE = "settings_account_security"
*/
fun NavGraphBuilder.accountSecurityDestination(
onNavigateBack: () -> Unit,
onNavigateToDeleteAccount: () -> Unit,
) {
composable(
route = ACCOUNT_SECURITY_ROUTE,
@ -21,7 +22,10 @@ fun NavGraphBuilder.accountSecurityDestination(
popEnterTransition = TransitionProviders.Enter.pushLeft,
popExitTransition = TransitionProviders.Exit.pushRight,
) {
AccountSecurityScreen(onNavigateBack = onNavigateBack)
AccountSecurityScreen(
onNavigateBack = onNavigateBack,
onNavigateToDeleteAccount = onNavigateToDeleteAccount,
)
}
}

View file

@ -52,6 +52,7 @@ import com.x8bit.bitwarden.ui.platform.theme.LocalNonMaterialTypography
@Composable
fun AccountSecurityScreen(
onNavigateBack: () -> Unit,
onNavigateToDeleteAccount: () -> Unit,
viewModel: AccountSecurityViewModel = hiltViewModel(),
intentHandler: IntentHandler = IntentHandler(context = LocalContext.current),
) {
@ -62,6 +63,8 @@ fun AccountSecurityScreen(
when (event) {
AccountSecurityEvent.NavigateBack -> onNavigateBack()
AccountSecurityEvent.NavigateToDeleteAccount -> onNavigateToDeleteAccount()
AccountSecurityEvent.NavigateToFingerprintPhrase -> {
intentHandler.launchUri("http://bitwarden.com/help/fingerprint-phrase".toUri())
}

View file

@ -87,8 +87,7 @@ class AccountSecurityViewModel @Inject constructor(
}
private fun handleDeleteAccountClick() {
// TODO BIT-1031: Navigate to delete account
sendEvent(AccountSecurityEvent.ShowToast("Not yet implemented.".asText()))
sendEvent(AccountSecurityEvent.NavigateToDeleteAccount)
}
private fun handleDismissDialog() {
@ -215,6 +214,11 @@ sealed class AccountSecurityEvent {
*/
data object NavigateBack : AccountSecurityEvent()
/**
* Navigate to the delete account screen.
*/
data object NavigateToDeleteAccount : AccountSecurityEvent()
/**
* Navigate to fingerprint phrase information.
*/

View file

@ -0,0 +1,33 @@
package com.x8bit.bitwarden.ui.platform.feature.settings.accountsecurity.deleteaccount
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import androidx.navigation.compose.composable
import com.x8bit.bitwarden.ui.platform.theme.TransitionProviders
private const val DELETE_ACCOUNT_ROUTE = "delete_account"
/**
* Add delete account destinations to the nav graph.
*/
fun NavGraphBuilder.deleteAccountDestination(
onNavigateBack: () -> Unit,
) {
composable(
route = DELETE_ACCOUNT_ROUTE,
enterTransition = TransitionProviders.Enter.slideUp,
exitTransition = TransitionProviders.Exit.slideDown,
popEnterTransition = TransitionProviders.Enter.slideUp,
popExitTransition = TransitionProviders.Exit.slideDown,
) {
DeleteAccountScreen(onNavigateBack = onNavigateBack)
}
}
/**
* Navigate to the delete account screen.
*/
fun NavController.navigateToDeleteAccount(navOptions: NavOptions? = null) {
navigate(DELETE_ACCOUNT_ROUTE, navOptions)
}

View file

@ -0,0 +1,130 @@
package com.x8bit.bitwarden.ui.platform.feature.settings.accountsecurity.deleteaccount
import android.widget.Toast
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect
import com.x8bit.bitwarden.ui.platform.components.BitwardenErrorButton
import com.x8bit.bitwarden.ui.platform.components.BitwardenOutlinedButton
import com.x8bit.bitwarden.ui.platform.components.BitwardenScaffold
import com.x8bit.bitwarden.ui.platform.components.BitwardenTopAppBar
/**
* Displays the delete account screen.
*/
@Suppress("LongMethod")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DeleteAccountScreen(
viewModel: DeleteAccountViewModel = hiltViewModel(),
onNavigateBack: () -> Unit,
) {
val context = LocalContext.current
val resources = context.resources
EventsEffect(viewModel = viewModel) { event ->
when (event) {
DeleteAccountEvent.NavigateBack -> onNavigateBack()
is DeleteAccountEvent.ShowToast -> {
Toast.makeText(context, event.message(resources), Toast.LENGTH_SHORT).show()
}
}
}
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
BitwardenScaffold(
modifier = Modifier
.fillMaxSize()
.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
BitwardenTopAppBar(
title = stringResource(id = R.string.delete_account),
scrollBehavior = scrollBehavior,
navigationIcon = painterResource(id = R.drawable.ic_close),
navigationIconContentDescription = stringResource(id = R.string.close),
onNavigationIconClick = remember(viewModel) {
{ viewModel.trySendAction(DeleteAccountAction.CloseClick) }
},
)
},
) { innerPadding ->
Column(
modifier = Modifier
.imePadding()
.fillMaxSize()
.padding(innerPadding)
.verticalScroll(rememberScrollState()),
) {
Spacer(modifier = Modifier.height(8.dp))
Icon(
painter = painterResource(id = R.drawable.ic_warning),
contentDescription = null,
tint = MaterialTheme.colorScheme.error,
modifier = Modifier.padding(horizontal = 16.dp),
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = stringResource(id = R.string.deleting_your_account_is_permanent),
style = MaterialTheme.typography.headlineSmall,
color = MaterialTheme.colorScheme.error,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
)
Spacer(modifier = Modifier.height(24.dp))
Text(
text = stringResource(id = R.string.delete_account_explanation),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
)
Spacer(modifier = Modifier.height(24.dp))
BitwardenErrorButton(
label = stringResource(id = R.string.delete_account),
onClick = remember(viewModel) {
{ viewModel.trySendAction(DeleteAccountAction.DeleteAccountClick) }
},
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
)
Spacer(modifier = Modifier.height(12.dp))
BitwardenOutlinedButton(
label = stringResource(id = R.string.cancel),
onClick = remember(viewModel) {
{ viewModel.trySendAction(DeleteAccountAction.CancelClick) }
},
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
)
Spacer(modifier = Modifier.navigationBarsPadding())
}
}
}

View file

@ -0,0 +1,75 @@
package com.x8bit.bitwarden.ui.platform.feature.settings.accountsecurity.deleteaccount
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
import com.x8bit.bitwarden.ui.platform.base.util.Text
import com.x8bit.bitwarden.ui.platform.base.util.asText
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
/**
* View model for the account security screen.
*/
@HiltViewModel
class DeleteAccountViewModel @Inject constructor() :
BaseViewModel<Unit, DeleteAccountEvent, DeleteAccountAction>(
initialState = Unit,
) {
override fun handleAction(action: DeleteAccountAction) {
when (action) {
DeleteAccountAction.CancelClick -> handleCancelClick()
DeleteAccountAction.CloseClick -> handleCloseClick()
DeleteAccountAction.DeleteAccountClick -> handleDeleteAccountClick()
}
}
private fun handleCancelClick() {
sendEvent(DeleteAccountEvent.NavigateBack)
}
private fun handleCloseClick() {
sendEvent(DeleteAccountEvent.NavigateBack)
}
private fun handleDeleteAccountClick() {
// TODO: Delete the users account (BIT-1111)
sendEvent(DeleteAccountEvent.ShowToast("Not yet implemented.".asText()))
}
}
/**
* Models events for the delete account screen.
*/
sealed class DeleteAccountEvent {
/**
* Navigates back.
*/
data object NavigateBack : DeleteAccountEvent()
/**
* Displays the [message] in a toast.
*/
data class ShowToast(
val message: Text,
) : DeleteAccountEvent()
}
/**
* Models actions for the delete account screen.
*/
sealed class DeleteAccountAction {
/**
* The user has clicked the cancel button.
*/
data object CancelClick : DeleteAccountAction()
/**
* The user has clicked the close button.
*/
data object CloseClick : DeleteAccountAction()
/**
* The user has clicked the delete account button.
*/
data object DeleteAccountClick : DeleteAccountAction()
}

View file

@ -4,6 +4,8 @@ import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import androidx.navigation.navigation
import com.x8bit.bitwarden.ui.platform.feature.settings.accountsecurity.deleteaccount.deleteAccountDestination
import com.x8bit.bitwarden.ui.platform.feature.settings.accountsecurity.deleteaccount.navigateToDeleteAccount
import com.x8bit.bitwarden.ui.platform.feature.vaultunlockednavbar.VAULT_UNLOCKED_NAV_BAR_ROUTE
import com.x8bit.bitwarden.ui.platform.feature.vaultunlockednavbar.vaultUnlockedNavBarDestination
import com.x8bit.bitwarden.ui.tools.feature.send.navigateToNewSend
@ -33,7 +35,9 @@ fun NavGraphBuilder.vaultUnlockedGraph(
vaultUnlockedNavBarDestination(
onNavigateToVaultAddItem = { navController.navigateToVaultAddItem() },
onNavigateToNewSend = { navController.navigateToNewSend() },
onNavigateToDeleteAccount = { navController.navigateToDeleteAccount() },
)
deleteAccountDestination(onNavigateBack = { navController.popBackStack() })
vaultAddItemDestination(onNavigateBack = { navController.popBackStack() })
newSendDestination(onNavigateBack = { navController.popBackStack() })
}

View file

@ -24,6 +24,7 @@ fun NavController.navigateToVaultUnlockedNavBar(navOptions: NavOptions? = null)
fun NavGraphBuilder.vaultUnlockedNavBarDestination(
onNavigateToVaultAddItem: () -> Unit,
onNavigateToNewSend: () -> Unit,
onNavigateToDeleteAccount: () -> Unit,
) {
composable(
route = VAULT_UNLOCKED_NAV_BAR_ROUTE,
@ -35,6 +36,7 @@ fun NavGraphBuilder.vaultUnlockedNavBarDestination(
VaultUnlockedNavBarScreen(
onNavigateToVaultAddItem = onNavigateToVaultAddItem,
onNavigateToNewSend = onNavigateToNewSend,
onNavigateToDeleteAccount = onNavigateToDeleteAccount,
)
}
}

View file

@ -67,6 +67,7 @@ fun VaultUnlockedNavBarScreen(
navController: NavHostController = rememberNavController(),
onNavigateToVaultAddItem: () -> Unit,
onNavigateToNewSend: () -> Unit,
onNavigateToDeleteAccount: () -> Unit,
) {
EventsEffect(viewModel = viewModel) { event ->
navController.apply {
@ -94,6 +95,7 @@ fun VaultUnlockedNavBarScreen(
navController = navController,
navigateToVaultAddItem = onNavigateToVaultAddItem,
navigateToNewSend = onNavigateToNewSend,
navigateToDeleteAccount = onNavigateToDeleteAccount,
generatorTabClickedAction = {
viewModel.trySendAction(VaultUnlockedNavBarAction.GeneratorTabClick)
},
@ -122,6 +124,7 @@ private fun VaultUnlockedNavBarScaffold(
settingsTabClickedAction: () -> Unit,
navigateToVaultAddItem: () -> Unit,
navigateToNewSend: () -> Unit,
navigateToDeleteAccount: () -> Unit,
) {
var shouldDimNavBar by remember { mutableStateOf(false) }
@ -181,7 +184,10 @@ private fun VaultUnlockedNavBarScaffold(
)
sendGraph(onNavigateToNewSend = navigateToNewSend)
generatorDestination()
settingsGraph(navController)
settingsGraph(
navController = navController,
onNavigateToDeleteAccount = navigateToDeleteAccount,
)
}
}
}

View file

@ -0,0 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp"
android:height="28dp"
android:viewportHeight="28"
android:viewportWidth="28">
<group>
<clip-path android:pathData="M0.667,0.667h26.667v26.667h-26.667z" />
<path
android:fillColor="#BA1A1A"
android:fillType="evenOdd"
android:pathData="M16.036,3.434L26.957,20.361C28.069,22.083 26.646,24 24.921,24H3.079C1.354,24 -0.069,22.083 1.043,20.361L11.964,3.434C12.91,1.967 15.09,1.967 16.036,3.434ZM14.635,4.337C14.345,3.888 13.655,3.888 13.365,4.337L2.443,21.264C2.141,21.733 2.498,22.333 3.079,22.333H24.921C25.502,22.333 25.859,21.733 25.557,21.264L14.635,4.337Z" />
<path
android:fillColor="#BA1A1A"
android:fillType="evenOdd"
android:pathData="M14.001,9.499C14.461,9.499 14.834,9.872 14.834,10.332V15.528C14.834,15.989 14.461,16.362 14.001,16.362C13.541,16.362 13.168,15.989 13.168,15.528V10.332C13.168,9.872 13.541,9.499 14.001,9.499Z" />
<path
android:fillColor="#BA1A1A"
android:pathData="M15.126,19.785C15.126,20.406 14.622,20.91 14.001,20.91C13.38,20.91 12.876,20.406 12.876,19.785C12.876,19.163 13.38,18.66 14.001,18.66C14.622,18.66 15.126,19.163 15.126,19.785Z" />
</group>
</vector>

View file

@ -33,6 +33,7 @@ import org.junit.Test
class AccountSecurityScreenTest : BaseComposeTest() {
private var onNavigateBackCalled = false
private var onNavigateToDeleteAccountCalled = false
private val intentHandler = mockk<IntentHandler> {
every { launchUri(any()) } just runs
@ -51,6 +52,7 @@ class AccountSecurityScreenTest : BaseComposeTest() {
composeTestRule.setContent {
AccountSecurityScreen(
onNavigateBack = { onNavigateBackCalled = true },
onNavigateToDeleteAccount = { onNavigateToDeleteAccountCalled = true },
viewModel = viewModel,
intentHandler = intentHandler,
)
@ -236,6 +238,12 @@ class AccountSecurityScreenTest : BaseComposeTest() {
assertTrue(onNavigateBackCalled)
}
@Test
fun `on NavigateToDeleteAccount should call onNavigateToDeleteAccountCalled`() {
mutableEventFlow.tryEmit(AccountSecurityEvent.NavigateToDeleteAccount)
assertTrue(onNavigateToDeleteAccountCalled)
}
@Test
fun `confirm dialog be shown or hidden according to the state`() {
composeTestRule.onNode(isDialog()).assertDoesNotExist()

View file

@ -62,14 +62,11 @@ class AccountSecurityViewModelTest : BaseViewModelTest() {
}
@Test
fun `on DeleteAccountClick should emit ShowToast`() = runTest {
fun `on DeleteAccountClick should emit NavigateToDeleteAccount`() = runTest {
val viewModel = createViewModel()
viewModel.eventFlow.test {
viewModel.trySendAction(AccountSecurityAction.DeleteAccountClick)
assertEquals(
AccountSecurityEvent.ShowToast("Not yet implemented.".asText()),
awaitItem(),
)
assertEquals(AccountSecurityEvent.NavigateToDeleteAccount, awaitItem())
}
}

View file

@ -0,0 +1,40 @@
package com.x8bit.bitwarden.ui.platform.feature.settings.accountsecurity.deleteaccount
import com.x8bit.bitwarden.ui.platform.base.BaseComposeTest
import io.mockk.every
import io.mockk.mockk
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
class DeleteAccountScreenTest : BaseComposeTest() {
private var onNavigateBackCalled = false
private val mutableEventFlow = MutableSharedFlow<DeleteAccountEvent>(
extraBufferCapacity = Int.MAX_VALUE,
)
private val mutableStateFlow = MutableStateFlow(Unit)
private val viewModel = mockk<DeleteAccountViewModel>(relaxed = true) {
every { eventFlow } returns mutableEventFlow
every { stateFlow } returns mutableStateFlow
}
@Before
fun setUp() {
composeTestRule.setContent {
DeleteAccountScreen(
onNavigateBack = { onNavigateBackCalled = true },
viewModel = viewModel,
)
}
}
@Test
fun `on NavigateBack should call onNavigateBack`() {
mutableEventFlow.tryEmit(DeleteAccountEvent.NavigateBack)
assertTrue(onNavigateBackCalled)
}
}

View file

@ -0,0 +1,43 @@
package com.x8bit.bitwarden.ui.platform.feature.settings.accountsecurity.deleteaccount
import app.cash.turbine.test
import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest
import com.x8bit.bitwarden.ui.platform.base.util.asText
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
class DeleteAccountViewModelTest : BaseViewModelTest() {
@Test
fun `on CancelClick should emit NavigateBack`() = runTest {
val viewModel = createViewModel()
viewModel.eventFlow.test {
viewModel.trySendAction(DeleteAccountAction.CancelClick)
assertEquals(DeleteAccountEvent.NavigateBack, awaitItem())
}
}
@Test
fun `on CloseClick should emit NavigateBack`() = runTest {
val viewModel = createViewModel()
viewModel.eventFlow.test {
viewModel.trySendAction(DeleteAccountAction.CloseClick)
assertEquals(DeleteAccountEvent.NavigateBack, awaitItem())
}
}
@Test
fun `on DeleteAccountClick should emit ShowToast`() = runTest {
val viewModel = createViewModel()
viewModel.eventFlow.test {
viewModel.trySendAction(DeleteAccountAction.DeleteAccountClick)
assertEquals(
DeleteAccountEvent.ShowToast("Not yet implemented.".asText()),
awaitItem(),
)
}
}
private fun createViewModel(): DeleteAccountViewModel = DeleteAccountViewModel()
}

View file

@ -34,6 +34,7 @@ class VaultUnlockedNavBarScreenTest : BaseComposeTest() {
navController = fakeNavHostController,
onNavigateToVaultAddItem = {},
onNavigateToNewSend = {},
onNavigateToDeleteAccount = {},
)
}
onNodeWithText("My vault").performClick()
@ -56,6 +57,7 @@ class VaultUnlockedNavBarScreenTest : BaseComposeTest() {
navController = fakeNavHostController,
onNavigateToVaultAddItem = {},
onNavigateToNewSend = {},
onNavigateToDeleteAccount = {},
)
}
runOnIdle { fakeNavHostController.assertCurrentRoute("vault") }
@ -79,6 +81,7 @@ class VaultUnlockedNavBarScreenTest : BaseComposeTest() {
navController = fakeNavHostController,
onNavigateToVaultAddItem = {},
onNavigateToNewSend = {},
onNavigateToDeleteAccount = {},
)
}
onNodeWithText("Send").performClick()
@ -101,6 +104,7 @@ class VaultUnlockedNavBarScreenTest : BaseComposeTest() {
navController = fakeNavHostController,
onNavigateToVaultAddItem = {},
onNavigateToNewSend = {},
onNavigateToDeleteAccount = {},
)
}
runOnIdle { fakeNavHostController.assertCurrentRoute("vault") }
@ -124,6 +128,7 @@ class VaultUnlockedNavBarScreenTest : BaseComposeTest() {
navController = fakeNavHostController,
onNavigateToVaultAddItem = {},
onNavigateToNewSend = {},
onNavigateToDeleteAccount = {},
)
}
onNodeWithText("Generator").performClick()
@ -146,6 +151,7 @@ class VaultUnlockedNavBarScreenTest : BaseComposeTest() {
navController = fakeNavHostController,
onNavigateToVaultAddItem = {},
onNavigateToNewSend = {},
onNavigateToDeleteAccount = {},
)
}
runOnIdle { fakeNavHostController.assertCurrentRoute("vault") }
@ -169,6 +175,7 @@ class VaultUnlockedNavBarScreenTest : BaseComposeTest() {
navController = fakeNavHostController,
onNavigateToVaultAddItem = {},
onNavigateToNewSend = {},
onNavigateToDeleteAccount = {},
)
}
onNodeWithText("Settings").performClick()
@ -191,6 +198,7 @@ class VaultUnlockedNavBarScreenTest : BaseComposeTest() {
navController = fakeNavHostController,
onNavigateToVaultAddItem = {},
onNavigateToNewSend = {},
onNavigateToDeleteAccount = {},
)
}
runOnIdle { fakeNavHostController.assertCurrentRoute("vault") }