From 2472648434d9dfd48fe34d02298ec50c76a8e4cc Mon Sep 17 00:00:00 2001 From: Brian Yencho Date: Tue, 24 Oct 2023 11:17:10 -0500 Subject: [PATCH] BIT-725: Replace "region" concept with Environment (#152) --- .../data/auth/repository/AuthRepository.kt | 6 --- .../auth/repository/AuthRepositoryImpl.kt | 3 -- .../ui/auth/feature/landing/LandingScreen.kt | 23 +++++---- .../auth/feature/landing/LandingViewModel.kt | 50 +++++++++++-------- .../ui/auth/feature/login/LoginScreen.kt | 4 +- .../ui/auth/feature/login/LoginViewModel.kt | 7 ++- .../auth/feature/landing/LandingScreenTest.kt | 22 +++++--- .../feature/landing/LandingViewModelTest.kt | 15 ++++-- .../ui/auth/feature/login/LoginScreenTest.kt | 15 +++--- .../auth/feature/login/LoginViewModelTest.kt | 50 ++++++++++++++----- 10 files changed, 120 insertions(+), 75 deletions(-) diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/AuthRepository.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/AuthRepository.kt index 2ba4ca7da..db8396529 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/AuthRepository.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/AuthRepository.kt @@ -27,12 +27,6 @@ interface AuthRepository { */ var rememberedEmailAddress: String? - /** - * The currently selected region label (`null` if not set). - */ - // TODO replace this with a more robust selected region object BIT-725 - var selectedRegionLabel: String - /** * Attempt to login with the given email and password. Updated access token will be reflected * in [authStateFlow]. diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryImpl.kt index 55df8bdc5..c50784e09 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryImpl.kt @@ -77,9 +77,6 @@ class AuthRepositoryImpl @Inject constructor( authDiskSource.rememberedEmailAddress = value } - // TODO Handle selected region functionality BIT-725 - override var selectedRegionLabel: String = "bitwarden.us" - override suspend fun login( email: String, password: String, diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingScreen.kt index 7a1598f66..55dc7a026 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingScreen.kt @@ -40,6 +40,7 @@ import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.x8bit.bitwarden.R +import com.x8bit.bitwarden.data.platform.repository.model.Environment import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect import com.x8bit.bitwarden.ui.platform.components.BitwardenBasicDialog import com.x8bit.bitwarden.ui.platform.components.BitwardenFilledButton @@ -132,10 +133,10 @@ fun LandingScreen( Spacer(modifier = Modifier.height(10.dp)) - RegionSelector( - selectedOption = state.selectedRegion, + EnvironmentSelector( + selectedOption = state.selectedEnvironment.type, onOptionSelected = remember(viewModel) { - { viewModel.trySendAction(LandingAction.RegionOptionSelect(it)) } + { viewModel.trySendAction(LandingAction.EnvironmentTypeSelect(it)) } }, modifier = Modifier .semantics { testTag = "RegionSelectorDropdown" } @@ -208,19 +209,19 @@ fun LandingScreen( * 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 onOptionSelected A callback that gets invoked when a region option is selected + * @param selectedOption The currently selected environment option. + * @param onOptionSelected A callback that gets invoked when an environment option is selected * and passes the selected option as an argument. * @param modifier A [Modifier] for the composable. * */ @Composable -private fun RegionSelector( - selectedOption: LandingState.RegionOption, - onOptionSelected: (LandingState.RegionOption) -> Unit, +private fun EnvironmentSelector( + selectedOption: Environment.Type, + onOptionSelected: (Environment.Type) -> Unit, modifier: Modifier, ) { - val options = LandingState.RegionOption.values().toList() + val options = Environment.Type.values() var expanded by remember { mutableStateOf(false) } Box(modifier = modifier) { @@ -238,7 +239,7 @@ private fun RegionSelector( modifier = Modifier.padding(end = 12.dp), ) Text( - text = selectedOption.label, + text = selectedOption.label(), style = MaterialTheme.typography.labelLarge, color = MaterialTheme.colorScheme.primary, modifier = Modifier.padding(end = 8.dp), @@ -256,7 +257,7 @@ private fun RegionSelector( ) { options.forEach { optionString -> DropdownMenuItem( - text = { Text(text = optionString.label) }, + text = { Text(text = optionString.label()) }, onClick = { expanded = false onOptionSelected(optionString) diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingViewModel.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingViewModel.kt index 2203adb90..7a7752c71 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingViewModel.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingViewModel.kt @@ -5,6 +5,8 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import com.x8bit.bitwarden.R import com.x8bit.bitwarden.data.auth.repository.AuthRepository +import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository +import com.x8bit.bitwarden.data.platform.repository.model.Environment import com.x8bit.bitwarden.ui.platform.base.BaseViewModel import com.x8bit.bitwarden.ui.platform.base.util.asText import com.x8bit.bitwarden.ui.platform.base.util.isValidEmail @@ -24,6 +26,7 @@ private const val KEY_STATE = "state" @HiltViewModel class LandingViewModel @Inject constructor( private val authRepository: AuthRepository, + private val environmentRepository: EnvironmentRepository, savedStateHandle: SavedStateHandle, ) : BaseViewModel( initialState = savedStateHandle[KEY_STATE] @@ -31,15 +34,20 @@ class LandingViewModel @Inject constructor( emailInput = authRepository.rememberedEmailAddress.orEmpty(), isContinueButtonEnabled = authRepository.rememberedEmailAddress != null, isRememberMeEnabled = authRepository.rememberedEmailAddress != null, - selectedRegion = LandingState.RegionOption.BITWARDEN_US, + selectedEnvironment = environmentRepository.environment, errorDialogState = BasicDialogState.Hidden, ), ) { init { - // As state updates, write to saved state handle: + // As state updates: + // - write to saved state handle + // - updated selected environment stateFlow - .onEach { savedStateHandle[KEY_STATE] = it } + .onEach { + savedStateHandle[KEY_STATE] = it + environmentRepository.environment = it.selectedEnvironment + } .launchIn(viewModelScope) } @@ -50,7 +58,7 @@ class LandingViewModel @Inject constructor( is LandingAction.ErrorDialogDismiss -> handleErrorDialogDismiss() is LandingAction.RememberMeToggle -> handleRememberMeToggled(action) is LandingAction.EmailInputChanged -> handleEmailInputUpdated(action) - is LandingAction.RegionOptionSelect -> handleRegionSelect(action) + is LandingAction.EnvironmentTypeSelect -> handleEnvironmentTypeSelect(action) } } @@ -82,8 +90,6 @@ class LandingViewModel @Inject constructor( // Update the remembered email address authRepository.rememberedEmailAddress = email.takeUnless { !isRememberMeEnabled } - // Update the selected region selectedRegionLabel - authRepository.selectedRegionLabel = mutableStateFlow.value.selectedRegion.label sendEvent(LandingEvent.NavigateToLogin(email)) } @@ -102,10 +108,21 @@ class LandingViewModel @Inject constructor( mutableStateFlow.update { it.copy(isRememberMeEnabled = action.isChecked) } } - private fun handleRegionSelect(action: LandingAction.RegionOptionSelect) { + private fun handleEnvironmentTypeSelect(action: LandingAction.EnvironmentTypeSelect) { + val environment = when (action.environmentType) { + Environment.Type.US -> Environment.Us + Environment.Type.EU -> Environment.Eu + Environment.Type.SELF_HOSTED -> { + // TODO Show dialog for setting selected environment (BIT-330) + Environment.SelfHosted( + environmentUrlData = Environment.Us.environmentUrlData, + ) + } + } + mutableStateFlow.update { it.copy( - selectedRegion = action.regionOption, + selectedEnvironment = environment, ) } } @@ -119,18 +136,9 @@ data class LandingState( val emailInput: String, val isContinueButtonEnabled: Boolean, val isRememberMeEnabled: Boolean, - val selectedRegion: RegionOption, + val selectedEnvironment: Environment, val errorDialogState: BasicDialogState, -) : 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"), - } -} +) : Parcelable /** * Models events for the landing screen. @@ -185,7 +193,7 @@ sealed class LandingAction { /** * Indicates that the selection from the region drop down has changed. */ - data class RegionOptionSelect( - val regionOption: LandingState.RegionOption, + data class EnvironmentTypeSelect( + val environmentType: Environment.Type, ) : LandingAction() } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreen.kt index 17b64333f..4d711839a 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreen.kt @@ -147,12 +147,12 @@ fun LoginScreen( .padding(bottom = 24.dp), isEnabled = state.isLoginButtonEnabled, ) - // TODO Get the "login target" from a dropdown (BIT-202) + Text( text = stringResource( id = R.string.logging_in_as_x_on_y, state.emailAddress, - state.region, + state.environmentLabel(), ), textAlign = TextAlign.Start, style = MaterialTheme.typography.bodyMedium, diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginViewModel.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginViewModel.kt index 6e4f81ed4..11941ab65 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginViewModel.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginViewModel.kt @@ -11,7 +11,9 @@ import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.model.LoginResult import com.x8bit.bitwarden.data.auth.repository.util.CaptchaCallbackTokenResult import com.x8bit.bitwarden.data.auth.repository.util.generateUriForCaptcha +import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository 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 com.x8bit.bitwarden.ui.platform.components.BasicDialogState import com.x8bit.bitwarden.ui.platform.components.LoadingDialogState @@ -31,6 +33,7 @@ private const val KEY_STATE = "state" @HiltViewModel class LoginViewModel @Inject constructor( private val authRepository: AuthRepository, + private val environmentRepository: EnvironmentRepository, savedStateHandle: SavedStateHandle, ) : BaseViewModel( initialState = savedStateHandle[KEY_STATE] @@ -38,7 +41,7 @@ class LoginViewModel @Inject constructor( emailAddress = LoginArgs(savedStateHandle).emailAddress, isLoginButtonEnabled = true, passwordInput = "", - region = authRepository.selectedRegionLabel, + environmentLabel = environmentRepository.environment.label, loadingDialogState = LoadingDialogState.Hidden, errorDialogState = BasicDialogState.Hidden, captchaToken = LoginArgs(savedStateHandle).captchaToken, @@ -193,7 +196,7 @@ data class LoginState( val passwordInput: String, val emailAddress: String, val captchaToken: String?, - val region: String, + val environmentLabel: Text, val isLoginButtonEnabled: Boolean, val loadingDialogState: LoadingDialogState, val errorDialogState: BasicDialogState, 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 45945e1a8..9f02f2b5a 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 @@ -1,5 +1,6 @@ package com.x8bit.bitwarden.ui.auth.feature.landing +import android.app.Application import androidx.compose.ui.test.assert import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.assertIsEnabled @@ -15,6 +16,8 @@ import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performScrollTo import androidx.compose.ui.test.performTextInput +import androidx.test.core.app.ApplicationProvider +import com.x8bit.bitwarden.data.platform.repository.model.Environment import com.x8bit.bitwarden.ui.platform.base.BaseComposeTest import com.x8bit.bitwarden.ui.platform.base.util.asText import com.x8bit.bitwarden.ui.platform.components.BasicDialogState @@ -29,6 +32,9 @@ import org.junit.Test import org.junit.jupiter.api.Assertions.assertEquals class LandingScreenTest : BaseComposeTest() { + private val resources + get() = ApplicationProvider.getApplicationContext().resources + @Test fun `continue button should be enabled or disabled according to the state`() { val mutableStateFlow = MutableStateFlow(DEFAULT_STATE) @@ -218,8 +224,8 @@ class LandingScreenTest : BaseComposeTest() { } @Test - fun `selecting region should send RegionOptionSelect action`() { - val selectedRegion = LandingState.RegionOption.BITWARDEN_EU + fun `selecting environment should send EnvironmentOptionSelect action`() { + val selectedEnvironment = Environment.Eu val viewModel = mockk(relaxed = true) { every { eventFlow } returns emptyFlow() every { stateFlow } returns MutableStateFlow(DEFAULT_STATE) @@ -234,13 +240,17 @@ class LandingScreenTest : BaseComposeTest() { } // Clicking to open dropdown - composeTestRule.onNodeWithText(LandingState.RegionOption.BITWARDEN_US.label).performClick() + composeTestRule + .onNodeWithText(Environment.Us.label.toString(resources)) + .performClick() // Clicking item from the dropdown menu - composeTestRule.onNodeWithText(selectedRegion.label).performClick() + composeTestRule + .onNodeWithText(selectedEnvironment.label.toString(resources)) + .performClick() verify { - viewModel.trySendAction(LandingAction.RegionOptionSelect(selectedRegion)) + viewModel.trySendAction(LandingAction.EnvironmentTypeSelect(selectedEnvironment.type)) } } @@ -319,7 +329,7 @@ class LandingScreenTest : BaseComposeTest() { emailInput = "", isContinueButtonEnabled = true, isRememberMeEnabled = false, - selectedRegion = LandingState.RegionOption.BITWARDEN_US, + selectedEnvironment = Environment.Us, errorDialogState = BasicDialogState.Hidden, ) } diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingViewModelTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingViewModelTest.kt index 2832f116e..c07b50a6c 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingViewModelTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingViewModelTest.kt @@ -3,6 +3,7 @@ package com.x8bit.bitwarden.ui.auth.feature.landing import androidx.lifecycle.SavedStateHandle import app.cash.turbine.test import com.x8bit.bitwarden.R +import com.x8bit.bitwarden.data.platform.repository.model.Environment import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest import com.x8bit.bitwarden.ui.platform.base.util.asText import com.x8bit.bitwarden.ui.platform.components.BasicDialogState @@ -145,14 +146,14 @@ class LandingViewModelTest : BaseViewModelTest() { } @Test - fun `RegionOptionSelect should update value of selected region`() = runTest { - val inputRegion = LandingState.RegionOption.BITWARDEN_EU + fun `EnvironmentTypeSelect should update value of selected region`() = runTest { + val inputEnvironment = Environment.Eu val viewModel = createViewModel() viewModel.stateFlow.test { awaitItem() - viewModel.trySendAction(LandingAction.RegionOptionSelect(inputRegion)) + viewModel.trySendAction(LandingAction.EnvironmentTypeSelect(inputEnvironment.type)) assertEquals( - DEFAULT_STATE.copy(selectedRegion = LandingState.RegionOption.BITWARDEN_EU), + DEFAULT_STATE.copy(selectedEnvironment = Environment.Eu), awaitItem(), ) } @@ -162,11 +163,15 @@ class LandingViewModelTest : BaseViewModelTest() { private fun createViewModel( rememberedEmail: String? = null, + environment: Environment = Environment.Us, savedStateHandle: SavedStateHandle = SavedStateHandle(), ): LandingViewModel = LandingViewModel( authRepository = mockk(relaxed = true) { every { rememberedEmailAddress } returns rememberedEmail }, + environmentRepository = mockk(relaxed = true) { + every { this@mockk.environment } returns environment + }, savedStateHandle = savedStateHandle, ) @@ -177,7 +182,7 @@ class LandingViewModelTest : BaseViewModelTest() { emailInput = "", isContinueButtonEnabled = false, isRememberMeEnabled = false, - selectedRegion = LandingState.RegionOption.BITWARDEN_US, + selectedEnvironment = Environment.Us, errorDialogState = BasicDialogState.Hidden, ) } 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 60562a669..690b5d3ae 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 @@ -14,6 +14,7 @@ import androidx.compose.ui.test.performScrollTo import androidx.compose.ui.test.performTextInput import com.x8bit.bitwarden.ui.platform.base.BaseComposeTest import com.x8bit.bitwarden.ui.platform.base.util.IntentHandler +import com.x8bit.bitwarden.ui.platform.base.util.asText import com.x8bit.bitwarden.ui.platform.components.BasicDialogState import com.x8bit.bitwarden.ui.platform.components.LoadingDialogState import io.mockk.every @@ -37,7 +38,7 @@ class LoginScreenTest : BaseComposeTest() { captchaToken = null, isLoginButtonEnabled = false, passwordInput = "", - region = "", + environmentLabel = "".asText(), loadingDialogState = LoadingDialogState.Hidden, errorDialogState = BasicDialogState.Hidden, ), @@ -65,7 +66,7 @@ class LoginScreenTest : BaseComposeTest() { captchaToken = null, isLoginButtonEnabled = false, passwordInput = "", - region = "", + environmentLabel = "".asText(), loadingDialogState = LoadingDialogState.Hidden, errorDialogState = BasicDialogState.Hidden, ), @@ -93,7 +94,7 @@ class LoginScreenTest : BaseComposeTest() { captchaToken = null, isLoginButtonEnabled = false, passwordInput = "", - region = "", + environmentLabel = "".asText(), loadingDialogState = LoadingDialogState.Hidden, errorDialogState = BasicDialogState.Hidden, ), @@ -121,7 +122,7 @@ class LoginScreenTest : BaseComposeTest() { captchaToken = null, isLoginButtonEnabled = false, passwordInput = "", - region = "", + environmentLabel = "".asText(), loadingDialogState = LoadingDialogState.Hidden, errorDialogState = BasicDialogState.Hidden, ), @@ -161,7 +162,7 @@ class LoginScreenTest : BaseComposeTest() { captchaToken = null, isLoginButtonEnabled = false, passwordInput = "", - region = "", + environmentLabel = "".asText(), loadingDialogState = LoadingDialogState.Hidden, errorDialogState = BasicDialogState.Hidden, ), @@ -190,7 +191,7 @@ class LoginScreenTest : BaseComposeTest() { captchaToken = null, isLoginButtonEnabled = false, passwordInput = "", - region = "", + environmentLabel = "".asText(), loadingDialogState = LoadingDialogState.Hidden, errorDialogState = BasicDialogState.Hidden, ), @@ -219,7 +220,7 @@ class LoginScreenTest : BaseComposeTest() { captchaToken = null, isLoginButtonEnabled = false, passwordInput = "", - region = "", + environmentLabel = "".asText(), loadingDialogState = LoadingDialogState.Hidden, errorDialogState = BasicDialogState.Hidden, ), diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginViewModelTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginViewModelTest.kt index 36370df52..00bdabeb3 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginViewModelTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginViewModelTest.kt @@ -8,6 +8,8 @@ import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.auth.repository.model.LoginResult import com.x8bit.bitwarden.data.auth.repository.util.CaptchaCallbackTokenResult import com.x8bit.bitwarden.data.auth.repository.util.generateUriForCaptcha +import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository +import com.x8bit.bitwarden.data.platform.repository.model.Environment import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest import com.x8bit.bitwarden.ui.platform.base.util.asText import com.x8bit.bitwarden.ui.platform.components.BasicDialogState @@ -29,7 +31,6 @@ class LoginViewModelTest : BaseViewModelTest() { private val savedStateHandle = SavedStateHandle().also { it["email_address"] = "test@gmail.com" - it["region_label"] = "" } @BeforeEach @@ -47,7 +48,9 @@ class LoginViewModelTest : BaseViewModelTest() { val viewModel = LoginViewModel( authRepository = mockk { every { captchaTokenResultFlow } returns flowOf() - every { selectedRegionLabel } returns "bitwarden.us" + }, + environmentRepository = mockk { + every { environment } returns Environment.Us }, savedStateHandle = savedStateHandle, ) @@ -72,6 +75,9 @@ class LoginViewModelTest : BaseViewModelTest() { authRepository = mockk { every { captchaTokenResultFlow } returns flowOf() }, + environmentRepository = mockk { + every { environment } returns Environment.Us + }, savedStateHandle = handle, ) viewModel.stateFlow.test { @@ -84,7 +90,9 @@ class LoginViewModelTest : BaseViewModelTest() { val viewModel = LoginViewModel( authRepository = mockk { every { captchaTokenResultFlow } returns flowOf() - every { selectedRegionLabel } returns "bitwarden.us" + }, + environmentRepository = mockk { + every { environment } returns Environment.Us }, savedStateHandle = savedStateHandle, ) @@ -108,10 +116,13 @@ class LoginViewModelTest : BaseViewModelTest() { ) } returns LoginResult.Error(errorMessage = "mock_error") every { captchaTokenResultFlow } returns flowOf() - every { selectedRegionLabel } returns "bitwarden.us" + } + val environmentRepository = mockk { + every { environment } returns Environment.Us } val viewModel = LoginViewModel( authRepository = authRepository, + environmentRepository = environmentRepository, savedStateHandle = savedStateHandle, ) viewModel.stateFlow.test { @@ -148,10 +159,12 @@ class LoginViewModelTest : BaseViewModelTest() { login("test@gmail.com", "", captchaToken = null) } returns LoginResult.Success every { captchaTokenResultFlow } returns flowOf() - every { selectedRegionLabel } returns "bitwarden.us" } val viewModel = LoginViewModel( authRepository = authRepository, + environmentRepository = mockk { + every { environment } returns Environment.Us + }, savedStateHandle = savedStateHandle, ) viewModel.stateFlow.test { @@ -186,10 +199,12 @@ class LoginViewModelTest : BaseViewModelTest() { coEvery { login("test@gmail.com", "", captchaToken = null) } returns LoginResult.CaptchaRequired(captchaId = "mock_captcha_id") every { captchaTokenResultFlow } returns flowOf() - every { selectedRegionLabel } returns "bitwarden.us" } val viewModel = LoginViewModel( authRepository = authRepository, + environmentRepository = mockk { + every { environment } returns Environment.Us + }, savedStateHandle = savedStateHandle, ) viewModel.eventFlow.test { @@ -207,7 +222,9 @@ class LoginViewModelTest : BaseViewModelTest() { val viewModel = LoginViewModel( authRepository = mockk { every { captchaTokenResultFlow } returns flowOf() - every { selectedRegionLabel } returns "bitwarden.us" + }, + environmentRepository = mockk { + every { environment } returns Environment.Us }, savedStateHandle = savedStateHandle, ) @@ -226,7 +243,9 @@ class LoginViewModelTest : BaseViewModelTest() { val viewModel = LoginViewModel( authRepository = mockk { every { captchaTokenResultFlow } returns flowOf() - every { selectedRegionLabel } returns "bitwarden.us" + }, + environmentRepository = mockk { + every { environment } returns Environment.Us }, savedStateHandle = savedStateHandle, ) @@ -245,7 +264,9 @@ class LoginViewModelTest : BaseViewModelTest() { val viewModel = LoginViewModel( authRepository = mockk { every { captchaTokenResultFlow } returns flowOf() - every { selectedRegionLabel } returns "bitwarden.us" + }, + environmentRepository = mockk { + every { environment } returns Environment.Us }, savedStateHandle = savedStateHandle, ) @@ -264,7 +285,9 @@ class LoginViewModelTest : BaseViewModelTest() { val viewModel = LoginViewModel( authRepository = mockk { every { captchaTokenResultFlow } returns flowOf() - every { selectedRegionLabel } returns "bitwarden.us" + }, + environmentRepository = mockk { + every { environment } returns Environment.Us }, savedStateHandle = savedStateHandle, ) @@ -283,7 +306,6 @@ class LoginViewModelTest : BaseViewModelTest() { every { captchaTokenResultFlow } returns flowOf( CaptchaCallbackTokenResult.Success("token"), ) - every { selectedRegionLabel } returns "bitwarden.us" coEvery { login( "test@gmail.com", @@ -292,8 +314,12 @@ class LoginViewModelTest : BaseViewModelTest() { ) } returns LoginResult.Success } + val environmentRepository = mockk { + every { environment } returns Environment.Us + } LoginViewModel( authRepository = authRepository, + environmentRepository = environmentRepository, savedStateHandle = savedStateHandle, ) coVerify { @@ -306,7 +332,7 @@ class LoginViewModelTest : BaseViewModelTest() { emailAddress = "test@gmail.com", passwordInput = "", isLoginButtonEnabled = true, - region = "bitwarden.us", + environmentLabel = Environment.Us.type.label, loadingDialogState = LoadingDialogState.Hidden, errorDialogState = BasicDialogState.Hidden, captchaToken = null,