diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/vaultunlockednavbar/VaultUnlockedNavBarScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/vaultunlockednavbar/VaultUnlockedNavBarScreen.kt index ea0e8c0521..bad2248170 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/vaultunlockednavbar/VaultUnlockedNavBarScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/vaultunlockednavbar/VaultUnlockedNavBarScreen.kt @@ -31,6 +31,7 @@ import androidx.compose.ui.res.stringResource import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import androidx.navigation.NavDestination.Companion.hierarchy +import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.NavHostController import androidx.navigation.NavOptions import androidx.navigation.compose.NavHost @@ -53,9 +54,9 @@ import com.x8bit.bitwarden.ui.tools.feature.generator.navigateToGenerator import com.x8bit.bitwarden.ui.tools.feature.send.SEND_GRAPH_ROUTE import com.x8bit.bitwarden.ui.tools.feature.send.navigateToSend import com.x8bit.bitwarden.ui.tools.feature.send.sendGraph -import com.x8bit.bitwarden.ui.vault.feature.vault.VAULT_ROUTE -import com.x8bit.bitwarden.ui.vault.feature.vault.navigateToVault -import com.x8bit.bitwarden.ui.vault.feature.vault.vaultDestination +import com.x8bit.bitwarden.ui.vault.feature.vault.VAULT_GRAPH_ROUTE +import com.x8bit.bitwarden.ui.vault.feature.vault.navigateToVaultGraph +import com.x8bit.bitwarden.ui.vault.feature.vault.vaultGraph import kotlinx.parcelize.Parcelize /** @@ -76,7 +77,7 @@ fun VaultUnlockedNavBarScreen( val navOptions = vaultUnlockedNavBarScreenNavOptions() when (event) { VaultUnlockedNavBarEvent.NavigateToVaultScreen -> { - navigateToVault(navOptions) + navigateToVaultGraph(navOptions) } VaultUnlockedNavBarEvent.NavigateToSendScreen -> { @@ -170,7 +171,7 @@ private fun VaultUnlockedNavBarScaffold( // - consume the IME insets. NavHost( navController = navController, - startDestination = VAULT_ROUTE, + startDestination = VAULT_GRAPH_ROUTE, modifier = Modifier .consumeWindowInsets(WindowInsets.navigationBars) .consumeWindowInsets(WindowInsets.ime) @@ -180,10 +181,9 @@ private fun VaultUnlockedNavBarScaffold( popEnterTransition = RootTransitionProviders.Enter.fadeIn, popExitTransition = RootTransitionProviders.Exit.fadeOut, ) { - vaultDestination( - onNavigateToVaultAddItemScreen = { - navigateToVaultAddItem() - }, + vaultGraph( + navController = navController, + onNavigateToVaultAddItemScreen = navigateToVaultAddItem, onNavigateToVaultItemScreen = onNavigateToVaultItem, onNavigateToVaultEditItemScreen = onNavigateToVaultEditItem, onDimBottomNavBarRequest = { shouldDim -> @@ -339,7 +339,7 @@ private sealed class VaultUnlockedNavBarTab : Parcelable { override val iconRes get() = R.drawable.ic_vault override val labelRes get() = R.string.my_vault override val contentDescriptionRes get() = R.string.my_vault - override val route get() = VAULT_ROUTE + override val route get() = VAULT_GRAPH_ROUTE } /** @@ -360,7 +360,7 @@ private sealed class VaultUnlockedNavBarTab : Parcelable { */ private fun NavController.vaultUnlockedNavBarScreenNavOptions(): NavOptions = navOptions { - popUpTo(graph.startDestinationId) { + popUpTo(graph.findStartDestination().id) { saveState = true } launchSingleTop = true diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingNavigation.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingNavigation.kt new file mode 100644 index 0000000000..575b9ebf2b --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingNavigation.kt @@ -0,0 +1,127 @@ +package com.x8bit.bitwarden.ui.vault.feature.itemlisting + +import androidx.lifecycle.SavedStateHandle +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavOptions +import androidx.navigation.NavType +import androidx.navigation.compose.composable +import androidx.navigation.navArgument +import com.x8bit.bitwarden.ui.platform.theme.TransitionProviders +import com.x8bit.bitwarden.ui.vault.model.VaultItemListingType + +private const val CARD: String = "card" +private const val FOLDER: String = "folder" +private const val IDENTITY: String = "identity" +private const val LOGIN: String = "login" +private const val SECURE_NOTE: String = "secure_note" +private const val TRASH: String = "trash" +private const val VAULT_ITEM_LISTING_PREFIX: String = "vault_item_listing" +private const val VAULT_ITEM_LISTING_TYPE: String = "vault_item_listing_type" +private const val ID: String = "id" +private const val VAULT_ITEM_LISTING_ROUTE: String = + "$VAULT_ITEM_LISTING_PREFIX/{$VAULT_ITEM_LISTING_TYPE}" + + "?$ID={$ID}" + +/** + * Class to retrieve vault item listing arguments from the [SavedStateHandle]. + */ +class VaultItemListingArgs( + val vaultItemListingType: VaultItemListingType, +) { + constructor(savedStateHandle: SavedStateHandle) : this( + vaultItemListingType = determineVaultItemListingType( + vaultItemListingTypeString = checkNotNull( + savedStateHandle[VAULT_ITEM_LISTING_TYPE], + ) as String, + id = savedStateHandle[ID], + ), + ) +} + +/** + * Add the [VaultItemListingScreen] to the nav graph. + */ +fun NavGraphBuilder.vaultItemListingDestination( + onNavigateBack: () -> Unit, + onNavigateToVaultItemScreen: (id: String) -> Unit, + onNavigateToVaultAddItemScreen: () -> Unit, +) { + composable( + route = VAULT_ITEM_LISTING_ROUTE, + arguments = listOf( + navArgument( + name = VAULT_ITEM_LISTING_TYPE, + builder = { type = NavType.StringType }, + ), + navArgument( + name = ID, + builder = { + type = NavType.StringType + nullable = true + }, + ), + ), + enterTransition = TransitionProviders.Enter.pushLeft, + exitTransition = TransitionProviders.Exit.pushLeft, + popEnterTransition = TransitionProviders.Enter.pushLeft, + popExitTransition = TransitionProviders.Exit.pushRight, + ) { + VaultItemListingScreen( + onNavigateBack = onNavigateBack, + onNavigateToVaultItem = onNavigateToVaultItemScreen, + onNavigateToVaultAddItemScreen = onNavigateToVaultAddItemScreen, + ) + } +} + +/** + * Navigate to the [VaultItemListingScreen]. + */ +fun NavController.navigateToVaultItemListing( + vaultItemListingType: VaultItemListingType, + navOptions: NavOptions? = null, +) { + navigate( + route = "$VAULT_ITEM_LISTING_PREFIX/${vaultItemListingType.toTypeString()}" + + "?$ID=${vaultItemListingType.toIdOrNull()}", + navOptions = navOptions, + ) +} + +private fun VaultItemListingType.toTypeString(): String { + return when (this) { + is VaultItemListingType.Card -> CARD + is VaultItemListingType.Folder -> FOLDER + is VaultItemListingType.Identity -> IDENTITY + is VaultItemListingType.Login -> LOGIN + is VaultItemListingType.SecureNote -> SECURE_NOTE + is VaultItemListingType.Trash -> TRASH + } +} + +private fun VaultItemListingType.toIdOrNull(): String? = + when (this) { + is VaultItemListingType.Folder -> folderId + is VaultItemListingType.Card -> null + is VaultItemListingType.Identity -> null + is VaultItemListingType.Login -> null + is VaultItemListingType.SecureNote -> null + is VaultItemListingType.Trash -> null + } + +private fun determineVaultItemListingType( + vaultItemListingTypeString: String, + id: String?, +): VaultItemListingType { + return when (vaultItemListingTypeString) { + LOGIN -> VaultItemListingType.Login + CARD -> VaultItemListingType.Card + IDENTITY -> VaultItemListingType.Identity + SECURE_NOTE -> VaultItemListingType.SecureNote + TRASH -> VaultItemListingType.Trash + FOLDER -> VaultItemListingType.Folder(folderId = id) + // This should never occur, vaultItemListingTypeString must match + else -> throw IllegalStateException() + } +} diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingScreen.kt new file mode 100644 index 0000000000..37847f711c --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingScreen.kt @@ -0,0 +1,27 @@ +package com.x8bit.bitwarden.ui.vault.feature.itemlisting + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier + +/** + * Displays the vault item listing screen. + */ +@Composable +fun VaultItemListingScreen( + onNavigateBack: () -> Unit, + onNavigateToVaultItem: (id: String) -> Unit, + onNavigateToVaultAddItemScreen: () -> Unit, +) { + Column( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Text(text = "Listing Screen") + } +} diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultGraphNavigation.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultGraphNavigation.kt new file mode 100644 index 0000000000..8ca327c6d0 --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultGraphNavigation.kt @@ -0,0 +1,46 @@ +package com.x8bit.bitwarden.ui.vault.feature.vault + +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavOptions +import androidx.navigation.navigation +import com.x8bit.bitwarden.ui.vault.feature.itemlisting.navigateToVaultItemListing +import com.x8bit.bitwarden.ui.vault.feature.itemlisting.vaultItemListingDestination + +const val VAULT_GRAPH_ROUTE: String = "vault_graph" + +/** + * Add vault destinations to the nav graph. + */ +fun NavGraphBuilder.vaultGraph( + navController: NavController, + onNavigateToVaultAddItemScreen: () -> Unit, + onNavigateToVaultItemScreen: (vaultItemId: String) -> Unit, + onNavigateToVaultEditItemScreen: (vaultItemId: String) -> Unit, + onDimBottomNavBarRequest: (shouldDim: Boolean) -> Unit, +) { + navigation( + route = VAULT_GRAPH_ROUTE, + startDestination = VAULT_ROUTE, + ) { + vaultDestination( + onNavigateToVaultAddItemScreen = onNavigateToVaultAddItemScreen, + onNavigateToVaultItemScreen = onNavigateToVaultItemScreen, + onNavigateToVaultEditItemScreen = onNavigateToVaultEditItemScreen, + onNavigateToVaultItemListingScreen = { navController.navigateToVaultItemListing(it) }, + onDimBottomNavBarRequest = onDimBottomNavBarRequest, + ) + vaultItemListingDestination( + onNavigateBack = { navController.popBackStack() }, + onNavigateToVaultItemScreen = onNavigateToVaultItemScreen, + onNavigateToVaultAddItemScreen = onNavigateToVaultAddItemScreen, + ) + } +} + +/** + * Navigate to the vault graph. + */ +fun NavController.navigateToVaultGraph(navOptions: NavOptions? = null) { + navigate(VAULT_GRAPH_ROUTE, navOptions) +} diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultNavigation.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultNavigation.kt index 3f1c92b114..3d27a6fff4 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultNavigation.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultNavigation.kt @@ -4,6 +4,8 @@ import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.NavOptions import androidx.navigation.compose.composable +import com.x8bit.bitwarden.ui.platform.theme.TransitionProviders +import com.x8bit.bitwarden.ui.vault.model.VaultItemListingType const val VAULT_ROUTE: String = "vault" @@ -14,13 +16,21 @@ fun NavGraphBuilder.vaultDestination( onNavigateToVaultAddItemScreen: () -> Unit, onNavigateToVaultItemScreen: (vaultItemId: String) -> Unit, onNavigateToVaultEditItemScreen: (vaultItemId: String) -> Unit, + onNavigateToVaultItemListingScreen: (vaultItemType: VaultItemListingType) -> Unit, onDimBottomNavBarRequest: (shouldDim: Boolean) -> Unit, ) { - composable(VAULT_ROUTE) { + composable( + route = VAULT_ROUTE, + enterTransition = TransitionProviders.Enter.stay, + exitTransition = TransitionProviders.Exit.pushLeft, + popEnterTransition = TransitionProviders.Enter.pushRight, + popExitTransition = TransitionProviders.Exit.fadeOut, + ) { VaultScreen( onNavigateToVaultAddItemScreen = onNavigateToVaultAddItemScreen, onNavigateToVaultItemScreen = onNavigateToVaultItemScreen, onNavigateToVaultEditItemScreen = onNavigateToVaultEditItemScreen, + onNavigateToVaultItemListingScreen = onNavigateToVaultItemListingScreen, onDimBottomNavBarRequest = onDimBottomNavBarRequest, ) } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreen.kt index 2a60246b54..221d0f44dd 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreen.kt @@ -35,6 +35,7 @@ import com.x8bit.bitwarden.ui.platform.components.BitwardenOverflowActionItem import com.x8bit.bitwarden.ui.platform.components.BitwardenScaffold import com.x8bit.bitwarden.ui.platform.components.BitwardenSearchActionItem import com.x8bit.bitwarden.ui.platform.components.model.AccountSummary +import com.x8bit.bitwarden.ui.vault.model.VaultItemListingType import kotlinx.collections.immutable.toImmutableList /** @@ -47,6 +48,7 @@ fun VaultScreen( onNavigateToVaultAddItemScreen: () -> Unit, onNavigateToVaultItemScreen: (vaultItemId: String) -> Unit, onNavigateToVaultEditItemScreen: (vaultItemId: String) -> Unit, + onNavigateToVaultItemListingScreen: (vaultItemType: VaultItemListingType) -> Unit, onDimBottomNavBarRequest: (shouldDim: Boolean) -> Unit, ) { val context = LocalContext.current @@ -65,40 +67,8 @@ fun VaultScreen( is VaultEvent.NavigateToEditVaultItem -> onNavigateToVaultEditItemScreen(event.itemId) - VaultEvent.NavigateToCardGroup -> { - Toast - .makeText(context, "Navigate to card type screen.", Toast.LENGTH_SHORT) - .show() - } - - is VaultEvent.NavigateToFolder -> { - Toast - .makeText(context, "Navigate to folder screen.", Toast.LENGTH_SHORT) - .show() - } - - VaultEvent.NavigateToIdentityGroup -> { - Toast - .makeText(context, "Navigate to identity type screen.", Toast.LENGTH_SHORT) - .show() - } - - VaultEvent.NavigateToLoginGroup -> { - Toast - .makeText(context, "Navigate to login type screen.", Toast.LENGTH_SHORT) - .show() - } - - VaultEvent.NavigateToSecureNotesGroup -> { - Toast - .makeText(context, "Navigate to secure notes type screen.", Toast.LENGTH_SHORT) - .show() - } - - VaultEvent.NavigateToTrash -> { - Toast - .makeText(context, "Navigate to trash screen.", Toast.LENGTH_SHORT) - .show() + is VaultEvent.NavigateToItemListing -> { + onNavigateToVaultItemListingScreen(event.itemListingType) } is VaultEvent.ShowToast -> { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModel.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModel.kt index b425ab50ed..2c50a6ea34 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModel.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModel.kt @@ -21,6 +21,7 @@ import com.x8bit.bitwarden.ui.vault.feature.vault.util.initials import com.x8bit.bitwarden.ui.vault.feature.vault.util.toAccountSummaries import com.x8bit.bitwarden.ui.vault.feature.vault.util.toActiveAccountSummary import com.x8bit.bitwarden.ui.vault.feature.vault.util.toViewState +import com.x8bit.bitwarden.ui.vault.model.VaultItemListingType import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.delay import kotlinx.coroutines.flow.launchIn @@ -102,19 +103,25 @@ class VaultViewModel @Inject constructor( } private fun handleCardClick() { - sendEvent(VaultEvent.NavigateToCardGroup) + sendEvent( + VaultEvent.NavigateToItemListing(VaultItemListingType.Card), + ) } private fun handleFolderItemClick(action: VaultAction.FolderClick) { - sendEvent(VaultEvent.NavigateToFolder(action.folderItem.id)) + sendEvent( + VaultEvent.NavigateToItemListing( + VaultItemListingType.Folder(action.folderItem.id), + ), + ) } private fun handleIdentityClick() { - sendEvent(VaultEvent.NavigateToIdentityGroup) + sendEvent(VaultEvent.NavigateToItemListing(VaultItemListingType.Identity)) } private fun handleLoginClick() { - sendEvent(VaultEvent.NavigateToLoginGroup) + sendEvent(VaultEvent.NavigateToItemListing(VaultItemListingType.Login)) } private fun handleSearchIconClick() { @@ -137,11 +144,11 @@ class VaultViewModel @Inject constructor( } private fun handleTrashClick() { - sendEvent(VaultEvent.NavigateToTrash) + sendEvent(VaultEvent.NavigateToItemListing(VaultItemListingType.Trash)) } private fun handleSecureNoteClick() { - sendEvent(VaultEvent.NavigateToSecureNotesGroup) + sendEvent(VaultEvent.NavigateToItemListing(VaultItemListingType.SecureNote)) } private fun handleVaultItemClick(action: VaultAction.VaultItemClick) { @@ -427,37 +434,12 @@ sealed class VaultEvent { ) : VaultEvent() /** - * Navigate to the card group screen. + * Navigate to the item listing screen. */ - data object NavigateToCardGroup : VaultEvent() - - /** - * Navigate to the folder screen. - */ - data class NavigateToFolder( - val folderId: String?, + data class NavigateToItemListing( + val itemListingType: VaultItemListingType, ) : VaultEvent() - /** - * Navigate to the identity group screen. - */ - data object NavigateToIdentityGroup : VaultEvent() - - /** - * Navigate to the login group screen. - */ - data object NavigateToLoginGroup : VaultEvent() - - /** - * Navigate to the trash screen. - */ - data object NavigateToTrash : VaultEvent() - - /** - * Navigate to the secure notes group screen. - */ - data object NavigateToSecureNotesGroup : VaultEvent() - /** * Show a toast with the given [message]. */ diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/model/VaultItemListingType.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/model/VaultItemListingType.kt new file mode 100644 index 0000000000..70f3d7ea79 --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/model/VaultItemListingType.kt @@ -0,0 +1,39 @@ +package com.x8bit.bitwarden.ui.vault.model + +/** + * Represents different types of listing that can be viewed. + */ +sealed class VaultItemListingType { + + /** + * A Login listing. + */ + data object Login : VaultItemListingType() + + /** + * An Identity listing. + */ + data object Identity : VaultItemListingType() + + /** + * A Secure Note listing. + */ + data object SecureNote : VaultItemListingType() + + /** + * A Card listing. + */ + data object Card : VaultItemListingType() + + /** + * A Trash listing. + */ + data object Trash : VaultItemListingType() + + /** + * A Folder listing. + * + * @param folderId the id of the folder, a null value indicates a, "no folder" grouping. + */ + data class Folder(val folderId: String?) : VaultItemListingType() +} diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/base/FakeNavHostController.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/base/FakeNavHostController.kt index 5826e3f388..fee68d66d7 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/base/FakeNavHostController.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/base/FakeNavHostController.kt @@ -69,6 +69,9 @@ class FakeNavHostController : NavHostController(context = mockk()) { mockk().apply { every { id } returns graphId every { startDestinationId } returns graphId + every { + findNode(graphId) + } returns mockk { every { id } returns graphId } } override var graph: NavGraph diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/vaultunlockednavbar/VaultUnlockedNavBarScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/vaultunlockednavbar/VaultUnlockedNavBarScreenTest.kt index b0e1b3312a..31bdb555dc 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/vaultunlockednavbar/VaultUnlockedNavBarScreenTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/vaultunlockednavbar/VaultUnlockedNavBarScreenTest.kt @@ -64,11 +64,11 @@ class VaultUnlockedNavBarScreenTest : BaseComposeTest() { onNavigateToDeleteAccount = {}, ) } - runOnIdle { fakeNavHostController.assertCurrentRoute("vault") } + runOnIdle { fakeNavHostController.assertCurrentRoute("vault_graph") } vaultUnlockedNavBarEventFlow.tryEmit(VaultUnlockedNavBarEvent.NavigateToVaultScreen) runOnIdle { fakeNavHostController.assertLastNavigation( - route = "vault", + route = "vault_graph", navOptions = expectedNavOptions, ) } @@ -115,7 +115,7 @@ class VaultUnlockedNavBarScreenTest : BaseComposeTest() { onNavigateToDeleteAccount = {}, ) } - runOnIdle { fakeNavHostController.assertCurrentRoute("vault") } + runOnIdle { fakeNavHostController.assertCurrentRoute("vault_graph") } vaultUnlockedNavBarEventFlow.tryEmit(VaultUnlockedNavBarEvent.NavigateToSendScreen) runOnIdle { fakeNavHostController.assertLastNavigation( @@ -166,7 +166,7 @@ class VaultUnlockedNavBarScreenTest : BaseComposeTest() { onNavigateToDeleteAccount = {}, ) } - runOnIdle { fakeNavHostController.assertCurrentRoute("vault") } + runOnIdle { fakeNavHostController.assertCurrentRoute("vault_graph") } vaultUnlockedNavBarEventFlow.tryEmit(VaultUnlockedNavBarEvent.NavigateToGeneratorScreen) runOnIdle { fakeNavHostController.assertLastNavigation( @@ -217,7 +217,7 @@ class VaultUnlockedNavBarScreenTest : BaseComposeTest() { onNavigateToDeleteAccount = {}, ) } - runOnIdle { fakeNavHostController.assertCurrentRoute("vault") } + runOnIdle { fakeNavHostController.assertCurrentRoute("vault_graph") } vaultUnlockedNavBarEventFlow.tryEmit(VaultUnlockedNavBarEvent.NavigateToSettingsScreen) runOnIdle { fakeNavHostController.assertLastNavigation( diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreenTest.kt index 7e3f64fc2b..31252dffb8 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreenTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreenTest.kt @@ -13,6 +13,7 @@ import androidx.compose.ui.test.performScrollToNode import com.x8bit.bitwarden.ui.platform.base.BaseComposeTest import com.x8bit.bitwarden.ui.platform.base.util.asText import com.x8bit.bitwarden.ui.platform.components.model.AccountSummary +import com.x8bit.bitwarden.ui.vault.model.VaultItemListingType import io.mockk.every import io.mockk.mockk import io.mockk.verify @@ -31,6 +32,7 @@ class VaultScreenTest : BaseComposeTest() { private var onNavigateToVaultAddItemScreenCalled = false private var onNavigateToVaultItemId: String? = null private var onNavigateToVaultEditItemId: String? = null + private var onNavigateToVaultItemListingType: VaultItemListingType? = null private var onDimBottomNavBarRequestCalled = false private val mutableEventFlow = MutableSharedFlow( @@ -50,6 +52,7 @@ class VaultScreenTest : BaseComposeTest() { onNavigateToVaultAddItemScreen = { onNavigateToVaultAddItemScreenCalled = true }, onNavigateToVaultItemScreen = { onNavigateToVaultItemId = it }, onNavigateToVaultEditItemScreen = { onNavigateToVaultEditItemId = it }, + onNavigateToVaultItemListingScreen = { onNavigateToVaultItemListingType = it }, onDimBottomNavBarRequest = { onDimBottomNavBarRequestCalled = true }, ) } @@ -134,6 +137,45 @@ class VaultScreenTest : BaseComposeTest() { assertEquals(id, onNavigateToVaultEditItemId) } + @Test + fun `NavigateNavigateToCardGroup event should call onNavigateToVaultItemListingType`() { + mutableEventFlow.tryEmit(VaultEvent.NavigateToItemListing(VaultItemListingType.Card)) + assertEquals(VaultItemListingType.Card, onNavigateToVaultItemListingType) + } + + @Test + fun `NavigateToIdentityGroup event should call onNavigateToVaultItemListingType`() { + mutableEventFlow.tryEmit(VaultEvent.NavigateToItemListing(VaultItemListingType.Identity)) + assertEquals(VaultItemListingType.Identity, onNavigateToVaultItemListingType) + } + + @Test + fun `NavigateToLoginGroup event should call onNavigateToVaultItemListingType`() { + mutableEventFlow.tryEmit(VaultEvent.NavigateToItemListing(VaultItemListingType.Login)) + assertEquals(VaultItemListingType.Login, onNavigateToVaultItemListingType) + } + + @Test + fun `NavigateToSecureNotesGroup event should call onNavigateToVaultItemListingType`() { + mutableEventFlow.tryEmit(VaultEvent.NavigateToItemListing(VaultItemListingType.SecureNote)) + assertEquals(VaultItemListingType.SecureNote, onNavigateToVaultItemListingType) + } + + @Test + fun `NavigateToTrash event should call onNavigateToVaultItemListingType`() { + mutableEventFlow.tryEmit(VaultEvent.NavigateToItemListing(VaultItemListingType.Trash)) + assertEquals(VaultItemListingType.Trash, onNavigateToVaultItemListingType) + } + + @Test + fun `NavigateToFolder event should call onNavigateToVaultItemListingType`() { + val mockFolderId = "mockFolderId" + mutableEventFlow.tryEmit( + VaultEvent.NavigateToItemListing(VaultItemListingType.Folder(mockFolderId)), + ) + assertEquals(VaultItemListingType.Folder(mockFolderId), onNavigateToVaultItemListingType) + } + @Test fun `clicking a favorite item should send VaultItemClick with the correct item`() { val itemText = "Test Item" diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModelTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModelTest.kt index 74df3aa879..7c208d4095 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModelTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModelTest.kt @@ -13,6 +13,7 @@ import com.x8bit.bitwarden.data.vault.repository.model.VaultData import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest import com.x8bit.bitwarden.ui.platform.base.util.asText import com.x8bit.bitwarden.ui.platform.components.model.AccountSummary +import com.x8bit.bitwarden.ui.vault.model.VaultItemListingType import io.mockk.every import io.mockk.just import io.mockk.mockk @@ -345,7 +346,10 @@ class VaultViewModelTest : BaseViewModelTest() { val viewModel = createViewModel() viewModel.eventFlow.test { viewModel.trySendAction(VaultAction.CardGroupClick) - assertEquals(VaultEvent.NavigateToCardGroup, awaitItem()) + assertEquals( + VaultEvent.NavigateToItemListing(VaultItemListingType.Card), + awaitItem(), + ) } } @@ -358,7 +362,10 @@ class VaultViewModelTest : BaseViewModelTest() { } viewModel.eventFlow.test { viewModel.trySendAction(VaultAction.FolderClick(folder)) - assertEquals(VaultEvent.NavigateToFolder(folderId), awaitItem()) + assertEquals( + VaultEvent.NavigateToItemListing(VaultItemListingType.Folder(folderId)), + awaitItem(), + ) } } @@ -367,7 +374,10 @@ class VaultViewModelTest : BaseViewModelTest() { val viewModel = createViewModel() viewModel.eventFlow.test { viewModel.trySendAction(VaultAction.IdentityGroupClick) - assertEquals(VaultEvent.NavigateToIdentityGroup, awaitItem()) + assertEquals( + VaultEvent.NavigateToItemListing(VaultItemListingType.Identity), + awaitItem(), + ) } } @@ -376,7 +386,10 @@ class VaultViewModelTest : BaseViewModelTest() { val viewModel = createViewModel() viewModel.eventFlow.test { viewModel.trySendAction(VaultAction.LoginGroupClick) - assertEquals(VaultEvent.NavigateToLoginGroup, awaitItem()) + assertEquals( + VaultEvent.NavigateToItemListing(VaultItemListingType.Login), + awaitItem(), + ) } } @@ -394,7 +407,10 @@ class VaultViewModelTest : BaseViewModelTest() { val viewModel = createViewModel() viewModel.eventFlow.test { viewModel.trySendAction(VaultAction.SecureNoteGroupClick) - assertEquals(VaultEvent.NavigateToSecureNotesGroup, awaitItem()) + assertEquals( + VaultEvent.NavigateToItemListing(VaultItemListingType.SecureNote), + awaitItem(), + ) } } @@ -403,7 +419,10 @@ class VaultViewModelTest : BaseViewModelTest() { val viewModel = createViewModel() viewModel.eventFlow.test { viewModel.trySendAction(VaultAction.TrashClick) - assertEquals(VaultEvent.NavigateToTrash, awaitItem()) + assertEquals( + VaultEvent.NavigateToItemListing(VaultItemListingType.Trash), + awaitItem(), + ) } }