mirror of
https://github.com/bitwarden/android.git
synced 2026-10-22 02:53:19 -05:00
[PM-40534] feat: Restrict Send creation flow when only one Send type is allowed (#7249)
This commit is contained in:
1 parent
68c69a40b2
commit
1ef5568f21
7 files changed
+262
-56
No files matched your search
@@ -33,6 +33,7 @@ private const val SEND_TYPES_COUNT: Int = 2
|
||||
@Composable
|
||||
fun SendContent(
|
||||
policyDisablesSend: Boolean,
|
||||
shouldShowTypesSection: Boolean,
|
||||
state: SendState.ViewState.Content,
|
||||
upgradedToPremiumCardData: UpgradedToPremiumCardData?,
|
||||
sendHandlers: SendHandlers,
|
||||
@@ -67,44 +68,46 @@ fun SendContent(
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenListHeaderText(
|
||||
label = stringResource(id = BitwardenString.types),
|
||||
supportingLabel = SEND_TYPES_COUNT.toString(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin()
|
||||
.padding(horizontal = 16.dp),
|
||||
)
|
||||
Spacer(modifier = Modifier.height(height = 8.dp))
|
||||
}
|
||||
if (shouldShowTypesSection) {
|
||||
item {
|
||||
BitwardenListHeaderText(
|
||||
label = stringResource(id = BitwardenString.types),
|
||||
supportingLabel = SEND_TYPES_COUNT.toString(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin()
|
||||
.padding(horizontal = 16.dp),
|
||||
)
|
||||
Spacer(modifier = Modifier.height(height = 8.dp))
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenGroupItem(
|
||||
label = stringResource(id = BitwardenString.type_text),
|
||||
supportingLabel = state.textTypeCount.toString(),
|
||||
startIcon = IconData.Local(iconRes = BitwardenDrawable.ic_file_text),
|
||||
onClick = sendHandlers.onTextTypeClick,
|
||||
cardStyle = CardStyle.Top(dividerPadding = 56.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag("SendTextFilter")
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
item {
|
||||
BitwardenGroupItem(
|
||||
label = stringResource(id = BitwardenString.type_text),
|
||||
supportingLabel = state.textTypeCount.toString(),
|
||||
startIcon = IconData.Local(iconRes = BitwardenDrawable.ic_file_text),
|
||||
onClick = sendHandlers.onTextTypeClick,
|
||||
cardStyle = CardStyle.Top(dividerPadding = 56.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag("SendTextFilter")
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
BitwardenGroupItem(
|
||||
label = stringResource(id = BitwardenString.type_file),
|
||||
supportingLabel = state.fileTypeCount.toString(),
|
||||
startIcon = IconData.Local(iconRes = BitwardenDrawable.ic_file),
|
||||
onClick = sendHandlers.onFileTypeClick,
|
||||
cardStyle = CardStyle.Bottom,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag("SendFileFilter")
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
item {
|
||||
BitwardenGroupItem(
|
||||
label = stringResource(id = BitwardenString.type_file),
|
||||
supportingLabel = state.fileTypeCount.toString(),
|
||||
startIcon = IconData.Local(iconRes = BitwardenDrawable.ic_file),
|
||||
onClick = sendHandlers.onFileTypeClick,
|
||||
cardStyle = CardStyle.Bottom,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag("SendFileFilter")
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
|
||||
@@ -202,6 +202,7 @@ fun SendScreen(
|
||||
when (val viewState = state.viewState) {
|
||||
is SendState.ViewState.Content -> SendContent(
|
||||
policyDisablesSend = state.policyDisablesSend,
|
||||
shouldShowTypesSection = state.shouldShowTypesSection,
|
||||
state = viewState,
|
||||
upgradedToPremiumCardData = upgradedToPremiumCardData,
|
||||
sendHandlers = sendHandlers,
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.x8bit.bitwarden.data.billing.manager.PremiumStateManager
|
||||
import com.x8bit.bitwarden.data.billing.manager.UPGRADED_TO_PREMIUM_LEARN_MORE_URL
|
||||
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.model.EffectiveSendPolicy
|
||||
import com.x8bit.bitwarden.data.platform.manager.network.NetworkConnectionManager
|
||||
import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository
|
||||
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
|
||||
@@ -30,6 +31,7 @@ import com.x8bit.bitwarden.data.vault.repository.model.RemovePasswordSendResult
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.SendData
|
||||
import com.x8bit.bitwarden.ui.platform.model.SnackbarRelay
|
||||
import com.x8bit.bitwarden.ui.tools.feature.send.model.SendItemType
|
||||
import com.x8bit.bitwarden.ui.tools.feature.send.util.toSendItemType
|
||||
import com.x8bit.bitwarden.ui.tools.feature.send.util.toViewState
|
||||
import com.x8bit.bitwarden.ui.vault.feature.item.VaultItemScreen
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
@@ -64,15 +66,18 @@ class SendViewModel @Inject constructor(
|
||||
) : BaseViewModel<SendState, SendEvent, SendAction>(
|
||||
// We load the state from the savedStateHandle for testing purposes.
|
||||
initialState = savedStateHandle[KEY_STATE]
|
||||
?: SendState(
|
||||
viewState = SendState.ViewState.Loading,
|
||||
dialogState = null,
|
||||
isPullToRefreshSettingEnabled = settingsRepo.getPullToRefreshEnabledFlow().value,
|
||||
policyDisablesSend = policyManager.getEffectiveSendPolicy().disableSend,
|
||||
isRefreshing = false,
|
||||
isPremiumUser = authRepo.userStateFlow.value?.activeAccount?.isPremium == true,
|
||||
isUpgradedToPremiumCardEligible = false,
|
||||
),
|
||||
?: policyManager.getEffectiveSendPolicy().let { effectiveSendPolicy ->
|
||||
SendState(
|
||||
viewState = SendState.ViewState.Loading,
|
||||
dialogState = null,
|
||||
isPullToRefreshSettingEnabled = settingsRepo.getPullToRefreshEnabledFlow().value,
|
||||
policyDisablesSend = effectiveSendPolicy.disableSend,
|
||||
singleAllowedSendType = effectiveSendPolicy.singleAllowedSendType,
|
||||
isRefreshing = false,
|
||||
isPremiumUser = authRepo.userStateFlow.value?.activeAccount?.isPremium == true,
|
||||
isUpgradedToPremiumCardEligible = false,
|
||||
)
|
||||
},
|
||||
) {
|
||||
|
||||
init {
|
||||
@@ -83,7 +88,7 @@ class SendViewModel @Inject constructor(
|
||||
.launchIn(viewModelScope)
|
||||
policyManager
|
||||
.getEffectiveSendPolicyFlow()
|
||||
.map { SendAction.Internal.PolicyUpdateReceive(it.disableSend) }
|
||||
.map { SendAction.Internal.PolicyUpdateReceive(effectiveSendPolicy = it) }
|
||||
.onEach(::sendAction)
|
||||
.launchIn(viewModelScope)
|
||||
vaultRepo
|
||||
@@ -314,7 +319,8 @@ class SendViewModel @Inject constructor(
|
||||
private fun handlePolicyUpdateReceive(action: SendAction.Internal.PolicyUpdateReceive) {
|
||||
mutableStateFlow.update {
|
||||
it.copy(
|
||||
policyDisablesSend = action.policyDisablesSend,
|
||||
policyDisablesSend = action.effectiveSendPolicy.disableSend,
|
||||
singleAllowedSendType = action.effectiveSendPolicy.singleAllowedSendType,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -324,13 +330,22 @@ class SendViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
private fun handleAddSendClick() {
|
||||
mutableStateFlow.update {
|
||||
it.copy(dialogState = SendState.DialogState.SelectSendAddType)
|
||||
}
|
||||
state
|
||||
.singleAllowedSendType
|
||||
// Skip the type picker when the policy only allows a single type, while still applying
|
||||
// the same restrictions the picker selection would.
|
||||
?.let { navigateToNewSendOrShowDialog(sendType = it) }
|
||||
?: mutableStateFlow.update {
|
||||
it.copy(dialogState = SendState.DialogState.SelectSendAddType)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleAddSendSelected(action: SendAction.AddSendSelected) {
|
||||
if (action.sendType == SendItemType.FILE) {
|
||||
navigateToNewSendOrShowDialog(sendType = action.sendType)
|
||||
}
|
||||
|
||||
private fun navigateToNewSendOrShowDialog(sendType: SendItemType) {
|
||||
if (sendType == SendItemType.FILE) {
|
||||
if (state.policyDisablesSend) {
|
||||
mutableStateFlow.update {
|
||||
it.copy(
|
||||
@@ -350,7 +365,7 @@ class SendViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
mutableStateFlow.update { it.copy(dialogState = null) }
|
||||
sendEvent(SendEvent.NavigateNewSend(sendType = action.sendType))
|
||||
sendEvent(SendEvent.NavigateNewSend(sendType = sendType))
|
||||
}
|
||||
|
||||
private fun handleLockClick() {
|
||||
@@ -499,6 +514,7 @@ data class SendState(
|
||||
val dialogState: DialogState?,
|
||||
private val isPullToRefreshSettingEnabled: Boolean,
|
||||
val policyDisablesSend: Boolean,
|
||||
val singleAllowedSendType: SendItemType?,
|
||||
val isRefreshing: Boolean,
|
||||
val isPremiumUser: Boolean,
|
||||
val isUpgradedToPremiumCardEligible: Boolean = false,
|
||||
@@ -509,6 +525,13 @@ data class SendState(
|
||||
val shouldShowSearchIcon: Boolean
|
||||
get() = viewState is ViewState.Content
|
||||
|
||||
/**
|
||||
* Whether the types section should be shown. Filtering by type is meaningless when the policy
|
||||
* only allows a single type.
|
||||
*/
|
||||
val shouldShowTypesSection: Boolean
|
||||
get() = singleAllowedSendType == null
|
||||
|
||||
/**
|
||||
* Indicates that the pull-to-refresh should be enabled in the UI.
|
||||
*/
|
||||
@@ -803,7 +826,7 @@ sealed class SendAction {
|
||||
* Indicates that a policy update has been received.
|
||||
*/
|
||||
data class PolicyUpdateReceive(
|
||||
val policyDisablesSend: Boolean,
|
||||
val effectiveSendPolicy: EffectiveSendPolicy,
|
||||
) : Internal()
|
||||
|
||||
/**
|
||||
@@ -905,3 +928,13 @@ sealed class SendEvent {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The only [SendItemType] the policy permits, or `null` when the user is not restricted to a single
|
||||
* type. A `null` [EffectiveSendPolicy.allowedSendTypes] means no restriction is in effect, which is
|
||||
* also the case whenever the send controls feature flag is disabled.
|
||||
*/
|
||||
private val EffectiveSendPolicy.singleAllowedSendType: SendItemType?
|
||||
get() = allowedSendTypes
|
||||
?.singleOrNull()
|
||||
?.toSendItemType()
|
||||
+10
@@ -1,5 +1,6 @@
|
||||
package com.x8bit.bitwarden.ui.tools.feature.send.util
|
||||
|
||||
import com.bitwarden.network.model.SendTypeJson
|
||||
import com.bitwarden.send.SendType
|
||||
import com.x8bit.bitwarden.ui.tools.feature.send.model.SendItemType
|
||||
|
||||
@@ -12,3 +13,12 @@ fun SendType.toSendItemType(): SendItemType =
|
||||
SendType.TEXT -> SendItemType.TEXT
|
||||
SendType.ITEM -> TODO("[PM-41095] Support Item SendType")
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the [SendTypeJson] to its corresponding [SendItemType].
|
||||
*/
|
||||
fun SendTypeJson.toSendItemType(): SendItemType =
|
||||
when (this) {
|
||||
SendTypeJson.FILE -> SendItemType.FILE
|
||||
SendTypeJson.TEXT -> SendItemType.TEXT
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import androidx.compose.ui.test.isPopup
|
||||
import androidx.compose.ui.test.onAllNodesWithText
|
||||
import androidx.compose.ui.test.onChildren
|
||||
import androidx.compose.ui.test.onNodeWithContentDescription
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performScrollTo
|
||||
@@ -356,6 +357,28 @@ class SendScreenTest : BitwardenComposeTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `types section should be displayed according to state`() {
|
||||
mutableStateFlow.update {
|
||||
it.copy(viewState = DEFAULT_CONTENT_VIEW_STATE, singleAllowedSendType = null)
|
||||
}
|
||||
composeTestRule.onNode(hasScrollToNodeAction()).performScrollToNode(hasText("Text"))
|
||||
composeTestRule.onNodeWithTag("SendTextFilter").assertIsDisplayed()
|
||||
composeTestRule.onNodeWithTag("SendFileFilter").assertIsDisplayed()
|
||||
|
||||
// Filtering by type is meaningless when only one type is allowed, so the whole section
|
||||
// is removed rather than partially rendered.
|
||||
mutableStateFlow.update {
|
||||
it.copy(
|
||||
viewState = DEFAULT_CONTENT_VIEW_STATE,
|
||||
singleAllowedSendType = SendItemType.TEXT,
|
||||
)
|
||||
}
|
||||
composeTestRule.onNodeWithTag("SendTextFilter").assertDoesNotExist()
|
||||
composeTestRule.onNodeWithTag("SendFileFilter").assertDoesNotExist()
|
||||
composeTestRule.onNodeWithText("Types").assertDoesNotExist()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `text type count should be updated according to state`() {
|
||||
val rowText = "Text"
|
||||
@@ -1107,6 +1130,7 @@ private val DEFAULT_STATE: SendState = SendState(
|
||||
dialogState = null,
|
||||
isPullToRefreshSettingEnabled = false,
|
||||
policyDisablesSend = false,
|
||||
singleAllowedSendType = null,
|
||||
isRefreshing = false,
|
||||
isPremiumUser = false,
|
||||
)
|
||||
|
||||
+116
-3
@@ -6,6 +6,7 @@ import com.bitwarden.core.data.repository.model.DataState
|
||||
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
|
||||
import com.bitwarden.data.repository.model.Environment
|
||||
import com.bitwarden.data.repository.util.baseWebSendUrl
|
||||
import com.bitwarden.network.model.SendTypeJson
|
||||
import com.bitwarden.ui.platform.base.BaseViewModelTest
|
||||
import com.bitwarden.ui.platform.components.snackbar.model.BitwardenSnackbarData
|
||||
import com.bitwarden.ui.platform.manager.snackbar.SnackbarRelayManager
|
||||
@@ -41,7 +42,6 @@ import io.mockk.verify
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.test.advanceTimeBy
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
@@ -72,9 +72,10 @@ class SendViewModelTest : BaseViewModelTest() {
|
||||
private val vaultRepo: VaultRepository = mockk {
|
||||
every { sendDataStateFlow } returns mutableSendDataFlow
|
||||
}
|
||||
private val mutableEffectiveSendPolicyFlow = MutableStateFlow(DEFAULT_EFFECTIVE_SEND_POLICY)
|
||||
private val policyManager: PolicyManager = mockk {
|
||||
every { getEffectiveSendPolicy() } returns DEFAULT_EFFECTIVE_SEND_POLICY
|
||||
every { getEffectiveSendPolicyFlow() } returns emptyFlow()
|
||||
every { getEffectiveSendPolicy() } answers { mutableEffectiveSendPolicyFlow.value }
|
||||
every { getEffectiveSendPolicyFlow() } returns mutableEffectiveSendPolicyFlow
|
||||
}
|
||||
|
||||
private val networkConnectionManager: NetworkConnectionManager = mockk {
|
||||
@@ -129,6 +130,115 @@ class SendViewModelTest : BaseViewModelTest() {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `AddSendClick should still display SelectSendAddType dialog when both types are allowed`() {
|
||||
mutableEffectiveSendPolicyFlow.value = DEFAULT_EFFECTIVE_SEND_POLICY.copy(
|
||||
allowedSendTypes = listOf(SendTypeJson.TEXT, SendTypeJson.FILE),
|
||||
)
|
||||
val viewModel = createViewModel()
|
||||
viewModel.trySendAction(SendAction.AddSendClick)
|
||||
assertEquals(
|
||||
DEFAULT_STATE.copy(dialogState = SendState.DialogState.SelectSendAddType),
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `AddSendClick should skip the type dialog when only text sends are allowed`() = runTest {
|
||||
mutableEffectiveSendPolicyFlow.value = DEFAULT_EFFECTIVE_SEND_POLICY.copy(
|
||||
allowedSendTypes = listOf(SendTypeJson.TEXT),
|
||||
)
|
||||
val viewModel = createViewModel()
|
||||
viewModel.eventFlow.test {
|
||||
viewModel.trySendAction(SendAction.AddSendClick)
|
||||
assertEquals(SendEvent.NavigateNewSend(sendType = SendItemType.TEXT), awaitItem())
|
||||
}
|
||||
assertEquals(
|
||||
DEFAULT_STATE.copy(singleAllowedSendType = SendItemType.TEXT),
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `AddSendClick should require premium when only file sends are allowed`() {
|
||||
mutableEffectiveSendPolicyFlow.value = DEFAULT_EFFECTIVE_SEND_POLICY.copy(
|
||||
allowedSendTypes = listOf(SendTypeJson.FILE),
|
||||
)
|
||||
mutableUserStateFlow.value = DEFAULT_USER_STATE.copy(
|
||||
accounts = listOf(DEFAULT_USER_ACCOUNT_STATE.copy(isPremium = false)),
|
||||
)
|
||||
val viewModel = createViewModel()
|
||||
|
||||
viewModel.trySendAction(SendAction.AddSendClick)
|
||||
|
||||
assertEquals(
|
||||
DEFAULT_STATE.copy(
|
||||
dialogState = SendState.DialogState.FileTypeRequiresPremium,
|
||||
singleAllowedSendType = SendItemType.FILE,
|
||||
),
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `AddSendClick should warn when only file sends are allowed and sends are disabled`() {
|
||||
mutableEffectiveSendPolicyFlow.value = DEFAULT_EFFECTIVE_SEND_POLICY.copy(
|
||||
allowedSendTypes = listOf(SendTypeJson.FILE),
|
||||
disableSend = true,
|
||||
)
|
||||
val viewModel = createViewModel()
|
||||
|
||||
viewModel.trySendAction(SendAction.AddSendClick)
|
||||
|
||||
assertEquals(
|
||||
DEFAULT_STATE.copy(
|
||||
dialogState = SendState.DialogState.Error(
|
||||
title = null,
|
||||
message = BitwardenString.send_disabled_warning.asText(),
|
||||
),
|
||||
policyDisablesSend = true,
|
||||
singleAllowedSendType = SendItemType.FILE,
|
||||
),
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `policyDisablesSend should update when the effective send policy disables sends`() =
|
||||
runTest {
|
||||
val viewModel = createViewModel()
|
||||
|
||||
viewModel.stateFlow.test {
|
||||
assertEquals(DEFAULT_STATE, awaitItem())
|
||||
|
||||
// While the send controls flag is disabled this is driven by the legacy
|
||||
// disable-send policy, which must continue to surface the policy warning.
|
||||
mutableEffectiveSendPolicyFlow.value =
|
||||
DEFAULT_EFFECTIVE_SEND_POLICY.copy(disableSend = true)
|
||||
|
||||
assertEquals(DEFAULT_STATE.copy(policyDisablesSend = true), awaitItem())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `state should update when the allowed send types change while the screen is open`() =
|
||||
runTest {
|
||||
val viewModel = createViewModel()
|
||||
|
||||
viewModel.stateFlow.test {
|
||||
assertEquals(DEFAULT_STATE, awaitItem())
|
||||
|
||||
mutableEffectiveSendPolicyFlow.value = DEFAULT_EFFECTIVE_SEND_POLICY.copy(
|
||||
allowedSendTypes = listOf(SendTypeJson.FILE),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
DEFAULT_STATE.copy(singleAllowedSendType = SendItemType.FILE),
|
||||
awaitItem(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `AddSendSelected with text type should emit NavigateNewSend`() = runTest {
|
||||
val viewModel = createViewModel()
|
||||
@@ -141,6 +251,8 @@ class SendViewModelTest : BaseViewModelTest() {
|
||||
|
||||
@Test
|
||||
fun `AddSendSelected with file type and disabled send policy should display warning dialog`() {
|
||||
mutableEffectiveSendPolicyFlow.value =
|
||||
DEFAULT_EFFECTIVE_SEND_POLICY.copy(disableSend = true)
|
||||
val state = DEFAULT_STATE.copy(policyDisablesSend = true)
|
||||
val viewModel = createViewModel(state = state)
|
||||
viewModel.trySendAction(SendAction.AddSendSelected(sendType = SendItemType.FILE))
|
||||
@@ -819,6 +931,7 @@ private val DEFAULT_STATE: SendState = SendState(
|
||||
dialogState = null,
|
||||
isPullToRefreshSettingEnabled = false,
|
||||
policyDisablesSend = false,
|
||||
singleAllowedSendType = null,
|
||||
isRefreshing = false,
|
||||
isPremiumUser = false,
|
||||
)
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.x8bit.bitwarden.ui.tools.feature.send.util
|
||||
|
||||
import com.bitwarden.network.model.SendTypeJson
|
||||
import com.bitwarden.send.SendType
|
||||
import com.x8bit.bitwarden.ui.tools.feature.send.model.SendItemType
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class SendTypeExtensionsTest {
|
||||
|
||||
@Test
|
||||
fun `toSendItemType should map each SendType to its matching SendItemType`() {
|
||||
assertEquals(SendItemType.FILE, SendType.FILE.toSendItemType())
|
||||
assertEquals(SendItemType.TEXT, SendType.TEXT.toSendItemType())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `toSendItemType should map each SendTypeJson to its matching SendItemType`() {
|
||||
assertEquals(SendItemType.FILE, SendTypeJson.FILE.toSendItemType())
|
||||
assertEquals(SendItemType.TEXT, SendTypeJson.TEXT.toSendItemType())
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user