mirror of
https://github.com/bitwarden/android.git
synced 2024-11-27 03:49:36 +03:00
Show appropriate empty states for autofill flow (#843)
This commit is contained in:
parent
9a8aca9fe1
commit
82ef39e15d
8 changed files with 214 additions and 71 deletions
|
@ -9,10 +9,8 @@ import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.x8bit.bitwarden.R
|
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.vault.VaultNoItems
|
import com.x8bit.bitwarden.ui.vault.feature.vault.VaultNoItems
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,31 +18,21 @@ import com.x8bit.bitwarden.ui.vault.feature.vault.VaultNoItems
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun VaultItemListingEmpty(
|
fun VaultItemListingEmpty(
|
||||||
itemListingType: VaultItemListingState.ItemListingType,
|
state: VaultItemListingState.ViewState.NoItems,
|
||||||
addItemClickAction: () -> Unit,
|
addItemClickAction: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
when (itemListingType) {
|
if (state.shouldShowAddButton) {
|
||||||
is VaultItemListingState.ItemListingType.Vault.Folder -> {
|
VaultNoItems(
|
||||||
GenericNoItems(
|
message = state.message(),
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
text = stringResource(id = R.string.no_items_folder),
|
addItemClickAction = addItemClickAction,
|
||||||
)
|
)
|
||||||
}
|
} else {
|
||||||
|
GenericNoItems(
|
||||||
is VaultItemListingState.ItemListingType.Vault.Trash -> {
|
text = state.message(),
|
||||||
GenericNoItems(
|
modifier = modifier,
|
||||||
modifier = modifier,
|
)
|
||||||
text = stringResource(id = R.string.no_items_trash),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
VaultNoItems(
|
|
||||||
modifier = modifier,
|
|
||||||
addItemClickAction = addItemClickAction,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -242,7 +242,7 @@ private fun VaultItemListingScaffold(
|
||||||
|
|
||||||
is VaultItemListingState.ViewState.NoItems -> {
|
is VaultItemListingState.ViewState.NoItems -> {
|
||||||
VaultItemListingEmpty(
|
VaultItemListingEmpty(
|
||||||
itemListingType = state.itemListingType,
|
state = state.viewState,
|
||||||
addItemClickAction = vaultItemListingHandlers.addVaultItemClick,
|
addItemClickAction = vaultItemListingHandlers.addVaultItemClick,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
)
|
)
|
||||||
|
|
|
@ -545,8 +545,10 @@ class VaultItemListingViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
.toFilteredList(state.vaultFilterType)
|
.toFilteredList(state.vaultFilterType)
|
||||||
.toViewState(
|
.toViewState(
|
||||||
|
itemListingType = listingType,
|
||||||
baseIconUrl = state.baseIconUrl,
|
baseIconUrl = state.baseIconUrl,
|
||||||
isIconLoadingDisabled = state.isIconLoadingDisabled,
|
isIconLoadingDisabled = state.isIconLoadingDisabled,
|
||||||
|
autofillSelectionData = state.autofillSelectionData,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -702,7 +704,10 @@ data class VaultItemListingState(
|
||||||
/**
|
/**
|
||||||
* Represents a state where the [VaultItemListingScreen] has no items to display.
|
* Represents a state where the [VaultItemListingScreen] has no items to display.
|
||||||
*/
|
*/
|
||||||
data object NoItems : ViewState() {
|
data class NoItems(
|
||||||
|
val message: Text,
|
||||||
|
val shouldShowAddButton: Boolean,
|
||||||
|
) : ViewState() {
|
||||||
override val isPullToRefreshEnabled: Boolean get() = true
|
override val isPullToRefreshEnabled: Boolean get() = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,10 @@ import com.bitwarden.core.FolderView
|
||||||
import com.bitwarden.core.SendType
|
import com.bitwarden.core.SendType
|
||||||
import com.bitwarden.core.SendView
|
import com.bitwarden.core.SendView
|
||||||
import com.x8bit.bitwarden.R
|
import com.x8bit.bitwarden.R
|
||||||
|
import com.x8bit.bitwarden.data.autofill.model.AutofillSelectionData
|
||||||
import com.x8bit.bitwarden.data.platform.util.subtitle
|
import com.x8bit.bitwarden.data.platform.util.subtitle
|
||||||
|
import com.x8bit.bitwarden.ui.platform.base.util.asText
|
||||||
|
import com.x8bit.bitwarden.ui.platform.base.util.toHostOrPathOrNull
|
||||||
import com.x8bit.bitwarden.ui.platform.components.model.IconData
|
import com.x8bit.bitwarden.ui.platform.components.model.IconData
|
||||||
import com.x8bit.bitwarden.ui.platform.util.toFormattedPattern
|
import com.x8bit.bitwarden.ui.platform.util.toFormattedPattern
|
||||||
import com.x8bit.bitwarden.ui.tools.feature.send.util.toLabelIcons
|
import com.x8bit.bitwarden.ui.tools.feature.send.util.toLabelIcons
|
||||||
|
@ -78,8 +81,10 @@ fun SendView.determineListingPredicate(
|
||||||
* Transforms a list of [CipherView] into [VaultItemListingState.ViewState].
|
* Transforms a list of [CipherView] into [VaultItemListingState.ViewState].
|
||||||
*/
|
*/
|
||||||
fun List<CipherView>.toViewState(
|
fun List<CipherView>.toViewState(
|
||||||
|
itemListingType: VaultItemListingState.ItemListingType.Vault,
|
||||||
baseIconUrl: String,
|
baseIconUrl: String,
|
||||||
isIconLoadingDisabled: Boolean,
|
isIconLoadingDisabled: Boolean,
|
||||||
|
autofillSelectionData: AutofillSelectionData?,
|
||||||
): VaultItemListingState.ViewState =
|
): VaultItemListingState.ViewState =
|
||||||
if (isNotEmpty()) {
|
if (isNotEmpty()) {
|
||||||
VaultItemListingState.ViewState.Content(
|
VaultItemListingState.ViewState.Content(
|
||||||
|
@ -89,7 +94,36 @@ fun List<CipherView>.toViewState(
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
VaultItemListingState.ViewState.NoItems
|
// Use the autofill empty message if necessary, otherwise use normal type-specific message
|
||||||
|
val message = autofillSelectionData
|
||||||
|
?.uri
|
||||||
|
?.toHostOrPathOrNull()
|
||||||
|
?.let { R.string.no_items_for_uri.asText(it) }
|
||||||
|
?: run {
|
||||||
|
when (itemListingType) {
|
||||||
|
is VaultItemListingState.ItemListingType.Vault.Folder -> {
|
||||||
|
R.string.no_items_folder
|
||||||
|
}
|
||||||
|
|
||||||
|
VaultItemListingState.ItemListingType.Vault.Trash -> {
|
||||||
|
R.string.no_items_trash
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> R.string.no_items
|
||||||
|
}
|
||||||
|
.asText()
|
||||||
|
}
|
||||||
|
val shouldShowAddButton = when (itemListingType) {
|
||||||
|
is VaultItemListingState.ItemListingType.Vault.Folder,
|
||||||
|
VaultItemListingState.ItemListingType.Vault.Trash,
|
||||||
|
-> false
|
||||||
|
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
VaultItemListingState.ViewState.NoItems(
|
||||||
|
message = message,
|
||||||
|
shouldShowAddButton = shouldShowAddButton,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -107,7 +141,10 @@ fun List<SendView>.toViewState(
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
VaultItemListingState.ViewState.NoItems
|
VaultItemListingState.ViewState.NoItems(
|
||||||
|
message = R.string.no_items.asText(),
|
||||||
|
shouldShowAddButton = true,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** * Updates a [VaultItemListingState.ItemListingType] with the given data if necessary. */
|
/** * Updates a [VaultItemListingState.ItemListingType] with the given data if necessary. */
|
||||||
|
|
|
@ -25,6 +25,7 @@ import com.x8bit.bitwarden.R
|
||||||
fun VaultNoItems(
|
fun VaultNoItems(
|
||||||
addItemClickAction: () -> Unit,
|
addItemClickAction: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
message: String = stringResource(id = R.string.no_items),
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
|
@ -36,7 +37,7 @@ fun VaultNoItems(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp),
|
.padding(horizontal = 16.dp),
|
||||||
text = stringResource(id = R.string.no_items),
|
text = message,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -300,7 +300,14 @@ class VaultItemListingScreenTest : BaseComposeTest() {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `add an item button click should send AddItemClick action`() {
|
fun `add an item button click should send AddItemClick action`() {
|
||||||
mutableStateFlow.update { it.copy(viewState = VaultItemListingState.ViewState.NoItems) }
|
mutableStateFlow.update {
|
||||||
|
it.copy(
|
||||||
|
viewState = VaultItemListingState.ViewState.NoItems(
|
||||||
|
message = "There are no items in your vault.".asText(),
|
||||||
|
shouldShowAddButton = true,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithText("Add an Item")
|
.onNodeWithText("Add an Item")
|
||||||
.performClick()
|
.performClick()
|
||||||
|
@ -385,7 +392,12 @@ class VaultItemListingScreenTest : BaseComposeTest() {
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
|
|
||||||
mutableStateFlow.update {
|
mutableStateFlow.update {
|
||||||
it.copy(viewState = VaultItemListingState.ViewState.NoItems)
|
it.copy(
|
||||||
|
viewState = VaultItemListingState.ViewState.NoItems(
|
||||||
|
message = "There are no items in your vault.".asText(),
|
||||||
|
shouldShowAddButton = true,
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
composeTestRule
|
composeTestRule
|
||||||
|
@ -401,7 +413,14 @@ class VaultItemListingScreenTest : BaseComposeTest() {
|
||||||
.onNodeWithText(message)
|
.onNodeWithText(message)
|
||||||
.assertIsNotDisplayed()
|
.assertIsNotDisplayed()
|
||||||
|
|
||||||
mutableStateFlow.update { it.copy(viewState = VaultItemListingState.ViewState.NoItems) }
|
mutableStateFlow.update {
|
||||||
|
it.copy(
|
||||||
|
viewState = VaultItemListingState.ViewState.NoItems(
|
||||||
|
message = "There are no items in your vault.".asText(),
|
||||||
|
shouldShowAddButton = true,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithText(message)
|
.onNodeWithText(message)
|
||||||
.assertIsNotDisplayed()
|
.assertIsNotDisplayed()
|
||||||
|
@ -422,23 +441,23 @@ class VaultItemListingScreenTest : BaseComposeTest() {
|
||||||
.assertDoesNotExist()
|
.assertDoesNotExist()
|
||||||
|
|
||||||
mutableStateFlow.update {
|
mutableStateFlow.update {
|
||||||
it.copy(viewState = VaultItemListingState.ViewState.NoItems)
|
it.copy(
|
||||||
|
viewState = VaultItemListingState.ViewState.NoItems(
|
||||||
|
message = "There are no items in your vault.".asText(),
|
||||||
|
shouldShowAddButton = true,
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithText(text = "Add an Item")
|
.onNodeWithText(text = "Add an Item")
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
|
|
||||||
mutableStateFlow.update {
|
|
||||||
it.copy(itemListingType = VaultItemListingState.ItemListingType.Vault.Trash)
|
|
||||||
}
|
|
||||||
composeTestRule
|
|
||||||
.onNodeWithText(text = "Add an Item")
|
|
||||||
.assertDoesNotExist()
|
|
||||||
|
|
||||||
mutableStateFlow.update {
|
mutableStateFlow.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
itemListingType = VaultItemListingState.ItemListingType.Vault.Folder(
|
viewState = VaultItemListingState.ViewState.NoItems(
|
||||||
folderId = null,
|
message = "There are no items in your vault.".asText(),
|
||||||
|
shouldShowAddButton = false,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -449,29 +468,16 @@ class VaultItemListingScreenTest : BaseComposeTest() {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `empty text should be displayed according to state`() {
|
fun `empty text should be displayed according to state`() {
|
||||||
mutableStateFlow.update {
|
|
||||||
DEFAULT_STATE.copy(viewState = VaultItemListingState.ViewState.NoItems)
|
|
||||||
}
|
|
||||||
composeTestRule
|
|
||||||
.onNodeWithText(text = "There are no items in your vault.")
|
|
||||||
.assertIsDisplayed()
|
|
||||||
|
|
||||||
mutableStateFlow.update {
|
|
||||||
it.copy(itemListingType = VaultItemListingState.ItemListingType.Vault.Trash)
|
|
||||||
}
|
|
||||||
composeTestRule
|
|
||||||
.onNodeWithText(text = "There are no items in the trash.")
|
|
||||||
.assertIsDisplayed()
|
|
||||||
|
|
||||||
mutableStateFlow.update {
|
mutableStateFlow.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
itemListingType = VaultItemListingState.ItemListingType.Vault.Folder(
|
viewState = VaultItemListingState.ViewState.NoItems(
|
||||||
folderId = null,
|
message = "There are no items in your vault.".asText(),
|
||||||
|
shouldShowAddButton = true,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
composeTestRule
|
composeTestRule
|
||||||
.onNodeWithText(text = "There are no items in this folder.")
|
.onNodeWithText(text = "There are no items in your vault.")
|
||||||
.assertIsDisplayed()
|
.assertIsDisplayed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -621,7 +621,12 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||||
assertEquals(VaultItemListingEvent.DismissPullToRefresh, awaitItem())
|
assertEquals(VaultItemListingEvent.DismissPullToRefresh, awaitItem())
|
||||||
}
|
}
|
||||||
assertEquals(
|
assertEquals(
|
||||||
createVaultItemListingState(viewState = VaultItemListingState.ViewState.NoItems),
|
createVaultItemListingState(
|
||||||
|
viewState = VaultItemListingState.ViewState.NoItems(
|
||||||
|
message = R.string.no_items.asText(),
|
||||||
|
shouldShowAddButton = true,
|
||||||
|
),
|
||||||
|
),
|
||||||
viewModel.stateFlow.value,
|
viewModel.stateFlow.value,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -645,7 +650,10 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||||
}
|
}
|
||||||
assertEquals(
|
assertEquals(
|
||||||
createVaultItemListingState(
|
createVaultItemListingState(
|
||||||
viewState = VaultItemListingState.ViewState.NoItems,
|
viewState = VaultItemListingState.ViewState.NoItems(
|
||||||
|
message = R.string.no_items.asText(),
|
||||||
|
shouldShowAddButton = true,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
viewModel.stateFlow.value,
|
viewModel.stateFlow.value,
|
||||||
)
|
)
|
||||||
|
@ -708,7 +716,12 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||||
val viewModel = createVaultItemListingViewModel()
|
val viewModel = createVaultItemListingViewModel()
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
createVaultItemListingState(viewState = VaultItemListingState.ViewState.NoItems),
|
createVaultItemListingState(
|
||||||
|
viewState = VaultItemListingState.ViewState.NoItems(
|
||||||
|
message = R.string.no_items.asText(),
|
||||||
|
shouldShowAddButton = true,
|
||||||
|
),
|
||||||
|
),
|
||||||
viewModel.stateFlow.value,
|
viewModel.stateFlow.value,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -729,7 +742,12 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||||
val viewModel = createVaultItemListingViewModel()
|
val viewModel = createVaultItemListingViewModel()
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
createVaultItemListingState(viewState = VaultItemListingState.ViewState.NoItems),
|
createVaultItemListingState(
|
||||||
|
viewState = VaultItemListingState.ViewState.NoItems(
|
||||||
|
message = R.string.no_items.asText(),
|
||||||
|
shouldShowAddButton = true,
|
||||||
|
),
|
||||||
|
),
|
||||||
viewModel.stateFlow.value,
|
viewModel.stateFlow.value,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -810,7 +828,10 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||||
}
|
}
|
||||||
assertEquals(
|
assertEquals(
|
||||||
createVaultItemListingState(
|
createVaultItemListingState(
|
||||||
viewState = VaultItemListingState.ViewState.NoItems,
|
viewState = VaultItemListingState.ViewState.NoItems(
|
||||||
|
message = R.string.no_items.asText(),
|
||||||
|
shouldShowAddButton = true,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
viewModel.stateFlow.value,
|
viewModel.stateFlow.value,
|
||||||
)
|
)
|
||||||
|
@ -836,7 +857,10 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||||
}
|
}
|
||||||
assertEquals(
|
assertEquals(
|
||||||
createVaultItemListingState(
|
createVaultItemListingState(
|
||||||
viewState = VaultItemListingState.ViewState.NoItems,
|
viewState = VaultItemListingState.ViewState.NoItems(
|
||||||
|
message = R.string.no_items.asText(),
|
||||||
|
shouldShowAddButton = true,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
viewModel.stateFlow.value,
|
viewModel.stateFlow.value,
|
||||||
)
|
)
|
||||||
|
@ -916,7 +940,10 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||||
}
|
}
|
||||||
assertEquals(
|
assertEquals(
|
||||||
createVaultItemListingState(
|
createVaultItemListingState(
|
||||||
viewState = VaultItemListingState.ViewState.NoItems,
|
viewState = VaultItemListingState.ViewState.NoItems(
|
||||||
|
message = R.string.no_items.asText(),
|
||||||
|
shouldShowAddButton = true,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
viewModel.stateFlow.value,
|
viewModel.stateFlow.value,
|
||||||
)
|
)
|
||||||
|
@ -941,7 +968,10 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||||
}
|
}
|
||||||
assertEquals(
|
assertEquals(
|
||||||
createVaultItemListingState(
|
createVaultItemListingState(
|
||||||
viewState = VaultItemListingState.ViewState.NoItems,
|
viewState = VaultItemListingState.ViewState.NoItems(
|
||||||
|
message = R.string.no_items.asText(),
|
||||||
|
shouldShowAddButton = true,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
viewModel.stateFlow.value,
|
viewModel.stateFlow.value,
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,6 +4,8 @@ import android.net.Uri
|
||||||
import com.bitwarden.core.CipherType
|
import com.bitwarden.core.CipherType
|
||||||
import com.bitwarden.core.CipherView
|
import com.bitwarden.core.CipherView
|
||||||
import com.bitwarden.core.SendType
|
import com.bitwarden.core.SendType
|
||||||
|
import com.x8bit.bitwarden.R
|
||||||
|
import com.x8bit.bitwarden.data.autofill.model.AutofillSelectionData
|
||||||
import com.x8bit.bitwarden.data.platform.repository.model.Environment
|
import com.x8bit.bitwarden.data.platform.repository.model.Environment
|
||||||
import com.x8bit.bitwarden.data.platform.repository.util.baseIconUrl
|
import com.x8bit.bitwarden.data.platform.repository.util.baseIconUrl
|
||||||
import com.x8bit.bitwarden.data.platform.repository.util.baseWebSendUrl
|
import com.x8bit.bitwarden.data.platform.repository.util.baseWebSendUrl
|
||||||
|
@ -12,13 +14,15 @@ import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockCipherView
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockCollectionView
|
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockCollectionView
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockFolderView
|
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockFolderView
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSendView
|
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSendView
|
||||||
|
import com.x8bit.bitwarden.ui.platform.base.util.asText
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingState
|
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingState
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.mockkStatic
|
import io.mockk.mockkStatic
|
||||||
import io.mockk.unmockkStatic
|
import io.mockk.unmockkStatic
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.jupiter.api.AfterEach
|
||||||
import org.junit.Test
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
import java.time.Clock
|
import java.time.Clock
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.time.ZoneOffset
|
import java.time.ZoneOffset
|
||||||
|
@ -30,6 +34,12 @@ class VaultItemListingDataExtensionsTest {
|
||||||
ZoneOffset.UTC,
|
ZoneOffset.UTC,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
fun tearDown() {
|
||||||
|
unmockkStatic(Uri::class)
|
||||||
|
unmockkStatic(CipherView::subtitle)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Suppress("MaxLineLength")
|
@Suppress("MaxLineLength")
|
||||||
fun `determineListingPredicate should return the correct predicate for non trash Login cipherView`() {
|
fun `determineListingPredicate should return the correct predicate for non trash Login cipherView`() {
|
||||||
|
@ -333,8 +343,10 @@ class VaultItemListingDataExtensionsTest {
|
||||||
)
|
)
|
||||||
|
|
||||||
val result = cipherViewList.toViewState(
|
val result = cipherViewList.toViewState(
|
||||||
|
itemListingType = VaultItemListingState.ItemListingType.Vault.Login,
|
||||||
isIconLoadingDisabled = false,
|
isIconLoadingDisabled = false,
|
||||||
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
|
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
|
||||||
|
autofillSelectionData = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
|
@ -364,9 +376,73 @@ class VaultItemListingDataExtensionsTest {
|
||||||
),
|
),
|
||||||
result,
|
result,
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
unmockkStatic(CipherView::subtitle)
|
@Suppress("MaxLineLength")
|
||||||
unmockkStatic(Uri::class)
|
@Test
|
||||||
|
fun `toViewState should transform an empty list of CipherViews into a NoItems ViewState with the appropriate data`() {
|
||||||
|
val cipherViewList = emptyList<CipherView>()
|
||||||
|
|
||||||
|
// Trash
|
||||||
|
assertEquals(
|
||||||
|
VaultItemListingState.ViewState.NoItems(
|
||||||
|
message = R.string.no_items_trash.asText(),
|
||||||
|
shouldShowAddButton = false,
|
||||||
|
),
|
||||||
|
cipherViewList.toViewState(
|
||||||
|
itemListingType = VaultItemListingState.ItemListingType.Vault.Trash,
|
||||||
|
isIconLoadingDisabled = false,
|
||||||
|
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
|
||||||
|
autofillSelectionData = null,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Folders
|
||||||
|
assertEquals(
|
||||||
|
VaultItemListingState.ViewState.NoItems(
|
||||||
|
message = R.string.no_items_folder.asText(),
|
||||||
|
shouldShowAddButton = false,
|
||||||
|
),
|
||||||
|
cipherViewList.toViewState(
|
||||||
|
itemListingType = VaultItemListingState.ItemListingType.Vault.Folder(
|
||||||
|
folderId = "folderId",
|
||||||
|
),
|
||||||
|
isIconLoadingDisabled = false,
|
||||||
|
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
|
||||||
|
autofillSelectionData = null,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Other ciphers
|
||||||
|
assertEquals(
|
||||||
|
VaultItemListingState.ViewState.NoItems(
|
||||||
|
message = R.string.no_items.asText(),
|
||||||
|
shouldShowAddButton = true,
|
||||||
|
),
|
||||||
|
cipherViewList.toViewState(
|
||||||
|
itemListingType = VaultItemListingState.ItemListingType.Vault.Login,
|
||||||
|
isIconLoadingDisabled = false,
|
||||||
|
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
|
||||||
|
autofillSelectionData = null,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Autofill
|
||||||
|
assertEquals(
|
||||||
|
VaultItemListingState.ViewState.NoItems(
|
||||||
|
message = R.string.no_items_for_uri.asText("www.test.com"),
|
||||||
|
shouldShowAddButton = true,
|
||||||
|
),
|
||||||
|
cipherViewList.toViewState(
|
||||||
|
itemListingType = VaultItemListingState.ItemListingType.Vault.Login,
|
||||||
|
isIconLoadingDisabled = false,
|
||||||
|
baseIconUrl = Environment.Us.environmentUrlData.baseIconUrl,
|
||||||
|
autofillSelectionData = AutofillSelectionData(
|
||||||
|
type = AutofillSelectionData.Type.LOGIN,
|
||||||
|
uri = "https://www.test.com",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in a new issue