BIT-151: Added Wireframe for Vault Screen (#48)

This commit is contained in:
Ramsey Smith
2023-09-14 13:02:56 -06:00
committed by GitHub
parent c1472ee078
commit e2a857df8c
16 changed files with 654 additions and 51 deletions

View File

@@ -68,6 +68,7 @@ class FakeNavHostController : NavHostController(context = mockk()) {
private val internalGraph =
mockk<NavGraph>().apply {
every { id } returns graphId
every { startDestinationId } returns graphId
}
override var graph: NavGraph

View File

@@ -1,13 +1,28 @@
package com.x8bit.bitwarden.ui.platform.feature.vaultunlockednavbar
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.navigation.navOptions
import com.x8bit.bitwarden.ui.platform.base.BaseComposeTest
import com.x8bit.bitwarden.ui.platform.base.FakeNavHostController
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import kotlinx.coroutines.flow.MutableSharedFlow
import org.junit.Test
class VaultUnlockedNavBarScreenTest : BaseComposeTest() {
private val fakeNavHostController = FakeNavHostController()
private val expectedNavOptions = navOptions {
// When changing root navigation state, pop everything else off the back stack:
popUpTo(fakeNavHostController.graphId) {
inclusive = false
saveState = true
}
launchSingleTop = true
restoreState = true
}
@Test
fun `vault tab click should send VaultTabClick action`() {
@@ -16,13 +31,40 @@ class VaultUnlockedNavBarScreenTest : BaseComposeTest() {
setContent {
VaultUnlockedNavBarScreen(
viewModel = viewModel,
navController = fakeNavHostController,
)
}
onNodeWithTag("vault").performClick()
onNodeWithText("My vault").performClick()
}
verify { viewModel.trySendAction(VaultUnlockedNavBarAction.VaultTabClick) }
}
@Test
fun `NavigateToVaultScreen should navigate to VaultScreen`() {
val vaultUnlockedNavBarEventFlow = MutableSharedFlow<VaultUnlockedNavBarEvent>(
extraBufferCapacity = Int.MAX_VALUE,
)
val viewModel = mockk<VaultUnlockedNavBarViewModel>(relaxed = true) {
every { eventFlow } returns vaultUnlockedNavBarEventFlow
}
composeTestRule.apply {
setContent {
VaultUnlockedNavBarScreen(
viewModel = viewModel,
navController = fakeNavHostController,
)
}
runOnIdle { fakeNavHostController.assertCurrentRoute("vault") }
vaultUnlockedNavBarEventFlow.tryEmit(VaultUnlockedNavBarEvent.NavigateToVaultScreen)
runOnIdle {
fakeNavHostController.assertLastNavigation(
route = "vault",
navOptions = expectedNavOptions,
)
}
}
}
@Test
fun `send tab click should send SendTabClick action`() {
val viewModel = mockk<VaultUnlockedNavBarViewModel>(relaxed = true)
@@ -30,13 +72,40 @@ class VaultUnlockedNavBarScreenTest : BaseComposeTest() {
setContent {
VaultUnlockedNavBarScreen(
viewModel = viewModel,
navController = fakeNavHostController,
)
}
onNodeWithTag("send").performClick()
onNodeWithText("Send").performClick()
}
verify { viewModel.trySendAction(VaultUnlockedNavBarAction.SendTabClick) }
}
@Test
fun `NavigateToSendScreen should navigate to SendScreen`() {
val vaultUnlockedNavBarEventFlow = MutableSharedFlow<VaultUnlockedNavBarEvent>(
extraBufferCapacity = Int.MAX_VALUE,
)
val viewModel = mockk<VaultUnlockedNavBarViewModel>(relaxed = true) {
every { eventFlow } returns vaultUnlockedNavBarEventFlow
}
composeTestRule.apply {
setContent {
VaultUnlockedNavBarScreen(
viewModel = viewModel,
navController = fakeNavHostController,
)
}
runOnIdle { fakeNavHostController.assertCurrentRoute("vault") }
vaultUnlockedNavBarEventFlow.tryEmit(VaultUnlockedNavBarEvent.NavigateToSendScreen)
runOnIdle {
fakeNavHostController.assertLastNavigation(
route = "send",
navOptions = expectedNavOptions,
)
}
}
}
@Test
fun `generator tab click should send GeneratorTabClick action`() {
val viewModel = mockk<VaultUnlockedNavBarViewModel>(relaxed = true)
@@ -44,13 +113,40 @@ class VaultUnlockedNavBarScreenTest : BaseComposeTest() {
setContent {
VaultUnlockedNavBarScreen(
viewModel = viewModel,
navController = fakeNavHostController,
)
}
onNodeWithTag("generator").performClick()
onNodeWithText("Generator").performClick()
}
verify { viewModel.trySendAction(VaultUnlockedNavBarAction.GeneratorTabClick) }
}
@Test
fun `NavigateToGeneratorScreen should navigate to GeneratorScreen`() {
val vaultUnlockedNavBarEventFlow = MutableSharedFlow<VaultUnlockedNavBarEvent>(
extraBufferCapacity = Int.MAX_VALUE,
)
val viewModel = mockk<VaultUnlockedNavBarViewModel>(relaxed = true) {
every { eventFlow } returns vaultUnlockedNavBarEventFlow
}
composeTestRule.apply {
setContent {
VaultUnlockedNavBarScreen(
viewModel = viewModel,
navController = fakeNavHostController,
)
}
runOnIdle { fakeNavHostController.assertCurrentRoute("vault") }
vaultUnlockedNavBarEventFlow.tryEmit(VaultUnlockedNavBarEvent.NavigateToGeneratorScreen)
runOnIdle {
fakeNavHostController.assertLastNavigation(
route = "generator",
navOptions = expectedNavOptions,
)
}
}
}
@Test
fun `settings tab click should send SendTabClick action`() {
val viewModel = mockk<VaultUnlockedNavBarViewModel>(relaxed = true)
@@ -58,10 +154,37 @@ class VaultUnlockedNavBarScreenTest : BaseComposeTest() {
setContent {
VaultUnlockedNavBarScreen(
viewModel = viewModel,
navController = fakeNavHostController,
)
}
onNodeWithTag("settings").performClick()
onNodeWithText("Settings").performClick()
}
verify { viewModel.trySendAction(VaultUnlockedNavBarAction.SettingsTabClick) }
}
@Test
fun `NavigateToSettingsScreen should navigate to SettingsScreen`() {
val vaultUnlockedNavBarEventFlow = MutableSharedFlow<VaultUnlockedNavBarEvent>(
extraBufferCapacity = Int.MAX_VALUE,
)
val viewModel = mockk<VaultUnlockedNavBarViewModel>(relaxed = true) {
every { eventFlow } returns vaultUnlockedNavBarEventFlow
}
composeTestRule.apply {
setContent {
VaultUnlockedNavBarScreen(
viewModel = viewModel,
navController = fakeNavHostController,
)
}
runOnIdle { fakeNavHostController.assertCurrentRoute("vault") }
vaultUnlockedNavBarEventFlow.tryEmit(VaultUnlockedNavBarEvent.NavigateToSettingsScreen)
runOnIdle {
fakeNavHostController.assertLastNavigation(
route = "settings",
navOptions = expectedNavOptions,
)
}
}
}
}

View File

@@ -12,7 +12,7 @@ class VaultUnlockedNavBarViewModelTest : BaseViewModelTest() {
val viewModel = VaultUnlockedNavBarViewModel()
viewModel.eventFlow.test {
viewModel.trySendAction(VaultUnlockedNavBarAction.VaultTabClick)
assertEquals(VaultUnlockedNavBarEvent.NavigateToVaultScreenNavBar, awaitItem())
assertEquals(VaultUnlockedNavBarEvent.NavigateToVaultScreen, awaitItem())
}
}

View File

@@ -0,0 +1,66 @@
package com.x8bit.bitwarden.ui.vault.feature.vault
import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import com.x8bit.bitwarden.ui.platform.base.BaseComposeTest
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.emptyFlow
import org.junit.Test
class VaultScreenTest : BaseComposeTest() {
@Test
fun `search icon click should send SearchIconClick action`() {
val viewModel = mockk<VaultViewModel>(relaxed = true) {
every { eventFlow } returns emptyFlow()
every { stateFlow } returns MutableStateFlow(VaultState.NoItems)
}
composeTestRule.apply {
setContent {
VaultScreen(
viewModel = viewModel,
)
}
onNodeWithContentDescription("Search vault").performClick()
}
verify { viewModel.trySendAction(VaultAction.SearchIconClick) }
}
@Test
fun `floating action button click should send AddItemClick action`() {
val viewModel = mockk<VaultViewModel>(relaxed = true) {
every { eventFlow } returns emptyFlow()
every { stateFlow } returns MutableStateFlow(VaultState.NoItems)
}
composeTestRule.apply {
setContent {
VaultScreen(
viewModel = viewModel,
)
}
onNodeWithContentDescription("Add Item").performClick()
}
verify { viewModel.trySendAction(VaultAction.AddItemClick) }
}
@Test
fun `add an item button click should send AddItemClick action`() {
val viewModel = mockk<VaultViewModel>(relaxed = true) {
every { eventFlow } returns emptyFlow()
every { stateFlow } returns MutableStateFlow(VaultState.NoItems)
}
composeTestRule.apply {
setContent {
VaultScreen(
viewModel = viewModel,
)
}
onNodeWithText("Add an Item").performClick()
}
verify { viewModel.trySendAction(VaultAction.AddItemClick) }
}
}

View File

@@ -0,0 +1,28 @@
package com.x8bit.bitwarden.ui.vault.feature.vault
import app.cash.turbine.test
import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
class VaultViewModelTest : BaseViewModelTest() {
@Test
fun `AddItemClick should navigate to the add item screen`() = runTest {
val viewModel = VaultViewModel()
viewModel.eventFlow.test {
viewModel.trySendAction(VaultAction.AddItemClick)
assertEquals(VaultEvent.NavigateToAddItemScreen, awaitItem())
}
}
@Test
fun `SearchIconClick should navigate to the vault search screen`() = runTest {
val viewModel = VaultViewModel()
viewModel.eventFlow.test {
viewModel.trySendAction(VaultAction.SearchIconClick)
assertEquals(VaultEvent.NavigateToVaultSearchScreen, awaitItem())
}
}
}