BIT-556 BIT-190 Update current CreateAccountScreen to match designs (#92)

This commit is contained in:
Andrew Haisting 2023-10-03 16:39:59 -05:00 committed by Álison Fernandes
parent eedf0b6f91
commit 38155dbefd
9 changed files with 237 additions and 65 deletions

View file

@ -22,7 +22,7 @@ fun NavGraphBuilder.authDestinations(navController: NavHostController) {
startDestination = LANDING_ROUTE, startDestination = LANDING_ROUTE,
route = AUTH_ROUTE, route = AUTH_ROUTE,
) { ) {
createAccountDestinations() createAccountDestinations(onNavigateBack = { navController.popBackStack() })
landingDestinations( landingDestinations(
onNavigateToCreateAccount = { navController.navigateToCreateAccount() }, onNavigateToCreateAccount = { navController.navigateToCreateAccount() },
onNavigateToLogin = { emailAddress, regionLabel -> onNavigateToLogin = { emailAddress, regionLabel ->

View file

@ -17,8 +17,10 @@ fun NavController.navigateToCreateAccount(navOptions: NavOptions? = null) {
/** /**
* Add the create account screen to the nav graph. * Add the create account screen to the nav graph.
*/ */
fun NavGraphBuilder.createAccountDestinations() { fun NavGraphBuilder.createAccountDestinations(
onNavigateBack: () -> Unit,
) {
composable(route = CREATE_ACCOUNT_ROUTE) { composable(route = CREATE_ACCOUNT_ROUTE) {
CreateAccountScreen() CreateAccountScreen(onNavigateBack)
} }
} }

View file

@ -2,21 +2,19 @@ package com.x8bit.bitwarden.ui.auth.feature.createaccount
import android.widget.Toast import android.widget.Toast
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement.spacedBy import androidx.compose.foundation.layout.Arrangement.spacedBy
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
@ -25,8 +23,10 @@ import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.Con
import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.EmailInputChange import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.EmailInputChange
import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.PasswordHintChange import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.PasswordHintChange
import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.PasswordInputChange import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.PasswordInputChange
import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.SubmitClick
import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect
import com.x8bit.bitwarden.ui.platform.components.BitwardenFilledButton
import com.x8bit.bitwarden.ui.platform.components.BitwardenPasswordField
import com.x8bit.bitwarden.ui.platform.components.BitwardenTextButtonTopAppBar
import com.x8bit.bitwarden.ui.platform.components.BitwardenTextField import com.x8bit.bitwarden.ui.platform.components.BitwardenTextField
/** /**
@ -35,12 +35,14 @@ import com.x8bit.bitwarden.ui.platform.components.BitwardenTextField
@Suppress("LongMethod") @Suppress("LongMethod")
@Composable @Composable
fun CreateAccountScreen( fun CreateAccountScreen(
onNavigateBack: () -> Unit,
viewModel: CreateAccountViewModel = hiltViewModel(), viewModel: CreateAccountViewModel = hiltViewModel(),
) { ) {
val state by viewModel.stateFlow.collectAsState() val state by viewModel.stateFlow.collectAsState()
val context = LocalContext.current val context = LocalContext.current
EventsEffect(viewModel) { event -> EventsEffect(viewModel) { event ->
when (event) { when (event) {
is CreateAccountEvent.NavigateBack -> onNavigateBack.invoke()
is CreateAccountEvent.ShowToast -> { is CreateAccountEvent.ShowToast -> {
Toast.makeText(context, event.text, Toast.LENGTH_SHORT).show() Toast.makeText(context, event.text, Toast.LENGTH_SHORT).show()
} }
@ -51,56 +53,60 @@ fun CreateAccountScreen(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.background(MaterialTheme.colorScheme.surface), .background(MaterialTheme.colorScheme.surface),
verticalArrangement = spacedBy(8.dp),
) { ) {
Row( BitwardenTextButtonTopAppBar(
modifier = Modifier title = stringResource(id = R.string.create_account),
.fillMaxWidth() navigationIcon = painterResource(id = R.drawable.ic_close),
.background(MaterialTheme.colorScheme.primary), navigationIconContentDescription = stringResource(id = R.string.close),
verticalAlignment = Alignment.CenterVertically, onNavigationIconClick = remember(viewModel) {
{ viewModel.trySendAction(CreateAccountAction.CloseClick) }
},
buttonText = stringResource(id = R.string.submit),
onButtonClick = remember(viewModel) {
{ viewModel.trySendAction(CreateAccountAction.SubmitClick) }
},
isButtonEnabled = state.isSubmitEnabled,
)
Column(
modifier = Modifier.padding(horizontal = 16.dp),
verticalArrangement = spacedBy(16.dp),
) { ) {
Text( BitwardenTextField(
modifier = Modifier label = stringResource(id = R.string.email_address),
.weight(1f) value = state.emailInput,
.padding(16.dp), onValueChange = remember(viewModel) {
text = stringResource(id = R.string.create_account), { viewModel.trySendAction(EmailInputChange(it)) }
color = MaterialTheme.colorScheme.onPrimary, },
style = MaterialTheme.typography.titleLarge, modifier = Modifier.fillMaxWidth(),
) )
Text( BitwardenPasswordField(
modifier = Modifier label = stringResource(id = R.string.master_password),
.clickable { value = state.passwordInput,
viewModel.trySendAction(SubmitClick) onValueChange = remember(viewModel) {
} { viewModel.trySendAction(PasswordInputChange(it)) }
.padding(16.dp), },
text = stringResource(id = R.string.submit), modifier = Modifier.fillMaxWidth(),
color = MaterialTheme.colorScheme.onPrimary, )
style = MaterialTheme.typography.bodyMedium, BitwardenPasswordField(
label = stringResource(id = R.string.retype_master_password),
value = state.confirmPasswordInput,
onValueChange = remember {
{ viewModel.trySendAction(ConfirmPasswordInputChange(it)) }
},
modifier = Modifier.fillMaxWidth(),
)
BitwardenTextField(
label = stringResource(id = R.string.master_password_hint),
value = state.passwordHintInput,
onValueChange = remember { { viewModel.trySendAction(PasswordHintChange(it)) } },
modifier = Modifier.fillMaxWidth(),
)
BitwardenFilledButton(
label = stringResource(id = R.string.submit),
onClick = remember { { viewModel.trySendAction(CreateAccountAction.SubmitClick) } },
isEnabled = state.isSubmitEnabled,
modifier = Modifier.fillMaxWidth(),
) )
} }
BitwardenTextField(
label = stringResource(id = R.string.email_address),
value = state.emailInput,
onValueChange = { viewModel.trySendAction(EmailInputChange(it)) },
modifier = Modifier.fillMaxWidth(),
)
BitwardenTextField(
label = stringResource(id = R.string.master_password),
value = state.passwordInput,
onValueChange = { viewModel.trySendAction(PasswordInputChange(it)) },
modifier = Modifier.fillMaxWidth(),
)
BitwardenTextField(
label = stringResource(id = R.string.retype_master_password),
value = state.confirmPasswordInput,
onValueChange = { viewModel.trySendAction(ConfirmPasswordInputChange(it)) },
modifier = Modifier.fillMaxWidth(),
)
BitwardenTextField(
label = stringResource(id = R.string.master_password_hint),
value = state.passwordHintInput,
onValueChange = { viewModel.trySendAction(PasswordHintChange(it)) },
modifier = Modifier.fillMaxWidth(),
)
} }
} }

View file

@ -31,6 +31,7 @@ class CreateAccountViewModel @Inject constructor(
passwordInput = "", passwordInput = "",
confirmPasswordInput = "", confirmPasswordInput = "",
passwordHintInput = "", passwordHintInput = "",
isSubmitEnabled = false,
), ),
) { ) {
@ -48,9 +49,14 @@ class CreateAccountViewModel @Inject constructor(
is EmailInputChange -> handleEmailInputChanged(action) is EmailInputChange -> handleEmailInputChanged(action)
is PasswordHintChange -> handlePasswordHintChanged(action) is PasswordHintChange -> handlePasswordHintChanged(action)
is PasswordInputChange -> handlePasswordInputChanged(action) is PasswordInputChange -> handlePasswordInputChanged(action)
is CreateAccountAction.CloseClick -> handleCloseClick()
} }
} }
private fun handleCloseClick() {
sendEvent(CreateAccountEvent.NavigateBack)
}
private fun handleEmailInputChanged(action: EmailInputChange) { private fun handleEmailInputChanged(action: EmailInputChange) {
mutableStateFlow.update { it.copy(emailInput = action.input) } mutableStateFlow.update { it.copy(emailInput = action.input) }
} }
@ -81,6 +87,7 @@ data class CreateAccountState(
val passwordInput: String, val passwordInput: String,
val confirmPasswordInput: String, val confirmPasswordInput: String,
val passwordHintInput: String, val passwordHintInput: String,
val isSubmitEnabled: Boolean,
) : Parcelable ) : Parcelable
/** /**
@ -88,6 +95,11 @@ data class CreateAccountState(
*/ */
sealed class CreateAccountEvent { sealed class CreateAccountEvent {
/**
* Navigate back to previous screen.
*/
data object NavigateBack : CreateAccountEvent()
/** /**
* Placeholder event for showing a toast. Can be removed once there are real events. * Placeholder event for showing a toast. Can be removed once there are real events.
*/ */
@ -103,6 +115,11 @@ sealed class CreateAccountAction {
*/ */
data object SubmitClick : CreateAccountAction() data object SubmitClick : CreateAccountAction()
/**
* User clicked close.
*/
data object CloseClick : CreateAccountAction()
/** /**
* Email input changed. * Email input changed.
*/ */

View file

@ -6,6 +6,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@ -26,7 +27,7 @@ fun BitwardenFilledButton(
) { ) {
Button( Button(
onClick = onClick, onClick = onClick,
modifier = modifier, modifier = modifier.semantics(mergeDescendants = true) {},
enabled = isEnabled, enabled = isEnabled,
contentPadding = PaddingValues( contentPadding = PaddingValues(
vertical = 10.dp, vertical = 10.dp,
@ -35,7 +36,11 @@ fun BitwardenFilledButton(
) { ) {
Text( Text(
text = label, text = label,
color = MaterialTheme.colorScheme.onPrimary, color = if (isEnabled) {
MaterialTheme.colorScheme.onPrimary
} else {
MaterialTheme.colorScheme.onSurface.copy(alpha = .38f)
},
style = MaterialTheme.typography.labelLarge, style = MaterialTheme.typography.labelLarge,
) )
} }

View file

@ -21,14 +21,20 @@ fun BitwardenTextButton(
label: String, label: String,
onClick: () -> Unit, onClick: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
isEnabled: Boolean = true,
) { ) {
TextButton( TextButton(
onClick = onClick, onClick = onClick,
modifier = modifier, modifier = modifier,
enabled = isEnabled,
) { ) {
Text( Text(
text = label, text = label,
color = MaterialTheme.colorScheme.primary, color = if (isEnabled) {
MaterialTheme.colorScheme.primary
} else {
MaterialTheme.colorScheme.onSurface.copy(alpha = .38f)
},
style = MaterialTheme.typography.labelLarge, style = MaterialTheme.typography.labelLarge,
modifier = Modifier modifier = Modifier
.padding( .padding(

View file

@ -0,0 +1,77 @@
package com.x8bit.bitwarden.ui.platform.components
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import com.x8bit.bitwarden.R
/**
* Represents a Bitwarden styled [TopAppBar] that assumes the following components:
*
* - a single navigation control in the upper-left defined by [navigationIcon],
* [navigationIconContentDescription], and [onNavigationIconClick].
* - a [title] in the middle.
* - a [BitwardenTextButton] on the right that will display [buttonText] and call [onButtonClick]
* when clicked and [isButtonEnabled] is true.
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BitwardenTextButtonTopAppBar(
title: String,
navigationIcon: Painter,
navigationIconContentDescription: String,
onNavigationIconClick: () -> Unit,
buttonText: String,
onButtonClick: () -> Unit,
isButtonEnabled: Boolean,
) {
TopAppBar(
navigationIcon = {
IconButton(
onClick = { onNavigationIconClick() },
) {
Icon(
painter = navigationIcon,
contentDescription = navigationIconContentDescription,
tint = MaterialTheme.colorScheme.onSurface,
)
}
},
title = {
Text(
text = title,
style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.onSurface,
)
},
actions = {
BitwardenTextButton(
label = buttonText,
onClick = onButtonClick,
isEnabled = isButtonEnabled,
)
},
)
}
@Preview
@Composable
private fun BitwardenTextButtonTopAppBar_preview() {
BitwardenTextButtonTopAppBar(
title = "Title",
navigationIcon = painterResource(id = R.drawable.ic_close),
navigationIconContentDescription = stringResource(id = R.string.close),
onNavigationIconClick = {},
buttonText = "Button",
onButtonClick = {},
isButtonEnabled = true,
)
}

View file

@ -1,8 +1,11 @@
package com.x8bit.bitwarden.ui.auth.feature.createaccount package com.x8bit.bitwarden.ui.auth.feature.createaccount
import androidx.compose.ui.test.onAllNodesWithText
import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTextInput import androidx.compose.ui.test.performTextInput
import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.CloseClick
import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.ConfirmPasswordInputChange import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.ConfirmPasswordInputChange
import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.EmailInputChange import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.EmailInputChange
import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.PasswordHintChange import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.PasswordHintChange
@ -14,24 +17,67 @@ import io.mockk.mockk
import io.mockk.verify import io.mockk.verify
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flowOf
import org.junit.Test import org.junit.Test
class CreateAccountScreenTest : BaseComposeTest() { class CreateAccountScreenTest : BaseComposeTest() {
@Test @Test
fun `submit click should send SubmitClick action`() { fun `app bar submit click should send SubmitClick action`() {
val viewModel = mockk<CreateAccountViewModel>(relaxed = true) { val viewModel = mockk<CreateAccountViewModel>(relaxed = true) {
every { stateFlow } returns MutableStateFlow(DEFAULT_STATE) every { stateFlow } returns MutableStateFlow(DEFAULT_STATE.copy(isSubmitEnabled = true))
every { eventFlow } returns emptyFlow() every { eventFlow } returns emptyFlow()
every { trySendAction(SubmitClick) } returns Unit every { trySendAction(SubmitClick) } returns Unit
} }
composeTestRule.setContent { composeTestRule.setContent {
CreateAccountScreen(viewModel) CreateAccountScreen(onNavigateBack = {}, viewModel = viewModel)
} }
composeTestRule.onNodeWithText("Submit").performClick() composeTestRule.onAllNodesWithText("Submit")[0].performClick()
verify { viewModel.trySendAction(SubmitClick) } verify { viewModel.trySendAction(SubmitClick) }
} }
@Test
fun `bottom button submit click should send SubmitClick action`() {
val viewModel = mockk<CreateAccountViewModel>(relaxed = true) {
every { stateFlow } returns MutableStateFlow(DEFAULT_STATE.copy(isSubmitEnabled = true))
every { eventFlow } returns emptyFlow()
every { trySendAction(SubmitClick) } returns Unit
}
composeTestRule.setContent {
CreateAccountScreen(onNavigateBack = {}, viewModel = viewModel)
}
composeTestRule.onAllNodesWithText("Submit")[1].performClick()
verify { viewModel.trySendAction(SubmitClick) }
}
@Test
fun `close click should send CloseClick action`() {
val viewModel = mockk<CreateAccountViewModel>(relaxed = true) {
every { stateFlow } returns MutableStateFlow(DEFAULT_STATE)
every { eventFlow } returns emptyFlow()
every { trySendAction(CloseClick) } returns Unit
}
composeTestRule.setContent {
CreateAccountScreen(onNavigateBack = {}, viewModel = viewModel)
}
composeTestRule.onNodeWithContentDescription("Close").performClick()
verify { viewModel.trySendAction(CloseClick) }
}
@Test
fun `NavigateBack event should invoke navigate back lambda`() {
var onNavigateBackCalled = false
val onNavigateBack = { onNavigateBackCalled = true }
val viewModel = mockk<CreateAccountViewModel>(relaxed = true) {
every { stateFlow } returns MutableStateFlow(DEFAULT_STATE)
every { eventFlow } returns flowOf(CreateAccountEvent.NavigateBack)
}
composeTestRule.setContent {
CreateAccountScreen(onNavigateBack = onNavigateBack, viewModel = viewModel)
}
assert(onNavigateBackCalled)
}
@Test @Test
fun `email input change should send EmailInputChange action`() { fun `email input change should send EmailInputChange action`() {
val viewModel = mockk<CreateAccountViewModel>(relaxed = true) { val viewModel = mockk<CreateAccountViewModel>(relaxed = true) {
@ -40,7 +86,7 @@ class CreateAccountScreenTest : BaseComposeTest() {
every { trySendAction(EmailInputChange("input")) } returns Unit every { trySendAction(EmailInputChange("input")) } returns Unit
} }
composeTestRule.setContent { composeTestRule.setContent {
CreateAccountScreen(viewModel) CreateAccountScreen(onNavigateBack = {}, viewModel = viewModel)
} }
composeTestRule.onNodeWithText("Email address").performTextInput(TEST_INPUT) composeTestRule.onNodeWithText("Email address").performTextInput(TEST_INPUT)
verify { viewModel.trySendAction(EmailInputChange(TEST_INPUT)) } verify { viewModel.trySendAction(EmailInputChange(TEST_INPUT)) }
@ -54,7 +100,7 @@ class CreateAccountScreenTest : BaseComposeTest() {
every { trySendAction(PasswordInputChange("input")) } returns Unit every { trySendAction(PasswordInputChange("input")) } returns Unit
} }
composeTestRule.setContent { composeTestRule.setContent {
CreateAccountScreen(viewModel) CreateAccountScreen(onNavigateBack = {}, viewModel = viewModel)
} }
composeTestRule.onNodeWithText("Master password").performTextInput(TEST_INPUT) composeTestRule.onNodeWithText("Master password").performTextInput(TEST_INPUT)
verify { viewModel.trySendAction(PasswordInputChange(TEST_INPUT)) } verify { viewModel.trySendAction(PasswordInputChange(TEST_INPUT)) }
@ -68,7 +114,7 @@ class CreateAccountScreenTest : BaseComposeTest() {
every { trySendAction(ConfirmPasswordInputChange("input")) } returns Unit every { trySendAction(ConfirmPasswordInputChange("input")) } returns Unit
} }
composeTestRule.setContent { composeTestRule.setContent {
CreateAccountScreen(viewModel) CreateAccountScreen(onNavigateBack = {}, viewModel = viewModel)
} }
composeTestRule.onNodeWithText("Re-type master password").performTextInput(TEST_INPUT) composeTestRule.onNodeWithText("Re-type master password").performTextInput(TEST_INPUT)
verify { viewModel.trySendAction(ConfirmPasswordInputChange(TEST_INPUT)) } verify { viewModel.trySendAction(ConfirmPasswordInputChange(TEST_INPUT)) }
@ -82,7 +128,7 @@ class CreateAccountScreenTest : BaseComposeTest() {
every { trySendAction(PasswordHintChange("input")) } returns Unit every { trySendAction(PasswordHintChange("input")) } returns Unit
} }
composeTestRule.setContent { composeTestRule.setContent {
CreateAccountScreen(viewModel) CreateAccountScreen(onNavigateBack = {}, viewModel = viewModel)
} }
composeTestRule composeTestRule
.onNodeWithText("Master password hint (optional)") .onNodeWithText("Master password hint (optional)")
@ -97,6 +143,7 @@ class CreateAccountScreenTest : BaseComposeTest() {
passwordInput = "", passwordInput = "",
confirmPasswordInput = "", confirmPasswordInput = "",
passwordHintInput = "", passwordHintInput = "",
isSubmitEnabled = false,
) )
} }
} }

View file

@ -2,6 +2,7 @@ package com.x8bit.bitwarden.ui.auth.feature.createaccount
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import app.cash.turbine.test import app.cash.turbine.test
import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.CloseClick
import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.ConfirmPasswordInputChange import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.ConfirmPasswordInputChange
import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.EmailInputChange import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.EmailInputChange
import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.PasswordHintChange import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.PasswordHintChange
@ -27,6 +28,7 @@ class CreateAccountViewModelTest : BaseViewModelTest() {
passwordInput = "password", passwordInput = "password",
confirmPasswordInput = "confirmPassword", confirmPasswordInput = "confirmPassword",
passwordHintInput = "hint", passwordHintInput = "hint",
isSubmitEnabled = false,
) )
val handle = SavedStateHandle(mapOf("state" to savedState)) val handle = SavedStateHandle(mapOf("state" to savedState))
val viewModel = CreateAccountViewModel(handle) val viewModel = CreateAccountViewModel(handle)
@ -42,6 +44,15 @@ class CreateAccountViewModelTest : BaseViewModelTest() {
} }
} }
@Test
fun `CloseClick should emit NavigateBack`() = runTest {
val viewModel = CreateAccountViewModel(SavedStateHandle())
viewModel.eventFlow.test {
viewModel.actionChannel.trySend(CloseClick)
assert(awaitItem() is CreateAccountEvent.NavigateBack)
}
}
@Test @Test
fun `ConfirmPasswordInputChange update passwordInput`() = runTest { fun `ConfirmPasswordInputChange update passwordInput`() = runTest {
val viewModel = CreateAccountViewModel(SavedStateHandle()) val viewModel = CreateAccountViewModel(SavedStateHandle())
@ -84,6 +95,7 @@ class CreateAccountViewModelTest : BaseViewModelTest() {
emailInput = "", emailInput = "",
confirmPasswordInput = "", confirmPasswordInput = "",
passwordHintInput = "", passwordHintInput = "",
isSubmitEnabled = false,
) )
} }
} }