mirror of
https://github.com/bitwarden/android.git
synced 2025-02-16 11:59:57 +03:00
BIT-202: Adding region selector composable to Landing Screen (#91)
This commit is contained in:
parent
bc319368ed
commit
eedf0b6f91
12 changed files with 238 additions and 28 deletions
|
@ -25,7 +25,9 @@ fun NavGraphBuilder.authDestinations(navController: NavHostController) {
|
|||
createAccountDestinations()
|
||||
landingDestinations(
|
||||
onNavigateToCreateAccount = { navController.navigateToCreateAccount() },
|
||||
onNavigateToLogin = { emailAddress -> navController.navigateToLogin(emailAddress) },
|
||||
onNavigateToLogin = { emailAddress, regionLabel ->
|
||||
navController.navigateToLogin(emailAddress, regionLabel)
|
||||
},
|
||||
)
|
||||
loginDestinations(
|
||||
onNavigateBack = { navController.popBackStack() },
|
||||
|
|
|
@ -19,7 +19,7 @@ fun NavController.navigateToLanding(navOptions: NavOptions? = null) {
|
|||
*/
|
||||
fun NavGraphBuilder.landingDestinations(
|
||||
onNavigateToCreateAccount: () -> Unit,
|
||||
onNavigateToLogin: (String) -> Unit,
|
||||
onNavigateToLogin: (emailAddress: String, regionLabel: String) -> Unit,
|
||||
) {
|
||||
composable(route = LANDING_ROUTE) {
|
||||
LandingScreen(
|
||||
|
|
|
@ -2,7 +2,9 @@ package com.x8bit.bitwarden.ui.auth.feature.landing
|
|||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
|
@ -14,11 +16,16 @@ import androidx.compose.foundation.layout.width
|
|||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.DropdownMenu
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
|
@ -36,6 +43,7 @@ import com.x8bit.bitwarden.ui.platform.components.BitwardenFilledButton
|
|||
import com.x8bit.bitwarden.ui.platform.components.BitwardenSwitch
|
||||
import com.x8bit.bitwarden.ui.platform.components.BitwardenTextButton
|
||||
import com.x8bit.bitwarden.ui.platform.components.BitwardenTextField
|
||||
import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
|
||||
|
||||
/**
|
||||
* The top level composable for the Landing screen.
|
||||
|
@ -44,14 +52,17 @@ import com.x8bit.bitwarden.ui.platform.components.BitwardenTextField
|
|||
@Suppress("LongMethod")
|
||||
fun LandingScreen(
|
||||
onNavigateToCreateAccount: () -> Unit,
|
||||
onNavigateToLogin: (emailAddress: String) -> Unit,
|
||||
onNavigateToLogin: (emailAddress: String, regionLabel: String) -> Unit,
|
||||
viewModel: LandingViewModel = hiltViewModel(),
|
||||
) {
|
||||
val state by viewModel.stateFlow.collectAsStateWithLifecycle()
|
||||
EventsEffect(viewModel = viewModel) { event ->
|
||||
when (event) {
|
||||
LandingEvent.NavigateToCreateAccount -> onNavigateToCreateAccount()
|
||||
is LandingEvent.NavigateToLogin -> onNavigateToLogin(event.emailAddress)
|
||||
is LandingEvent.NavigateToLogin -> onNavigateToLogin(
|
||||
event.emailAddress,
|
||||
event.regionLabel,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,6 +114,14 @@ fun LandingScreen(
|
|||
label = stringResource(id = R.string.email_address),
|
||||
)
|
||||
|
||||
RegionSelector(
|
||||
selectedOption = state.selectedRegion,
|
||||
options = LandingState.RegionOption.values().toList(),
|
||||
onOptionSelected = remember(viewModel) {
|
||||
{ viewModel.trySendAction(LandingAction.RegionOptionSelect(it)) }
|
||||
},
|
||||
)
|
||||
|
||||
BitwardenSwitch(
|
||||
label = stringResource(id = R.string.remember_me),
|
||||
isChecked = state.isRememberMeEnabled,
|
||||
|
@ -152,12 +171,78 @@ fun LandingScreen(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A dropdown selector UI component specific to region url selection on the Landing screen.
|
||||
*
|
||||
* This composable displays a dropdown menu allowing users to select a region
|
||||
* from a list of options. When an option is selected, it invokes the provided callback
|
||||
* and displays the currently selected region on the UI.
|
||||
*
|
||||
* @param selectedOption The currently selected region option.
|
||||
* @param options A list of region options available for selection.
|
||||
* @param onOptionSelected A callback that gets invoked when a region option is selected
|
||||
* and passes the selected option as an argument.
|
||||
*
|
||||
*/
|
||||
@Composable
|
||||
private fun RegionSelector(
|
||||
selectedOption: LandingState.RegionOption,
|
||||
options: List<LandingState.RegionOption>,
|
||||
onOptionSelected: (LandingState.RegionOption) -> Unit,
|
||||
) {
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
|
||||
Box(modifier = Modifier.fillMaxWidth()) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.clickable { expanded = !expanded }
|
||||
.fillMaxWidth()
|
||||
.padding(start = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.logging_in_on),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
modifier = Modifier.padding(end = 12.dp),
|
||||
)
|
||||
Text(
|
||||
text = selectedOption.label,
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier.padding(end = 8.dp),
|
||||
)
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_region_select_dropdown),
|
||||
contentDescription = stringResource(id = R.string.region),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
|
||||
DropdownMenu(
|
||||
expanded = expanded,
|
||||
onDismissRequest = { expanded = false },
|
||||
) {
|
||||
options.forEach { optionString ->
|
||||
DropdownMenuItem(
|
||||
text = { Text(text = optionString.label) },
|
||||
onClick = {
|
||||
expanded = false
|
||||
onOptionSelected(optionString)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun LandingScreen_preview() {
|
||||
LandingScreen(
|
||||
onNavigateToCreateAccount = {},
|
||||
onNavigateToLogin = {},
|
||||
viewModel = LandingViewModel(SavedStateHandle()),
|
||||
)
|
||||
BitwardenTheme {
|
||||
LandingScreen(
|
||||
onNavigateToCreateAccount = {},
|
||||
onNavigateToLogin = { _, _ -> },
|
||||
viewModel = LandingViewModel(SavedStateHandle()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ class LandingViewModel @Inject constructor(
|
|||
emailInput = "",
|
||||
isContinueButtonEnabled = false,
|
||||
isRememberMeEnabled = false,
|
||||
selectedRegion = LandingState.RegionOption.BITWARDEN_US,
|
||||
),
|
||||
) {
|
||||
|
||||
|
@ -41,6 +42,7 @@ class LandingViewModel @Inject constructor(
|
|||
LandingAction.CreateAccountClick -> handleCreateAccountClicked()
|
||||
is LandingAction.RememberMeToggle -> handleRememberMeToggled(action)
|
||||
is LandingAction.EmailInputChanged -> handleEmailInputUpdated(action)
|
||||
is LandingAction.RegionOptionSelect -> handleRegionSelect(action)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,7 +61,9 @@ class LandingViewModel @Inject constructor(
|
|||
if (mutableStateFlow.value.emailInput.isBlank()) {
|
||||
return
|
||||
}
|
||||
sendEvent(LandingEvent.NavigateToLogin(mutableStateFlow.value.emailInput))
|
||||
val email = mutableStateFlow.value.emailInput
|
||||
val selectedRegionLabel = mutableStateFlow.value.selectedRegion.label
|
||||
sendEvent(LandingEvent.NavigateToLogin(email, selectedRegionLabel))
|
||||
}
|
||||
|
||||
private fun handleCreateAccountClicked() {
|
||||
|
@ -69,6 +73,14 @@ class LandingViewModel @Inject constructor(
|
|||
private fun handleRememberMeToggled(action: LandingAction.RememberMeToggle) {
|
||||
mutableStateFlow.update { it.copy(isRememberMeEnabled = action.isChecked) }
|
||||
}
|
||||
|
||||
private fun handleRegionSelect(action: LandingAction.RegionOptionSelect) {
|
||||
mutableStateFlow.update {
|
||||
it.copy(
|
||||
selectedRegion = action.regionOption,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,7 +91,17 @@ data class LandingState(
|
|||
val emailInput: String,
|
||||
val isContinueButtonEnabled: Boolean,
|
||||
val isRememberMeEnabled: Boolean,
|
||||
) : Parcelable
|
||||
val selectedRegion: RegionOption,
|
||||
) : Parcelable {
|
||||
/**
|
||||
* Enumerates the possible region options with their corresponding labels.
|
||||
*/
|
||||
enum class RegionOption(val label: String) {
|
||||
BITWARDEN_US("bitwarden.com"),
|
||||
BITWARDEN_EU("bitwarden.eu"),
|
||||
SELF_HOSTED("Self-hosted"),
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Models events for the landing screen.
|
||||
|
@ -91,10 +113,11 @@ sealed class LandingEvent {
|
|||
data object NavigateToCreateAccount : LandingEvent()
|
||||
|
||||
/**
|
||||
* Navigates to the Login screen with the given email address.
|
||||
* Navigates to the Login screen with the given email address and region label.
|
||||
*/
|
||||
data class NavigateToLogin(
|
||||
val emailAddress: String,
|
||||
val regionLabel: String,
|
||||
) : LandingEvent()
|
||||
}
|
||||
|
||||
|
@ -125,4 +148,11 @@ sealed class LandingAction {
|
|||
data class EmailInputChanged(
|
||||
val input: String,
|
||||
) : LandingAction()
|
||||
|
||||
/**
|
||||
* Indicates that the selection from the region drop down has changed.
|
||||
*/
|
||||
data class RegionOptionSelect(
|
||||
val regionOption: LandingState.RegionOption,
|
||||
) : LandingAction()
|
||||
}
|
||||
|
|
|
@ -9,25 +9,28 @@ import androidx.navigation.compose.composable
|
|||
import androidx.navigation.navArgument
|
||||
|
||||
private const val EMAIL_ADDRESS: String = "email_address"
|
||||
private const val LOGIN_ROUTE: String = "login/{$EMAIL_ADDRESS}"
|
||||
private const val REGION_LABEL: String = "region_label"
|
||||
private const val LOGIN_ROUTE: String = "login/{$EMAIL_ADDRESS}/{$REGION_LABEL}"
|
||||
|
||||
/**
|
||||
* Class to retrieve login arguments from the [SavedStateHandle].
|
||||
*/
|
||||
class LoginArgs(val emailAddress: String) {
|
||||
class LoginArgs(val emailAddress: String, val regionLabel: String) {
|
||||
constructor(savedStateHandle: SavedStateHandle) : this(
|
||||
checkNotNull(savedStateHandle[EMAIL_ADDRESS]) as String,
|
||||
checkNotNull(savedStateHandle[REGION_LABEL]) as String,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigate to the login screen with the given email address.
|
||||
* Navigate to the login screen with the given email address and region label.
|
||||
*/
|
||||
fun NavController.navigateToLogin(
|
||||
emailAddress: String,
|
||||
regionLabel: String,
|
||||
navOptions: NavOptions? = null,
|
||||
) {
|
||||
this.navigate("login/$emailAddress", navOptions)
|
||||
this.navigate("login/$emailAddress/$regionLabel", navOptions)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -145,7 +145,7 @@ fun LoginScreen(
|
|||
text = stringResource(
|
||||
id = R.string.log_in_attempt_by_x_on_y,
|
||||
state.emailAddress,
|
||||
"bitwarden.com",
|
||||
state.region,
|
||||
),
|
||||
textAlign = TextAlign.Start,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
|
|
|
@ -34,6 +34,7 @@ class LoginViewModel @Inject constructor(
|
|||
emailAddress = LoginArgs(savedStateHandle).emailAddress,
|
||||
isLoginButtonEnabled = true,
|
||||
passwordInput = "",
|
||||
region = LoginArgs(savedStateHandle).regionLabel,
|
||||
),
|
||||
) {
|
||||
|
||||
|
@ -135,6 +136,7 @@ class LoginViewModel @Inject constructor(
|
|||
data class LoginState(
|
||||
val passwordInput: String,
|
||||
val emailAddress: String,
|
||||
val region: String,
|
||||
val isLoginButtonEnabled: Boolean,
|
||||
) : Parcelable
|
||||
|
||||
|
|
13
app/src/main/res/drawable/ic_region_select_dropdown.xml
Normal file
13
app/src/main/res/drawable/ic_region_select_dropdown.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:viewportWidth="16"
|
||||
android:viewportHeight="16">
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M0.5,0.5h15v15h-15z"/>
|
||||
<path
|
||||
android:pathData="M7.995,12.65C7.552,12.649 7.123,12.467 6.789,12.138L0.866,6.361C0.701,6.2 0.585,5.986 0.532,5.747C0.479,5.509 0.492,5.258 0.571,5.029C0.639,4.811 0.764,4.622 0.931,4.487C1.098,4.352 1.297,4.279 1.502,4.277L14.489,4.213C14.694,4.213 14.895,4.284 15.063,4.418C15.23,4.551 15.357,4.739 15.427,4.956C15.506,5.185 15.522,5.436 15.47,5.675C15.418,5.914 15.302,6.129 15.138,6.292L9.208,12.13C8.874,12.464 8.442,12.649 7.995,12.65Z"
|
||||
android:fillColor="#175DDC"/>
|
||||
</group>
|
||||
</vector>
|
|
@ -28,6 +28,7 @@ class LandingScreenTest : BaseComposeTest() {
|
|||
emailInput = "",
|
||||
isContinueButtonEnabled = true,
|
||||
isRememberMeEnabled = false,
|
||||
selectedRegion = LandingState.RegionOption.BITWARDEN_US,
|
||||
),
|
||||
)
|
||||
val viewModel = mockk<LandingViewModel>(relaxed = true) {
|
||||
|
@ -37,7 +38,7 @@ class LandingScreenTest : BaseComposeTest() {
|
|||
composeTestRule.setContent {
|
||||
LandingScreen(
|
||||
onNavigateToCreateAccount = {},
|
||||
onNavigateToLogin = {},
|
||||
onNavigateToLogin = { _, _ -> },
|
||||
viewModel = viewModel,
|
||||
)
|
||||
}
|
||||
|
@ -57,13 +58,14 @@ class LandingScreenTest : BaseComposeTest() {
|
|||
emailInput = "",
|
||||
isContinueButtonEnabled = true,
|
||||
isRememberMeEnabled = false,
|
||||
selectedRegion = LandingState.RegionOption.BITWARDEN_US,
|
||||
),
|
||||
)
|
||||
}
|
||||
composeTestRule.setContent {
|
||||
LandingScreen(
|
||||
onNavigateToCreateAccount = {},
|
||||
onNavigateToLogin = {},
|
||||
onNavigateToLogin = { _, _ -> },
|
||||
viewModel = viewModel,
|
||||
)
|
||||
}
|
||||
|
@ -82,13 +84,14 @@ class LandingScreenTest : BaseComposeTest() {
|
|||
emailInput = "",
|
||||
isContinueButtonEnabled = true,
|
||||
isRememberMeEnabled = false,
|
||||
selectedRegion = LandingState.RegionOption.BITWARDEN_US,
|
||||
),
|
||||
)
|
||||
}
|
||||
composeTestRule.setContent {
|
||||
LandingScreen(
|
||||
onNavigateToCreateAccount = {},
|
||||
onNavigateToLogin = {},
|
||||
onNavigateToLogin = { _, _ -> },
|
||||
viewModel = viewModel,
|
||||
)
|
||||
}
|
||||
|
@ -111,13 +114,14 @@ class LandingScreenTest : BaseComposeTest() {
|
|||
emailInput = "",
|
||||
isContinueButtonEnabled = true,
|
||||
isRememberMeEnabled = false,
|
||||
selectedRegion = LandingState.RegionOption.BITWARDEN_US,
|
||||
),
|
||||
)
|
||||
}
|
||||
composeTestRule.setContent {
|
||||
LandingScreen(
|
||||
onNavigateToCreateAccount = {},
|
||||
onNavigateToLogin = {},
|
||||
onNavigateToLogin = { _, _ -> },
|
||||
viewModel = viewModel,
|
||||
)
|
||||
}
|
||||
|
@ -137,13 +141,14 @@ class LandingScreenTest : BaseComposeTest() {
|
|||
emailInput = "",
|
||||
isContinueButtonEnabled = true,
|
||||
isRememberMeEnabled = false,
|
||||
selectedRegion = LandingState.RegionOption.BITWARDEN_US,
|
||||
),
|
||||
)
|
||||
}
|
||||
composeTestRule.setContent {
|
||||
LandingScreen(
|
||||
onNavigateToCreateAccount = {},
|
||||
onNavigateToLogin = {},
|
||||
onNavigateToLogin = { _, _ -> },
|
||||
viewModel = viewModel,
|
||||
)
|
||||
}
|
||||
|
@ -163,13 +168,14 @@ class LandingScreenTest : BaseComposeTest() {
|
|||
emailInput = "",
|
||||
isContinueButtonEnabled = true,
|
||||
isRememberMeEnabled = false,
|
||||
selectedRegion = LandingState.RegionOption.BITWARDEN_US,
|
||||
),
|
||||
)
|
||||
}
|
||||
composeTestRule.setContent {
|
||||
LandingScreen(
|
||||
onNavigateToCreateAccount = { onNavigateToCreateAccountCalled = true },
|
||||
onNavigateToLogin = {},
|
||||
onNavigateToLogin = { _, _ -> },
|
||||
viewModel = viewModel,
|
||||
)
|
||||
}
|
||||
|
@ -179,24 +185,69 @@ class LandingScreenTest : BaseComposeTest() {
|
|||
@Test
|
||||
fun `NavigateToLogin event should call onNavigateToLogin`() {
|
||||
val testEmail = "test@test.com"
|
||||
var onNavigateToLoginEmail = ""
|
||||
val testRegion = "bitwarden.com"
|
||||
|
||||
var capturedEmail: String? = null
|
||||
var capturedRegion: String? = null
|
||||
|
||||
val viewModel = mockk<LandingViewModel>(relaxed = true) {
|
||||
every { eventFlow } returns flowOf(LandingEvent.NavigateToLogin(testEmail))
|
||||
every { eventFlow } returns flowOf(LandingEvent.NavigateToLogin(testEmail, testRegion))
|
||||
every { stateFlow } returns MutableStateFlow(
|
||||
LandingState(
|
||||
emailInput = "",
|
||||
isContinueButtonEnabled = true,
|
||||
isRememberMeEnabled = false,
|
||||
selectedRegion = LandingState.RegionOption.BITWARDEN_US,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
composeTestRule.setContent {
|
||||
LandingScreen(
|
||||
onNavigateToCreateAccount = { },
|
||||
onNavigateToLogin = { onNavigateToLoginEmail = it },
|
||||
onNavigateToLogin = { email, region ->
|
||||
capturedEmail = email
|
||||
capturedRegion = region
|
||||
},
|
||||
viewModel = viewModel,
|
||||
)
|
||||
}
|
||||
assertEquals(testEmail, onNavigateToLoginEmail)
|
||||
|
||||
assertEquals(testEmail, capturedEmail)
|
||||
assertEquals(testRegion, capturedRegion)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `selecting region should send RegionOptionSelect action`() {
|
||||
val selectedRegion = LandingState.RegionOption.BITWARDEN_EU
|
||||
val viewModel = mockk<LandingViewModel>(relaxed = true) {
|
||||
every { eventFlow } returns emptyFlow()
|
||||
every { stateFlow } returns MutableStateFlow(
|
||||
LandingState(
|
||||
emailInput = "",
|
||||
isContinueButtonEnabled = true,
|
||||
isRememberMeEnabled = false,
|
||||
selectedRegion = LandingState.RegionOption.BITWARDEN_US,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
composeTestRule.setContent {
|
||||
LandingScreen(
|
||||
onNavigateToCreateAccount = {},
|
||||
onNavigateToLogin = { _, _ -> },
|
||||
viewModel = viewModel,
|
||||
)
|
||||
}
|
||||
|
||||
// Clicking to open dropdown
|
||||
composeTestRule.onNodeWithText(LandingState.RegionOption.BITWARDEN_US.label).performClick()
|
||||
|
||||
// Clicking item from the dropdown menu
|
||||
composeTestRule.onNodeWithText(selectedRegion.label).performClick()
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(LandingAction.RegionOptionSelect(selectedRegion))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ class LandingViewModelTest : BaseViewModelTest() {
|
|||
viewModel.eventFlow.test {
|
||||
viewModel.actionChannel.trySend(LandingAction.ContinueButtonClick)
|
||||
assertEquals(
|
||||
LandingEvent.NavigateToLogin("input"),
|
||||
LandingEvent.NavigateToLogin("input", "bitwarden.com"),
|
||||
awaitItem(),
|
||||
)
|
||||
}
|
||||
|
@ -106,11 +106,26 @@ class LandingViewModelTest : BaseViewModelTest() {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `RegionOptionSelect should update value of selected region`() = runTest {
|
||||
val inputRegion = LandingState.RegionOption.BITWARDEN_EU
|
||||
val viewModel = LandingViewModel(SavedStateHandle())
|
||||
viewModel.stateFlow.test {
|
||||
awaitItem()
|
||||
viewModel.trySendAction(LandingAction.RegionOptionSelect(inputRegion))
|
||||
assertEquals(
|
||||
DEFAULT_STATE.copy(selectedRegion = LandingState.RegionOption.BITWARDEN_EU),
|
||||
awaitItem(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val DEFAULT_STATE = LandingState(
|
||||
emailInput = "",
|
||||
isContinueButtonEnabled = false,
|
||||
isRememberMeEnabled = false,
|
||||
selectedRegion = LandingState.RegionOption.BITWARDEN_US,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ class LoginScreenTest : BaseComposeTest() {
|
|||
emailAddress = "",
|
||||
isLoginButtonEnabled = false,
|
||||
passwordInput = "",
|
||||
region = "",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -58,6 +59,7 @@ class LoginScreenTest : BaseComposeTest() {
|
|||
emailAddress = "",
|
||||
isLoginButtonEnabled = false,
|
||||
passwordInput = "",
|
||||
region = "",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -82,6 +84,7 @@ class LoginScreenTest : BaseComposeTest() {
|
|||
emailAddress = "",
|
||||
isLoginButtonEnabled = false,
|
||||
passwordInput = "",
|
||||
region = "",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -106,6 +109,7 @@ class LoginScreenTest : BaseComposeTest() {
|
|||
emailAddress = "",
|
||||
isLoginButtonEnabled = false,
|
||||
passwordInput = "",
|
||||
region = "",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -142,6 +146,7 @@ class LoginScreenTest : BaseComposeTest() {
|
|||
emailAddress = "",
|
||||
isLoginButtonEnabled = false,
|
||||
passwordInput = "",
|
||||
region = "",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -167,6 +172,7 @@ class LoginScreenTest : BaseComposeTest() {
|
|||
emailAddress = "",
|
||||
isLoginButtonEnabled = false,
|
||||
passwordInput = "",
|
||||
region = "",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -192,6 +198,7 @@ class LoginScreenTest : BaseComposeTest() {
|
|||
emailAddress = "",
|
||||
isLoginButtonEnabled = false,
|
||||
passwordInput = "",
|
||||
region = "",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ class LoginViewModelTest : BaseViewModelTest() {
|
|||
|
||||
private val savedStateHandle = SavedStateHandle().also {
|
||||
it["email_address"] = "test@gmail.com"
|
||||
it["region_label"] = ""
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
|
@ -262,6 +263,7 @@ class LoginViewModelTest : BaseViewModelTest() {
|
|||
emailAddress = "test@gmail.com",
|
||||
passwordInput = "",
|
||||
isLoginButtonEnabled = true,
|
||||
region = "",
|
||||
)
|
||||
|
||||
private const val LOGIN_RESULT_PATH =
|
||||
|
|
Loading…
Add table
Reference in a new issue