mirror of
https://github.com/bitwarden/android.git
synced 2025-03-15 18:58:59 +03:00
Add support for deleting an attachment (#768)
This commit is contained in:
parent
dc3081c5d6
commit
04d60a50ff
7 changed files with 266 additions and 17 deletions
|
@ -18,11 +18,15 @@ import androidx.hilt.navigation.compose.hiltViewModel
|
|||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect
|
||||
import com.x8bit.bitwarden.ui.platform.components.BasicDialogState
|
||||
import com.x8bit.bitwarden.ui.platform.components.BitwardenBasicDialog
|
||||
import com.x8bit.bitwarden.ui.platform.components.BitwardenErrorContent
|
||||
import com.x8bit.bitwarden.ui.platform.components.BitwardenLoadingContent
|
||||
import com.x8bit.bitwarden.ui.platform.components.BitwardenLoadingDialog
|
||||
import com.x8bit.bitwarden.ui.platform.components.BitwardenScaffold
|
||||
import com.x8bit.bitwarden.ui.platform.components.BitwardenTextButton
|
||||
import com.x8bit.bitwarden.ui.platform.components.BitwardenTopAppBar
|
||||
import com.x8bit.bitwarden.ui.platform.components.LoadingDialogState
|
||||
import com.x8bit.bitwarden.ui.platform.components.NavigationIcon
|
||||
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
|
||||
import com.x8bit.bitwarden.ui.platform.theme.LocalIntentManager
|
||||
|
@ -65,6 +69,11 @@ fun AttachmentsScreen(
|
|||
}
|
||||
}
|
||||
|
||||
AttachmentsDialogs(
|
||||
dialogState = state.dialogState,
|
||||
onDismissRequest = attachmentsHandlers.onDismissRequest,
|
||||
)
|
||||
|
||||
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
|
||||
BitwardenScaffold(
|
||||
modifier = Modifier
|
||||
|
@ -109,3 +118,25 @@ fun AttachmentsScreen(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AttachmentsDialogs(
|
||||
dialogState: AttachmentsState.DialogState?,
|
||||
onDismissRequest: () -> Unit,
|
||||
) {
|
||||
when (dialogState) {
|
||||
is AttachmentsState.DialogState.Error -> BitwardenBasicDialog(
|
||||
visibilityState = BasicDialogState.Shown(
|
||||
title = dialogState.title,
|
||||
message = dialogState.message,
|
||||
),
|
||||
onDismissRequest = onDismissRequest,
|
||||
)
|
||||
|
||||
is AttachmentsState.DialogState.Loading -> BitwardenLoadingDialog(
|
||||
visibilityState = LoadingDialogState.Shown(dialogState.message),
|
||||
)
|
||||
|
||||
null -> Unit
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.bitwarden.core.CipherView
|
|||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.data.platform.repository.model.DataState
|
||||
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.DeleteAttachmentResult
|
||||
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.Text
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.asText
|
||||
|
@ -18,6 +19,8 @@ import kotlinx.coroutines.flow.launchIn
|
|||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.parcelize.IgnoredOnParcel
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -26,6 +29,7 @@ private const val KEY_STATE = "state"
|
|||
/**
|
||||
* ViewModel responsible for handling user interactions in the attachments screen.
|
||||
*/
|
||||
@Suppress("TooManyFunctions")
|
||||
@HiltViewModel
|
||||
class AttachmentsViewModel @Inject constructor(
|
||||
private val vaultRepo: VaultRepository,
|
||||
|
@ -36,6 +40,7 @@ class AttachmentsViewModel @Inject constructor(
|
|||
?: AttachmentsState(
|
||||
cipherId = AttachmentsArgs(savedStateHandle).cipherId,
|
||||
viewState = AttachmentsState.ViewState.Loading,
|
||||
dialogState = null,
|
||||
),
|
||||
) {
|
||||
init {
|
||||
|
@ -50,6 +55,7 @@ class AttachmentsViewModel @Inject constructor(
|
|||
when (action) {
|
||||
AttachmentsAction.BackClick -> handleBackClick()
|
||||
AttachmentsAction.SaveClick -> handleSaveClick()
|
||||
AttachmentsAction.DismissDialogClick -> handleDismissDialogClick()
|
||||
AttachmentsAction.ChooseFileClick -> handleChooseFileClick()
|
||||
is AttachmentsAction.FileChoose -> handleFileChoose(action)
|
||||
is AttachmentsAction.DeleteClick -> handleDeleteClick(action)
|
||||
|
@ -66,6 +72,10 @@ class AttachmentsViewModel @Inject constructor(
|
|||
// TODO: Handle saving the attachments (BIT-522)
|
||||
}
|
||||
|
||||
private fun handleDismissDialogClick() {
|
||||
mutableStateFlow.update { it.copy(dialogState = null) }
|
||||
}
|
||||
|
||||
private fun handleChooseFileClick() {
|
||||
sendEvent(AttachmentsEvent.ShowChooserSheet)
|
||||
}
|
||||
|
@ -76,13 +86,30 @@ class AttachmentsViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun handleDeleteClick(action: AttachmentsAction.DeleteClick) {
|
||||
sendEvent(AttachmentsEvent.ShowToast("Not Yet Implemented".asText()))
|
||||
// TODO: Handle choosing a file the attachments (BIT-522)
|
||||
onContent { content ->
|
||||
val cipherView = content.originalCipher ?: return@onContent
|
||||
mutableStateFlow.update {
|
||||
it.copy(
|
||||
dialogState = AttachmentsState.DialogState.Loading(
|
||||
message = R.string.deleting.asText(),
|
||||
),
|
||||
)
|
||||
}
|
||||
viewModelScope.launch {
|
||||
val result = vaultRepo.deleteCipherAttachment(
|
||||
cipherId = state.cipherId,
|
||||
attachmentId = action.attachmentId,
|
||||
cipherView = cipherView,
|
||||
)
|
||||
sendAction(AttachmentsAction.Internal.DeleteResultReceive(result))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleInternalAction(action: AttachmentsAction.Internal) {
|
||||
when (action) {
|
||||
is AttachmentsAction.Internal.CipherReceive -> handleCipherReceive(action)
|
||||
is AttachmentsAction.Internal.DeleteResultReceive -> handleDeleteResultReceive(action)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,6 +169,32 @@ class AttachmentsViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleDeleteResultReceive(action: AttachmentsAction.Internal.DeleteResultReceive) {
|
||||
when (action.result) {
|
||||
DeleteAttachmentResult.Error -> {
|
||||
mutableStateFlow.update {
|
||||
it.copy(
|
||||
dialogState = AttachmentsState.DialogState.Error(
|
||||
title = R.string.an_error_has_occurred.asText(),
|
||||
message = R.string.generic_error_message.asText(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
DeleteAttachmentResult.Success -> {
|
||||
mutableStateFlow.update { it.copy(dialogState = null) }
|
||||
sendEvent(AttachmentsEvent.ShowToast(R.string.attachment_deleted.asText()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun onContent(
|
||||
crossinline block: (AttachmentsState.ViewState.Content) -> Unit,
|
||||
) {
|
||||
(state.viewState as? AttachmentsState.ViewState.Content)?.let(block)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -151,6 +204,7 @@ class AttachmentsViewModel @Inject constructor(
|
|||
data class AttachmentsState(
|
||||
val cipherId: String,
|
||||
val viewState: ViewState,
|
||||
val dialogState: DialogState?,
|
||||
) : Parcelable {
|
||||
/**
|
||||
* Represents the specific view states for the [AttachmentsScreen].
|
||||
|
@ -174,6 +228,8 @@ data class AttachmentsState(
|
|||
*/
|
||||
@Parcelize
|
||||
data class Content(
|
||||
@IgnoredOnParcel
|
||||
val originalCipher: CipherView? = null,
|
||||
val attachments: List<AttachmentItem>,
|
||||
) : ViewState()
|
||||
}
|
||||
|
@ -187,6 +243,28 @@ data class AttachmentsState(
|
|||
val title: String,
|
||||
val displaySize: String,
|
||||
) : Parcelable
|
||||
|
||||
/**
|
||||
* Represents the current state of any dialogs on the screen.
|
||||
*/
|
||||
sealed class DialogState : Parcelable {
|
||||
/**
|
||||
* Represents a dismissible dialog with the given error [message].
|
||||
*/
|
||||
@Parcelize
|
||||
data class Error(
|
||||
val title: Text?,
|
||||
val message: Text,
|
||||
) : DialogState()
|
||||
|
||||
/**
|
||||
* Represents a loading dialog with the given [message].
|
||||
*/
|
||||
@Parcelize
|
||||
data class Loading(
|
||||
val message: Text,
|
||||
) : DialogState()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -225,6 +303,11 @@ sealed class AttachmentsAction {
|
|||
*/
|
||||
data object SaveClick : AttachmentsAction()
|
||||
|
||||
/**
|
||||
* User clicked to dismiss a dialog.
|
||||
*/
|
||||
data object DismissDialogClick : AttachmentsAction()
|
||||
|
||||
/**
|
||||
* User clicked to select a new attachment file.
|
||||
*/
|
||||
|
@ -254,5 +337,12 @@ sealed class AttachmentsAction {
|
|||
data class CipherReceive(
|
||||
val cipherDataState: DataState<CipherView?>,
|
||||
) : Internal()
|
||||
|
||||
/**
|
||||
* The result of deleting the attachment.
|
||||
*/
|
||||
data class DeleteResultReceive(
|
||||
val result: DeleteAttachmentResult,
|
||||
) : Internal()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ data class AttachmentsHandlers(
|
|||
val onChooseFileClick: () -> Unit,
|
||||
val onFileChoose: (IntentManager.FileData) -> Unit,
|
||||
val onDeleteClick: (attachmentId: String) -> Unit,
|
||||
val onDismissRequest: () -> Unit,
|
||||
) {
|
||||
companion object {
|
||||
/**
|
||||
|
@ -30,6 +31,9 @@ data class AttachmentsHandlers(
|
|||
onDeleteClick = {
|
||||
viewModel.trySendAction(AttachmentsAction.DeleteClick(it))
|
||||
},
|
||||
onDismissRequest = {
|
||||
viewModel.trySendAction(AttachmentsAction.DismissDialogClick)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import com.x8bit.bitwarden.ui.vault.feature.attachments.AttachmentsState
|
|||
*/
|
||||
fun CipherView.toViewState(): AttachmentsState.ViewState.Content =
|
||||
AttachmentsState.ViewState.Content(
|
||||
originalCipher = this,
|
||||
attachments = this
|
||||
.attachments
|
||||
.orEmpty()
|
||||
|
|
|
@ -11,6 +11,7 @@ import androidx.compose.ui.test.onNodeWithContentDescription
|
|||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockCipherView
|
||||
import com.x8bit.bitwarden.ui.platform.base.BaseComposeTest
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.asText
|
||||
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
|
||||
|
@ -76,7 +77,7 @@ class AttachmentsScreenTest : BaseComposeTest() {
|
|||
@Test
|
||||
fun `on choose file click should send ChooseFileClick`() {
|
||||
mutableStateFlow.update {
|
||||
it.copy(viewState = AttachmentsState.ViewState.Content(emptyList()))
|
||||
it.copy(viewState = DEFAULT_CONTENT_WITHOUT_ATTACHMENTS)
|
||||
}
|
||||
|
||||
composeTestRule.onNodeWithTextAfterScroll("Choose file").performClick()
|
||||
|
@ -96,7 +97,7 @@ class AttachmentsScreenTest : BaseComposeTest() {
|
|||
composeTestRule.onNode(isProgressBar).assertDoesNotExist()
|
||||
|
||||
mutableStateFlow.update {
|
||||
it.copy(viewState = AttachmentsState.ViewState.Content(emptyList()))
|
||||
it.copy(viewState = DEFAULT_CONTENT_WITHOUT_ATTACHMENTS)
|
||||
}
|
||||
composeTestRule.onNode(isProgressBar).assertDoesNotExist()
|
||||
}
|
||||
|
@ -113,7 +114,7 @@ class AttachmentsScreenTest : BaseComposeTest() {
|
|||
composeTestRule.onNodeWithText(errorMessage).assertDoesNotExist()
|
||||
|
||||
mutableStateFlow.update {
|
||||
it.copy(viewState = AttachmentsState.ViewState.Content(emptyList()))
|
||||
it.copy(viewState = DEFAULT_CONTENT_WITHOUT_ATTACHMENTS)
|
||||
}
|
||||
composeTestRule.onNodeWithText(errorMessage).assertDoesNotExist()
|
||||
}
|
||||
|
@ -121,7 +122,7 @@ class AttachmentsScreenTest : BaseComposeTest() {
|
|||
@Test
|
||||
fun `content with no items should be displayed according to state`() {
|
||||
mutableStateFlow.update {
|
||||
it.copy(viewState = AttachmentsState.ViewState.Content(emptyList()))
|
||||
it.copy(viewState = DEFAULT_CONTENT_WITHOUT_ATTACHMENTS)
|
||||
}
|
||||
composeTestRule
|
||||
.onNodeWithTextAfterScroll("There are no attachments.")
|
||||
|
@ -197,15 +198,60 @@ class AttachmentsScreenTest : BaseComposeTest() {
|
|||
viewModel.trySendAction(AttachmentsAction.DeleteClick(cipherId))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `error dialog should be displayed according to state`() {
|
||||
val errorMessage = "Fail"
|
||||
composeTestRule.onNode(isDialog()).assertDoesNotExist()
|
||||
composeTestRule.onNodeWithText(errorMessage).assertDoesNotExist()
|
||||
|
||||
mutableStateFlow.update {
|
||||
it.copy(
|
||||
dialogState = AttachmentsState.DialogState.Error(
|
||||
title = null,
|
||||
message = errorMessage.asText(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
composeTestRule
|
||||
.onNodeWithText(errorMessage)
|
||||
.assert(hasAnyAncestor(isDialog()))
|
||||
.assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `loading dialog should be displayed according to state`() {
|
||||
val loadingMessage = "deleting"
|
||||
composeTestRule.onNode(isDialog()).assertDoesNotExist()
|
||||
composeTestRule.onNodeWithText(loadingMessage).assertDoesNotExist()
|
||||
|
||||
mutableStateFlow.update {
|
||||
it.copy(dialogState = AttachmentsState.DialogState.Loading(loadingMessage.asText()))
|
||||
}
|
||||
|
||||
composeTestRule
|
||||
.onNodeWithText(loadingMessage)
|
||||
.assertIsDisplayed()
|
||||
.assert(hasAnyAncestor(isDialog()))
|
||||
}
|
||||
}
|
||||
|
||||
private val DEFAULT_STATE: AttachmentsState = AttachmentsState(
|
||||
cipherId = "cipherId-1234",
|
||||
viewState = AttachmentsState.ViewState.Loading,
|
||||
dialogState = null,
|
||||
)
|
||||
|
||||
private val DEFAULT_CONTENT_WITHOUT_ATTACHMENTS: AttachmentsState.ViewState.Content =
|
||||
AttachmentsState.ViewState.Content(
|
||||
originalCipher = createMockCipherView(number = 1),
|
||||
attachments = emptyList(),
|
||||
)
|
||||
|
||||
private val DEFAULT_CONTENT_WITH_ATTACHMENTS: AttachmentsState.ViewState.Content =
|
||||
AttachmentsState.ViewState.Content(
|
||||
originalCipher = createMockCipherView(number = 1),
|
||||
attachments = listOf(
|
||||
AttachmentsState.AttachmentItem(
|
||||
id = "cipherId-1234",
|
||||
|
|
|
@ -7,11 +7,13 @@ import com.x8bit.bitwarden.R
|
|||
import com.x8bit.bitwarden.data.platform.repository.model.DataState
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockCipherView
|
||||
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.DeleteAttachmentResult
|
||||
import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.asText
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.concat
|
||||
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
|
||||
import com.x8bit.bitwarden.ui.vault.feature.attachments.util.toViewState
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
|
@ -71,6 +73,19 @@ class AttachmentsViewModelTest : BaseViewModelTest() {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `DismissDialogClick should emit DismissDialogClick`() = runTest {
|
||||
val initialState = DEFAULT_STATE.copy(
|
||||
dialogState = AttachmentsState.DialogState.Loading("Loading".asText()),
|
||||
)
|
||||
val viewModel = createViewModel(initialState)
|
||||
viewModel.stateFlow.test {
|
||||
assertEquals(initialState, awaitItem())
|
||||
viewModel.trySendAction(AttachmentsAction.DismissDialogClick)
|
||||
assertEquals(initialState.copy(dialogState = null), awaitItem())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ChooseFileClick should emit ShowToast`() = runTest {
|
||||
val viewModel = createViewModel()
|
||||
|
@ -91,12 +106,65 @@ class AttachmentsViewModelTest : BaseViewModelTest() {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `DeleteClick should emit ShowToast`() = runTest {
|
||||
val attachmentId = "attachmentId-1234"
|
||||
fun `DeleteClick with deleteCipherAttachment error should display error dialog`() = runTest {
|
||||
val cipherId = "mockId-1"
|
||||
val attachmentId = "mockId-1"
|
||||
val cipherView = createMockCipherView(number = 1)
|
||||
val initialState = DEFAULT_STATE.copy(viewState = DEFAULT_CONTENT_WITH_ATTACHMENTS)
|
||||
coEvery {
|
||||
vaultRepository.deleteCipherAttachment(
|
||||
cipherId = cipherId,
|
||||
attachmentId = attachmentId,
|
||||
cipherView = cipherView,
|
||||
)
|
||||
} returns DeleteAttachmentResult.Error
|
||||
mutableVaultItemStateFlow.tryEmit(DataState.Loaded(cipherView))
|
||||
|
||||
val viewModel = createViewModel()
|
||||
viewModel.stateFlow.test {
|
||||
assertEquals(initialState, awaitItem())
|
||||
viewModel.actionChannel.trySend(AttachmentsAction.DeleteClick(attachmentId))
|
||||
assertEquals(
|
||||
initialState.copy(
|
||||
dialogState = AttachmentsState.DialogState.Loading(
|
||||
message = R.string.deleting.asText(),
|
||||
),
|
||||
),
|
||||
awaitItem(),
|
||||
)
|
||||
assertEquals(
|
||||
initialState.copy(
|
||||
dialogState = AttachmentsState.DialogState.Error(
|
||||
title = R.string.an_error_has_occurred.asText(),
|
||||
message = R.string.generic_error_message.asText(),
|
||||
),
|
||||
),
|
||||
awaitItem(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `DeleteClick with deleteCipherAttachment success should emit ShowToast`() = runTest {
|
||||
val cipherId = "mockId-1"
|
||||
val attachmentId = "mockId-1"
|
||||
val cipherView = createMockCipherView(number = 1)
|
||||
coEvery {
|
||||
vaultRepository.deleteCipherAttachment(
|
||||
cipherId = cipherId,
|
||||
attachmentId = attachmentId,
|
||||
cipherView = cipherView,
|
||||
)
|
||||
} returns DeleteAttachmentResult.Success
|
||||
mutableVaultItemStateFlow.tryEmit(DataState.Loaded(cipherView))
|
||||
|
||||
val viewModel = createViewModel()
|
||||
viewModel.eventFlow.test {
|
||||
viewModel.trySendAction(AttachmentsAction.DeleteClick(attachmentId))
|
||||
assertEquals(AttachmentsEvent.ShowToast("Not Yet Implemented".asText()), awaitItem())
|
||||
viewModel.actionChannel.trySend(AttachmentsAction.DeleteClick(cipherId))
|
||||
assertEquals(
|
||||
AttachmentsEvent.ShowToast(R.string.attachment_deleted.asText()),
|
||||
awaitItem(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,23 +281,25 @@ class AttachmentsViewModelTest : BaseViewModelTest() {
|
|||
vaultRepo = vaultRepository,
|
||||
savedStateHandle = SavedStateHandle().apply {
|
||||
set("state", initialState)
|
||||
set("cipher_id", initialState?.cipherId ?: "cipherId-1234")
|
||||
set("cipher_id", initialState?.cipherId ?: "mockId-1")
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private val DEFAULT_STATE: AttachmentsState = AttachmentsState(
|
||||
cipherId = "cipherId-1234",
|
||||
cipherId = "mockId-1",
|
||||
viewState = AttachmentsState.ViewState.Loading,
|
||||
dialogState = null,
|
||||
)
|
||||
|
||||
private val DEFAULT_CONTENT_WITH_ATTACHMENTS: AttachmentsState.ViewState.Content =
|
||||
AttachmentsState.ViewState.Content(
|
||||
originalCipher = createMockCipherView(number = 1),
|
||||
attachments = listOf(
|
||||
AttachmentsState.AttachmentItem(
|
||||
id = "cipherId-1234",
|
||||
title = "cool_file.png",
|
||||
displaySize = "10 MB",
|
||||
id = "mockId-1",
|
||||
title = "mockFileName-1",
|
||||
displaySize = "mockSizeName-1",
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -16,6 +16,7 @@ class CipherViewExtensionsTest {
|
|||
|
||||
assertEquals(
|
||||
AttachmentsState.ViewState.Content(
|
||||
originalCipher = cipherView,
|
||||
attachments = listOf(
|
||||
AttachmentsState.AttachmentItem(
|
||||
id = "mockId-1",
|
||||
|
@ -37,7 +38,10 @@ class CipherViewExtensionsTest {
|
|||
val result = cipherView.toViewState()
|
||||
|
||||
assertEquals(
|
||||
AttachmentsState.ViewState.Content(attachments = emptyList()),
|
||||
AttachmentsState.ViewState.Content(
|
||||
originalCipher = cipherView,
|
||||
attachments = emptyList(),
|
||||
),
|
||||
result,
|
||||
)
|
||||
}
|
||||
|
@ -55,7 +59,10 @@ class CipherViewExtensionsTest {
|
|||
val result = cipherView.toViewState()
|
||||
|
||||
assertEquals(
|
||||
AttachmentsState.ViewState.Content(attachments = emptyList()),
|
||||
AttachmentsState.ViewState.Content(
|
||||
originalCipher = cipherView,
|
||||
attachments = emptyList(),
|
||||
),
|
||||
result,
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue