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 3d5af3deb..cf48511b5 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 @@ -42,21 +42,26 @@ class LandingViewModel @Inject constructor( isContinueButtonEnabled = authRepository.rememberedEmailAddress != null, isRememberMeEnabled = authRepository.rememberedEmailAddress != null, selectedEnvironmentType = environmentRepository.environment.type, + selectedEnvironmentLabel = environmentRepository.environment.label, dialog = null, accountSummaries = authRepository.userStateFlow.value?.toAccountSummaries().orEmpty(), ), ) { /** - * Returns the [AccountSummary] from the current state that matches the current email input, - * of `null` if there is no match. + * Returns the [AccountSummary] from the current state that matches the current email input and + * the the current environment, or `null` if there is no match. */ private val matchingAccountSummary: AccountSummary? get() { val currentEmail = state.emailInput + val currentEnvironmentLabel = state.selectedEnvironmentLabel val accountSummaries = state.accountSummaries return accountSummaries - .find { it.email == currentEmail } + .find { + it.email == currentEmail && + it.environmentLabel == currentEnvironmentLabel + } ?.takeUnless { !it.isLoggedIn } } @@ -221,6 +226,7 @@ class LandingViewModel @Inject constructor( mutableStateFlow.update { it.copy( selectedEnvironmentType = action.environment.type, + selectedEnvironmentLabel = action.environment.label, ) } } @@ -248,6 +254,7 @@ data class LandingState( val isContinueButtonEnabled: Boolean, val isRememberMeEnabled: Boolean, val selectedEnvironmentType: Environment.Type, + val selectedEnvironmentLabel: String, val dialog: DialogState?, val accountSummaries: List, ) : Parcelable { 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 a7816cd7c..6d1df86a7 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 @@ -473,6 +473,7 @@ private val DEFAULT_STATE = LandingState( isContinueButtonEnabled = true, isRememberMeEnabled = false, selectedEnvironmentType = Environment.Type.US, + selectedEnvironmentLabel = Environment.Us.label, dialog = null, accountSummaries = emptyList(), ) 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 1eaefad5f..c41623591 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 @@ -196,7 +196,7 @@ class LandingViewModelTest : BaseViewModelTest() { @Suppress("MaxLineLength") @Test - fun `ContinueButtonClick with an email input matching an existing account that is logged in should show the account already added dialog`() { + fun `ContinueButtonClick with an email input matching an existing account on same environment that is logged in should show the account already added dialog`() { val rememberedEmail = "active@bitwarden.com" val activeAccount = UserState.Account( userId = "activeUserId", @@ -246,6 +246,63 @@ class LandingViewModelTest : BaseViewModelTest() { ) } + @Suppress("MaxLineLength") + @Test + fun `ContinueButtonClick with an email input matching an existing account on different environment that is logged in should emit NavigateToLogin`() = + runTest { + val rememberedEmail = "active@bitwarden.com" + val activeAccount = UserState.Account( + userId = "activeUserId", + name = "name", + email = rememberedEmail, + avatarColorHex = "avatarColorHex", + environment = Environment.Us, + isPremium = true, + isLoggedIn = true, + isVaultUnlocked = true, + needsPasswordReset = false, + isBiometricsEnabled = false, + organizations = emptyList(), + needsMasterPassword = false, + trustedDevice = null, + ) + val userState = UserState( + activeUserId = "activeUserId", + accounts = listOf(activeAccount), + ) + val viewModel = createViewModel( + rememberedEmail = rememberedEmail, + userState = userState, + ) + val accountSummaries = userState.toAccountSummaries() + val initialState = DEFAULT_STATE.copy( + emailInput = rememberedEmail, + isContinueButtonEnabled = true, + isRememberMeEnabled = true, + accountSummaries = accountSummaries, + ) + assertEquals( + initialState, + viewModel.stateFlow.value, + ) + + viewModel.eventFlow.test { + viewModel.trySendAction(LandingAction.EnvironmentTypeSelect(Environment.Eu.type)) + assertEquals( + initialState.copy( + selectedEnvironmentLabel = Environment.Eu.label, + selectedEnvironmentType = Environment.Eu.type, + ), + viewModel.stateFlow.value, + ) + viewModel.trySendAction(LandingAction.ContinueButtonClick) + assertEquals( + LandingEvent.NavigateToLogin(rememberedEmail), + awaitItem(), + ) + } + } + @Suppress("MaxLineLength") @Test fun `ContinueButtonClick with an email input matching an existing account that is logged out should emit NavigateToLogin`() = @@ -382,7 +439,10 @@ class LandingViewModelTest : BaseViewModelTest() { awaitItem() viewModel.trySendAction(LandingAction.EnvironmentTypeSelect(inputEnvironmentType)) assertEquals( - DEFAULT_STATE.copy(selectedEnvironmentType = Environment.Type.EU), + DEFAULT_STATE.copy( + selectedEnvironmentType = Environment.Type.EU, + selectedEnvironmentLabel = Environment.Eu.label, + ), awaitItem(), ) } @@ -494,6 +554,7 @@ class LandingViewModelTest : BaseViewModelTest() { isContinueButtonEnabled = false, isRememberMeEnabled = false, selectedEnvironmentType = Environment.Type.US, + selectedEnvironmentLabel = Environment.Us.label, dialog = null, accountSummaries = emptyList(), )