PM-11741 add password modal to root nav for generator shortcut specia… (#3883)

This commit is contained in:
Dave Severns 2024-09-09 11:42:19 -04:00 committed by GitHub
parent c817253760
commit fa2d7e0218
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 117 additions and 1 deletions

View file

@ -47,6 +47,8 @@ import com.x8bit.bitwarden.ui.platform.feature.vaultunlocked.vaultUnlockedGraph
import com.x8bit.bitwarden.ui.platform.theme.NonNullEnterTransitionProvider
import com.x8bit.bitwarden.ui.platform.theme.NonNullExitTransitionProvider
import com.x8bit.bitwarden.ui.platform.theme.RootTransitionProviders
import com.x8bit.bitwarden.ui.tools.feature.generator.model.GeneratorMode
import com.x8bit.bitwarden.ui.tools.feature.generator.navigateToGeneratorModal
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.model.AddSendType
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.navigateToAddSend
import com.x8bit.bitwarden.ui.vault.feature.addedit.navigateToVaultAddEdit
@ -113,6 +115,7 @@ fun RootNavScreen(
is RootNavState.VaultUnlockedForFido2Save,
is RootNavState.VaultUnlockedForFido2Assertion,
is RootNavState.VaultUnlockedForFido2GetCredentials,
is RootNavState.GeneratorShortcut,
-> VAULT_UNLOCKED_GRAPH_ROUTE
}
val currentRoute = navController.currentDestination?.rootLevelRoute()
@ -217,6 +220,11 @@ fun RootNavScreen(
navOptions = rootNavOptions,
)
}
RootNavState.GeneratorShortcut -> {
navController.navigateToVaultUnlockedGraph(rootNavOptions)
navController.navigateToGeneratorModal(mode = GeneratorMode.Modal.Password)
}
}
}
}

View file

@ -131,7 +131,9 @@ class RootNavViewModel @Inject constructor(
)
}
SpecialCircumstance.GeneratorShortcut,
SpecialCircumstance.GeneratorShortcut -> {
RootNavState.GeneratorShortcut
}
SpecialCircumstance.VaultShortcut,
null,
-> RootNavState.VaultUnlocked(activeUserId = userState.activeAccount.userId)
@ -320,6 +322,12 @@ sealed class RootNavState : Parcelable {
*/
@Parcelize
data object ExpiredRegistrationLink : RootNavState()
/**
* App should show the password generator modal.
*/
@Parcelize
data object GeneratorShortcut : RootNavState()
}
/**

View file

@ -225,6 +225,15 @@ class RootNavScreenTest : BaseComposeTest() {
navOptions = expectedNavOptions,
)
}
// Make sure navigating to the generator shortcut works as expected:
rootNavStateFlow.value = RootNavState.GeneratorShortcut
composeTestRule
.runOnIdle {
fakeNavHostController.assertLastNavigation(
route = "generator_modal/password_generator",
)
}
}
}

View file

@ -905,6 +905,97 @@ class RootNavViewModelTest : BaseViewModelTest() {
assertEquals(RootNavState.VaultLocked, viewModel.stateFlow.value)
}
@Suppress("MaxLineLength")
@Test
fun `when there are no accounts but there is a GeneratorShortcut special circumstance the nav state should be Auth`() {
every { authRepository.hasPendingAccountAddition } returns false
specialCircumstanceManager.specialCircumstance =
SpecialCircumstance.GeneratorShortcut
mutableUserStateFlow.tryEmit(null)
val viewModel = createViewModel()
assertEquals(
RootNavState.Auth,
viewModel.stateFlow.value,
)
}
@Suppress("MaxLineLength")
@Test
fun `when the active user has an unlocked vault and there is a GeneratorShortcut special circumstance the nav state should be GeneratorShortcut`() {
every { authRepository.hasPendingAccountAddition } returns true
specialCircumstanceManager.specialCircumstance =
SpecialCircumstance.GeneratorShortcut
mutableUserStateFlow.tryEmit(
UserState(
activeUserId = "activeUserId",
accounts = listOf(
UserState.Account(
userId = "activeUserId",
name = "name",
email = "email",
avatarColorHex = "avatarHexColor",
environment = Environment.Us,
isPremium = true,
isLoggedIn = true,
isVaultUnlocked = true,
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
),
)
val viewModel = createViewModel()
assertEquals(
RootNavState.GeneratorShortcut,
viewModel.stateFlow.value,
)
}
@Suppress("MaxLineLength")
@Test
fun `when the active user has a locked vault and there is a GeneratorShortcut special circumstance the nav state should be VaultLocked`() {
every { authRepository.hasPendingAccountAddition } returns true
specialCircumstanceManager.specialCircumstance =
SpecialCircumstance.GeneratorShortcut
mutableUserStateFlow.tryEmit(
UserState(
activeUserId = "activeUserId",
accounts = listOf(
UserState.Account(
userId = "activeUserId",
name = "name",
email = "email",
avatarColorHex = "avatarColorHex",
environment = Environment.Us,
isPremium = true,
isLoggedIn = true,
isVaultUnlocked = false,
needsPasswordReset = false,
isBiometricsEnabled = false,
organizations = emptyList(),
needsMasterPassword = false,
trustedDevice = null,
hasMasterPassword = true,
isUsingKeyConnector = false,
),
),
),
)
val viewModel = createViewModel()
assertEquals(
RootNavState.VaultLocked,
viewModel.stateFlow.value,
)
}
private fun createViewModel(): RootNavViewModel =
RootNavViewModel(
authRepository = authRepository,