BIT-603: Display Collections on Vault screen (#386)

This commit is contained in:
Brian Yencho
2023-12-13 11:37:52 -06:00
committed by GitHub
parent 29228c1b21
commit 2f40334e4f
10 changed files with 216 additions and 6 deletions

View File

@@ -25,7 +25,7 @@ fun createMockCipherView(number: Int): CipherView =
id = "mockId-$number",
organizationId = "mockOrganizationId-$number",
folderId = "mockId-$number",
collectionIds = listOf("mockCollectionId-$number"),
collectionIds = listOf("mockId-$number"),
key = "mockKey-$number",
name = "mockName-$number",
notes = "mockNotes-$number",

View File

@@ -41,11 +41,14 @@ fun ComposeContentTestRule.assertNoDialogExists() {
/**
* A helper that asserts that the node does not exist in the scrollable list.
*/
fun ComposeContentTestRule.assertScrollableNodeDoesNotExist(text: String) {
fun ComposeContentTestRule.assertScrollableNodeDoesNotExist(
text: String,
substring: Boolean = false,
) {
val scrollableNodeInteraction = onNode(hasScrollToNodeAction())
assertThrows<AssertionError> {
// throws since it cannot find the node.
scrollableNodeInteraction.performScrollToNode(hasText(text))
scrollableNodeInteraction.performScrollToNode(hasText(text, substring))
}
}
@@ -53,9 +56,12 @@ fun ComposeContentTestRule.assertScrollableNodeDoesNotExist(text: String) {
* A helper used to scroll to and get the matching node in a scrollable list. This is intended to
* be used with lazy lists that would otherwise fail when calling [performScrollToNode].
*/
fun ComposeContentTestRule.onNodeWithTextAfterScroll(text: String): SemanticsNodeInteraction {
onNode(hasScrollToNodeAction()).performScrollToNode(hasText(text))
return onNodeWithText(text)
fun ComposeContentTestRule.onNodeWithTextAfterScroll(
text: String,
substring: Boolean = false,
): SemanticsNodeInteraction {
onNode(hasScrollToNodeAction()).performScrollToNode(hasText(text, substring))
return onNodeWithText(text, substring)
}
/**

View File

@@ -1,5 +1,6 @@
package com.x8bit.bitwarden.ui.vault.feature.vault
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertTextEquals
import androidx.compose.ui.test.filterToOne
import androidx.compose.ui.test.hasClickAction
@@ -15,8 +16,10 @@ import com.x8bit.bitwarden.ui.platform.components.model.AccountSummary
import com.x8bit.bitwarden.ui.util.assertLockOrLogoutDialogIsDisplayed
import com.x8bit.bitwarden.ui.util.assertLogoutConfirmationDialogIsDisplayed
import com.x8bit.bitwarden.ui.util.assertNoDialogExists
import com.x8bit.bitwarden.ui.util.assertScrollableNodeDoesNotExist
import com.x8bit.bitwarden.ui.util.assertSwitcherIsDisplayed
import com.x8bit.bitwarden.ui.util.assertSwitcherIsNotDisplayed
import com.x8bit.bitwarden.ui.util.onNodeWithTextAfterScroll
import com.x8bit.bitwarden.ui.util.performAccountClick
import com.x8bit.bitwarden.ui.util.performAccountIconClick
import com.x8bit.bitwarden.ui.util.performAccountLongClick
@@ -319,6 +322,66 @@ class VaultScreenTest : BaseComposeTest() {
}
}
@Test
fun `collection data should update according to the state`() {
val collectionsHeader = "Collections"
val collectionsCount = 1
val collectionName = "Test Collection"
val collectionCount = 3
val collectionItem = VaultState.ViewState.CollectionItem(
id = "12345",
name = collectionName,
itemCount = collectionCount,
)
composeTestRule.assertScrollableNodeDoesNotExist(collectionsHeader, substring = true)
composeTestRule.assertScrollableNodeDoesNotExist(collectionName, substring = true)
mutableStateFlow.update {
it.copy(
viewState = DEFAULT_CONTENT_VIEW_STATE.copy(
collectionItems = listOf(collectionItem),
),
)
}
composeTestRule
.onNodeWithTextAfterScroll(collectionsHeader, substring = true)
.assertTextEquals(collectionsHeader, collectionsCount.toString())
.assertIsDisplayed()
composeTestRule
.onNodeWithText(collectionName)
.assertTextEquals(collectionName, collectionCount.toString())
}
@Test
fun `clicking a collection item should send CollectionClick with the correct item`() {
val collectionName = "Test Collection"
val collectionCount = 3
val collectionItem = VaultState.ViewState.CollectionItem(
id = "12345",
name = collectionName,
itemCount = collectionCount,
)
mutableStateFlow.update {
it.copy(
viewState = DEFAULT_CONTENT_VIEW_STATE.copy(
collectionItems = listOf(collectionItem),
),
)
}
composeTestRule.onNode(hasScrollToNodeAction()).performScrollToNode(hasText(collectionName))
composeTestRule
.onNodeWithText(collectionName)
.assertTextEquals(collectionName, collectionCount.toString())
.performClick()
verify {
viewModel.trySendAction(VaultAction.CollectionClick(collectionItem))
}
}
@Test
fun `clicking a no folder item should send VaultItemClick with the correct item`() {
val itemText = "Test Item"
@@ -583,5 +646,6 @@ private val DEFAULT_CONTENT_VIEW_STATE: VaultState.ViewState.Content = VaultStat
favoriteItems = emptyList(),
folderItems = emptyList(),
noFolderItems = emptyList(),
collectionItems = emptyList(),
trashItemsCount = 0,
)

View File

@@ -284,6 +284,13 @@ class VaultViewModelTest : BaseViewModelTest() {
itemCount = 1,
),
),
collectionItems = listOf(
VaultState.ViewState.CollectionItem(
id = "mockId-1",
name = "mockName-1",
itemCount = 1,
),
),
noFolderItems = listOf(),
trashItemsCount = 0,
),
@@ -437,6 +444,22 @@ class VaultViewModelTest : BaseViewModelTest() {
}
}
@Test
fun `CollectionClick should emit ShowToast`() = runTest {
val viewModel = createViewModel()
val collectionId = "12345"
val collection = mockk<VaultState.ViewState.CollectionItem> {
every { id } returns collectionId
}
viewModel.eventFlow.test {
viewModel.trySendAction(VaultAction.CollectionClick(collection))
assertEquals(
VaultEvent.ShowToast(message = "Not yet implemented."),
awaitItem(),
)
}
}
@Test
fun `IdentityGroupClick should emit NavigateToItemListing event with Identity type`() =
runTest {

View File

@@ -56,6 +56,13 @@ class VaultDataExtensionsTest {
itemCount = 1,
),
),
collectionItems = listOf(
VaultState.ViewState.CollectionItem(
id = "mockId-1",
name = "mockName-1",
itemCount = 1,
),
),
noFolderItems = listOf(),
trashItemsCount = 0,
),
@@ -103,6 +110,13 @@ class VaultDataExtensionsTest {
itemCount = 0,
),
),
collectionItems = listOf(
VaultState.ViewState.CollectionItem(
id = "mockId-1",
name = "mockName-1",
itemCount = 0,
),
),
noFolderItems = emptyList(),
trashItemsCount = 0,
),