Merge branch 'fix/2284_update-conversation-object-when-changing-message-starred-status' into 'develop'

Update conversations when performing star/unstar action on messages

See merge request android/mail/proton-mail-android!782
This commit is contained in:
Stefanija Boshkovska 2021-11-02 14:38:37 +00:00
commit b5b23db6ca
12 changed files with 359 additions and 43 deletions

View File

@ -77,6 +77,7 @@ import ch.protonmail.android.usecase.VerifyConnection
import ch.protonmail.android.usecase.delete.DeleteMessage
import ch.protonmail.android.usecase.fetch.FetchVerificationKeys
import ch.protonmail.android.usecase.message.ChangeMessagesReadStatus
import ch.protonmail.android.usecase.message.ChangeMessagesStarredStatus
import ch.protonmail.android.utils.AppUtil
import ch.protonmail.android.utils.DownloadUtils
import ch.protonmail.android.utils.Event
@ -139,6 +140,7 @@ internal class MessageDetailsViewModel @Inject constructor(
private val conversationRepository: ConversationsRepository,
private val changeMessagesReadStatus: ChangeMessagesReadStatus,
private val changeConversationsReadStatus: ChangeConversationsReadStatus,
private val changeMessagesStarredStatus: ChangeMessagesStarredStatus,
private val changeConversationsStarredStatus: ChangeConversationsStarredStatus,
private val deleteMessage: DeleteMessage,
private val deleteConversations: DeleteConversations,
@ -766,26 +768,34 @@ internal class MessageDetailsViewModel @Inject constructor(
fun handleStarUnStar(messageOrConversationId: String, isChecked: Boolean) {
val ids = listOf(messageOrConversationId)
val primaryUserId = userManager.requireCurrentUserId()
if (isConversationEnabled()) {
viewModelScope.launch {
viewModelScope.launch {
if (isConversationEnabled()) {
val starAction = if (isChecked) {
ChangeConversationsStarredStatus.Action.ACTION_STAR
} else {
ChangeConversationsStarredStatus.Action.ACTION_UNSTAR
}
val primaryUserId = userManager.requireCurrentUserId()
changeConversationsStarredStatus(
ids,
primaryUserId,
starAction
)
}
} else {
if (isChecked) {
messageRepository.starMessages(ids)
} else {
messageRepository.unStarMessages(ids)
if (isChecked) {
changeMessagesStarredStatus(
primaryUserId,
ids,
ChangeMessagesStarredStatus.Action.ACTION_STAR
)
} else {
changeMessagesStarredStatus(
primaryUserId,
ids,
ChangeMessagesStarredStatus.Action.ACTION_UNSTAR
)
}
}
}
}

View File

@ -51,6 +51,7 @@ import ch.protonmail.android.settings.pin.viewmodel.PinFragmentViewModelFactory
import ch.protonmail.android.usecase.VerifyConnection
import ch.protonmail.android.usecase.delete.DeleteMessage
import ch.protonmail.android.usecase.message.ChangeMessagesReadStatus
import ch.protonmail.android.usecase.message.ChangeMessagesStarredStatus
import ch.protonmail.android.viewmodel.ManageLabelsDialogViewModel
import com.birbit.android.jobqueue.JobManager
import dagger.Module
@ -109,6 +110,7 @@ internal class ViewModelModule {
observeConversationModeEnabled: ObserveConversationModeEnabled,
changeMessagesReadStatus: ChangeMessagesReadStatus,
changeConversationsReadStatus: ChangeConversationsReadStatus,
changeMessagesStarredStatus: ChangeMessagesStarredStatus,
changeConversationsStarredStatus: ChangeConversationsStarredStatus,
observeMessagesByLocation: ObserveMessagesByLocation,
observeAllUnreadCounters: ObserveAllUnreadCounters,
@ -136,6 +138,7 @@ internal class ViewModelModule {
observeConversationModeEnabled = observeConversationModeEnabled,
changeMessagesReadStatus = changeMessagesReadStatus,
changeConversationsReadStatus = changeConversationsReadStatus,
changeMessagesStarredStatus = changeMessagesStarredStatus,
changeConversationsStarredStatus = changeConversationsStarredStatus,
observeAllUnreadCounters = observeAllUnreadCounters,
moveConversationsToFolder = moveConversationsToFolder,

View File

@ -56,6 +56,7 @@ import ch.protonmail.android.mailbox.domain.model.GetOneConversationParameters
import ch.protonmail.android.mailbox.domain.model.UnreadCounter
import ch.protonmail.android.mailbox.domain.model.createBookmarkParametersOr
import ch.protonmail.android.usecase.message.ChangeMessagesReadStatus
import ch.protonmail.android.usecase.message.ChangeMessagesStarredStatus
import com.dropbox.android.external.store4.Fetcher
import com.dropbox.android.external.store4.SourceOfTruth
import com.dropbox.android.external.store4.StoreBuilder
@ -316,6 +317,32 @@ internal class ConversationsRepositoryImpl @Inject constructor(
return ConversationsActionResult.Success
}
override suspend fun updateConvosBasedOnMessagesStarredStatus(
userId: UserId,
messageIds: List<String>,
action: ChangeMessagesStarredStatus.Action
) {
messageIds.forEach forEachMessageId@{ messageId ->
val message = messageDao.findMessageByIdOnce(messageId) ?: return@forEachMessageId
val conversation = message.conversationId?.let {
conversationDao.findConversation(userId.id, it)
} ?: return@forEachMessageId
val labels = updateLabelsAfterMessageAction(
message,
conversation.labels,
Constants.MessageLocationType.STARRED.messageLocationTypeValue.toString(),
action == ChangeMessagesStarredStatus.Action.ACTION_STAR
)
conversationDao.update(
conversation.copy(
labels = labels
)
)
}
}
override suspend fun moveToFolder(
conversationIds: List<String>,
userId: UserId,
@ -419,9 +446,10 @@ internal class ConversationsRepositoryImpl @Inject constructor(
var labels = conversation.labels
message.allLabelIDs.forEach { labelId ->
labels = updateLabelsAfterMessageAction(
labelId,
message,
labels,
message
labelId,
false
)
}
conversationDao.update(
@ -613,23 +641,34 @@ internal class ConversationsRepositoryImpl @Inject constructor(
}
private fun updateLabelsAfterMessageAction(
labelId: String,
message: Message,
labels: List<LabelContextDatabaseModel>,
message: Message
labelId: String,
shouldAddMessageToLabel: Boolean // true == add message to label; false == remove message from label
): List<LabelContextDatabaseModel> {
val label = labels.find { it.id == labelId }
val updatedLabels = labels.filterNot { it.id == labelId }.toMutableList()
if (label != null && label.contextNumMessages > 1) {
val updatedLabel = label.copy(
id = label.id,
val updatedLabel = if (shouldAddMessageToLabel) {
LabelContextDatabaseModel(
id = labelId,
contextNumUnread = label?.contextNumUnread ?: 0 + message.Unread.toInt(),
contextNumMessages = label?.contextNumMessages ?: 0 + 1,
contextTime = max(label?.contextTime ?: 0, message.time),
contextSize = label?.contextSize ?: 0 + message.totalSize.toInt(),
contextNumAttachments = label?.contextNumAttachments ?: 0 + message.numAttachments
)
} else if (label != null && label.contextNumMessages > 1) {
LabelContextDatabaseModel(
id = labelId,
contextNumUnread = label.contextNumUnread - message.Unread.toInt(),
contextNumMessages = label.contextNumMessages - 1,
contextTime = label.contextTime,
contextSize = label.contextSize - message.totalSize.toInt(),
contextNumAttachments = label.contextNumAttachments - message.numAttachments
)
updatedLabels.add(updatedLabel)
}
} else null
updatedLabel?.let { updatedLabels.add(updatedLabel) }
return updatedLabels
}

View File

@ -27,6 +27,7 @@ import ch.protonmail.android.mailbox.domain.model.ConversationsActionResult
import ch.protonmail.android.mailbox.domain.model.GetAllConversationsParameters
import ch.protonmail.android.mailbox.domain.model.UnreadCounter
import ch.protonmail.android.usecase.message.ChangeMessagesReadStatus
import ch.protonmail.android.usecase.message.ChangeMessagesStarredStatus
import kotlinx.coroutines.flow.Flow
import me.proton.core.domain.arch.DataResult
import me.proton.core.domain.entity.UserId
@ -97,6 +98,12 @@ interface ConversationsRepository {
suspend fun unstar(conversationIds: List<String>, userId: UserId): ConversationsActionResult
suspend fun updateConvosBasedOnMessagesStarredStatus(
userId: UserId,
messageIds: List<String>,
action: ChangeMessagesStarredStatus.Action
)
suspend fun moveToFolder(
conversationIds: List<String>,
userId: UserId,

View File

@ -38,7 +38,6 @@ import ch.protonmail.android.domain.loadMoreMap
import ch.protonmail.android.drawer.presentation.mapper.DrawerFoldersAndLabelsSectionUiModelMapper
import ch.protonmail.android.drawer.presentation.model.DrawerFoldersAndLabelsSectionUiModel
import ch.protonmail.android.jobs.ApplyLabelJob
import ch.protonmail.android.jobs.PostStarJob
import ch.protonmail.android.jobs.RemoveLabelJob
import ch.protonmail.android.labels.domain.LabelRepository
import ch.protonmail.android.labels.domain.model.Label
@ -68,6 +67,7 @@ import ch.protonmail.android.ui.model.LabelChipUiModel
import ch.protonmail.android.usecase.VerifyConnection
import ch.protonmail.android.usecase.delete.DeleteMessage
import ch.protonmail.android.usecase.message.ChangeMessagesReadStatus
import ch.protonmail.android.usecase.message.ChangeMessagesStarredStatus
import ch.protonmail.android.utils.Event
import ch.protonmail.android.utils.UiUtil
import ch.protonmail.android.utils.UserUtils
@ -125,6 +125,7 @@ internal class MailboxViewModel @Inject constructor(
private val observeConversationsByLocation: ObserveConversationsByLocation,
private val changeMessagesReadStatus: ChangeMessagesReadStatus,
private val changeConversationsReadStatus: ChangeConversationsReadStatus,
private val changeMessagesStarredStatus: ChangeMessagesStarredStatus,
private val changeConversationsStarredStatus: ChangeConversationsStarredStatus,
private val observeAllUnreadCounters: ObserveAllUnreadCounters,
private val moveConversationsToFolder: MoveConversationsToFolder,
@ -723,16 +724,20 @@ internal class MailboxViewModel @Inject constructor(
}
fun star(ids: List<String>, userId: UserId, location: Constants.MessageLocationType) {
if (conversationModeEnabled(location)) {
viewModelScope.launch {
viewModelScope.launch {
if (conversationModeEnabled(location)) {
changeConversationsStarredStatus(
ids,
userId,
ChangeConversationsStarredStatus.Action.ACTION_STAR
)
} else {
changeMessagesStarredStatus(
userId,
ids,
ChangeMessagesStarredStatus.Action.ACTION_STAR
)
}
} else {
jobManager.addJobInBackground(PostStarJob(ids))
}
}

View File

@ -35,6 +35,7 @@ import ch.protonmail.android.repository.MessageRepository
import ch.protonmail.android.ui.actionsheet.model.ActionSheetTarget
import ch.protonmail.android.usecase.delete.DeleteMessage
import ch.protonmail.android.usecase.message.ChangeMessagesReadStatus
import ch.protonmail.android.usecase.message.ChangeMessagesStarredStatus
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.MutableStateFlow
@ -56,6 +57,7 @@ internal class MessageActionSheetViewModel @Inject constructor(
private val messageRepository: MessageRepository,
private val changeMessagesReadStatus: ChangeMessagesReadStatus,
private val changeConversationsReadStatus: ChangeConversationsReadStatus,
private val changeMessagesStarredStatus: ChangeMessagesStarredStatus,
private val changeConversationsStarredStatus: ChangeConversationsStarredStatus,
private val conversationModeEnabled: ConversationModeEnabled,
private val accountManager: AccountManager
@ -164,9 +166,9 @@ internal class MessageActionSheetViewModel @Inject constructor(
shallIgnoreLocationInConversationResolution: Boolean = false
) {
viewModelScope.launch {
if (isActionAppliedToConversation(location, shallIgnoreLocationInConversationResolution)) {
val primaryUserId = accountManager.getPrimaryUserId().first()
if (primaryUserId != null) {
val primaryUserId = accountManager.getPrimaryUserId().first()
if (primaryUserId != null) {
if (isActionAppliedToConversation(location, shallIgnoreLocationInConversationResolution)) {
val result = changeConversationsStarredStatus(
ids,
primaryUserId,
@ -176,10 +178,14 @@ internal class MessageActionSheetViewModel @Inject constructor(
cancel("Could not complete the action")
}
} else {
Timber.e("Primary user id is null. Cannot star message/conversation")
changeMessagesStarredStatus(
primaryUserId,
ids,
ChangeMessagesStarredStatus.Action.ACTION_STAR
)
}
} else {
messageRepository.starMessages(ids)
Timber.e("Primary user id is null. Cannot star message/conversation")
}
}.invokeOnCompletion { cancellationException ->
if (cancellationException != null) {
@ -200,9 +206,9 @@ internal class MessageActionSheetViewModel @Inject constructor(
shallIgnoreLocationInConversationResolution: Boolean = false
) {
viewModelScope.launch {
if (isActionAppliedToConversation(location, shallIgnoreLocationInConversationResolution)) {
val primaryUserId = accountManager.getPrimaryUserId().first()
if (primaryUserId != null) {
val primaryUserId = accountManager.getPrimaryUserId().first()
if (primaryUserId != null) {
if (isActionAppliedToConversation(location, shallIgnoreLocationInConversationResolution)) {
val result = changeConversationsStarredStatus(
ids,
primaryUserId,
@ -212,10 +218,14 @@ internal class MessageActionSheetViewModel @Inject constructor(
cancel("Could not complete the action")
}
} else {
Timber.e("Primary user id is null. Cannot unstar message/conversation")
changeMessagesStarredStatus(
primaryUserId,
ids,
ChangeMessagesStarredStatus.Action.ACTION_UNSTAR
)
}
} else {
messageRepository.unStarMessages(ids)
Timber.e("Primary user id is null. Cannot unstar message/conversation")
}
}.invokeOnCompletion { cancellationException ->
if (cancellationException != null) {

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2020 Proton Technologies AG
*
* This file is part of ProtonMail.
*
* ProtonMail is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonMail is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonMail. If not, see https://www.gnu.org/licenses/.
*/
package ch.protonmail.android.usecase.message
import ch.protonmail.android.mailbox.domain.ConversationsRepository
import ch.protonmail.android.repository.MessageRepository
import me.proton.core.domain.entity.UserId
import javax.inject.Inject
/**
* A use case that handles changing the starred status a messages
*/
class ChangeMessagesStarredStatus @Inject constructor(
private val messageRepository: MessageRepository,
private val conversationsRepository: ConversationsRepository
) {
suspend operator fun invoke(
userId: UserId,
messageIds: List<String>,
action: Action
) {
if (action == Action.ACTION_STAR) {
messageRepository.starMessages(messageIds)
} else {
messageRepository.unStarMessages(messageIds)
}
conversationsRepository.updateConvosBasedOnMessagesStarredStatus(
userId,
messageIds,
action
)
}
enum class Action {
ACTION_STAR,
ACTION_UNSTAR
}
}

View File

@ -72,6 +72,7 @@ import ch.protonmail.android.ui.model.LabelChipUiModel
import ch.protonmail.android.usecase.VerifyConnection
import ch.protonmail.android.usecase.delete.DeleteMessage
import ch.protonmail.android.usecase.message.ChangeMessagesReadStatus
import ch.protonmail.android.usecase.message.ChangeMessagesStarredStatus
import com.birbit.android.jobqueue.JobManager
import dagger.hilt.EntryPoints
import io.mockk.Runs
@ -137,6 +138,8 @@ class MailboxViewModelTest : ArchTest, CoroutinesTest {
private val changeConversationsReadStatus: ChangeConversationsReadStatus = mockk()
private val changeMessagesStarredStatus: ChangeMessagesStarredStatus = mockk()
private val changeConversationsStarredStatus: ChangeConversationsStarredStatus = mockk()
private val moveConversationsToFolder: MoveConversationsToFolder = mockk()
@ -220,6 +223,7 @@ class MailboxViewModelTest : ArchTest, CoroutinesTest {
observeConversationsByLocation = observeConversationsByLocation,
changeMessagesReadStatus = changeMessagesReadStatus,
changeConversationsReadStatus = changeConversationsReadStatus,
changeMessagesStarredStatus = changeMessagesStarredStatus,
changeConversationsStarredStatus = changeConversationsStarredStatus,
observeAllUnreadCounters = mockk(),
moveConversationsToFolder = moveConversationsToFolder,

View File

@ -65,6 +65,7 @@ import ch.protonmail.android.usecase.VerifyConnection
import ch.protonmail.android.usecase.delete.DeleteMessage
import ch.protonmail.android.usecase.fetch.FetchVerificationKeys
import ch.protonmail.android.usecase.message.ChangeMessagesReadStatus
import ch.protonmail.android.usecase.message.ChangeMessagesStarredStatus
import ch.protonmail.android.utils.DownloadUtils
import io.mockk.Runs
import io.mockk.coEvery
@ -113,6 +114,8 @@ class MessageDetailsViewModelTest : ArchTest, CoroutinesTest {
private val changeConversationsReadStatus: ChangeConversationsReadStatus = mockk(relaxed = true)
private val changeMessagesStarredStatus: ChangeMessagesStarredStatus = mockk()
private val changeConversationsStarredStatus: ChangeConversationsStarredStatus = mockk(relaxed = true)
private val messageDetailsRepository: MessageDetailsRepository = mockk(relaxed = true)
@ -214,6 +217,7 @@ class MessageDetailsViewModelTest : ArchTest, CoroutinesTest {
conversationRepository,
changeMessagesReadStatus,
changeConversationsReadStatus,
changeMessagesStarredStatus,
changeConversationsStarredStatus,
deleteMessage,
deleteConversations,
@ -980,9 +984,11 @@ class MessageDetailsViewModelTest : ArchTest, CoroutinesTest {
inputMessageLocation.messageLocationTypeValue
coEvery { conversationModeEnabled(inputMessageLocation) } returns false
val isChecked = true
every {
messageRepository.starMessages(
listOf(inputConversationId)
coEvery {
changeMessagesStarredStatus(
any(),
listOf(inputConversationId),
ChangeMessagesStarredStatus.Action.ACTION_STAR
)
} just Runs
@ -998,13 +1004,17 @@ class MessageDetailsViewModelTest : ArchTest, CoroutinesTest {
)
}
coVerify(exactly = 1) {
messageRepository.starMessages(
listOf(inputConversationId)
changeMessagesStarredStatus(
any(),
listOf(inputConversationId),
ChangeMessagesStarredStatus.Action.ACTION_STAR
)
}
coVerify(exactly = 0) {
messageRepository.unStarMessages(
any()
changeMessagesStarredStatus(
any(),
listOf(inputConversationId),
ChangeMessagesStarredStatus.Action.ACTION_UNSTAR
)
}
}

View File

@ -73,6 +73,7 @@ import ch.protonmail.android.mailbox.domain.model.LabelContext
import ch.protonmail.android.mailbox.domain.model.MessageDomainModel
import ch.protonmail.android.mailbox.domain.model.UnreadCounter
import ch.protonmail.android.usecase.message.ChangeMessagesReadStatus
import ch.protonmail.android.usecase.message.ChangeMessagesStarredStatus
import io.mockk.Runs
import io.mockk.coEvery
import io.mockk.coVerify
@ -235,6 +236,7 @@ class ConversationsRepositoryImplTest : ArchTest {
private val messageId2 = "messageId2"
private val inboxLabelId = MessageLocationType.INBOX.messageLocationTypeValue.toString()
private val trashLabelId = MessageLocationType.TRASH.messageLocationTypeValue.toString()
private val starredLabelId = MessageLocationType.STARRED.messageLocationTypeValue.toString()
private val unlabelConversationsRemoteWorker: UnlabelConversationsRemoteWorker.Enqueuer = mockk(relaxed = true)
private val deleteConversationsRemoteWorker: DeleteConversationsRemoteWorker.Enqueuer = mockk(relaxed = true)
@ -955,6 +957,64 @@ class ConversationsRepositoryImplTest : ArchTest {
}
}
@Test
fun verifyConversationsAreUpdatedWhenMessagesAreStarred() = runBlockingTest {
// given
val action = ChangeMessagesStarredStatus.Action.ACTION_STAR
val inboxLabel = buildLabelContextDatabaseModel(
id = inboxLabelId,
contextNumUnread = 0,
contextNumMessages = 2,
contextNumAttachments = 3
)
val starredLabel = buildLabelContextDatabaseModel(
id = starredLabelId,
contextNumUnread = 1,
contextNumMessages = 1,
contextTime = 123,
contextSize = 123,
contextNumAttachments = 2
)
val conversation1 = buildConversationDatabaseModel(
userId = testUserId.id,
id = conversationId1,
numMessages = 2,
numUnread = 0,
numAttachments = 3,
labels = listOf(inboxLabel)
)
val updatedConversation1 = buildConversationDatabaseModel(
userId = testUserId.id,
id = conversationId1,
numMessages = 2,
numUnread = 0,
numAttachments = 3,
labels = listOf(inboxLabel, starredLabel)
)
val message1 = Message(
conversationId = conversationId1,
Unread = true,
time = 123,
totalSize = 123,
numAttachments = 2
)
coEvery { messageDao.findMessageByIdOnce(messageId1) } returns message1
coEvery { conversationDao.findConversation(testUserId.id, conversationId1) } returns conversation1
coEvery { conversationDao.update(updatedConversation1) } returns 123
// when
conversationsRepository.updateConvosBasedOnMessagesStarredStatus(
testUserId,
listOf(messageId1),
action
)
// then
coVerify {
conversationDao.update(updatedConversation1)
}
}
@Test
fun verifyConversationsAndMessagesAreMovedToFolder() {
runBlockingTest {

View File

@ -37,6 +37,7 @@ import ch.protonmail.android.ui.actionsheet.MessageActionSheetViewModel
import ch.protonmail.android.ui.actionsheet.model.ActionSheetTarget
import ch.protonmail.android.usecase.delete.DeleteMessage
import ch.protonmail.android.usecase.message.ChangeMessagesReadStatus
import ch.protonmail.android.usecase.message.ChangeMessagesStarredStatus
import io.mockk.Called
import io.mockk.MockKAnnotations
import io.mockk.Runs
@ -74,6 +75,9 @@ class MessageActionSheetViewModelTest : ArchTest, CoroutinesTest {
@MockK
private lateinit var changeConversationsReadStatus: ChangeConversationsReadStatus
@MockK
private lateinit var changeMessagesStarredStatus: ChangeMessagesStarredStatus
@MockK
private lateinit var changeConversationsStarredStatus: ChangeConversationsStarredStatus
@ -109,6 +113,7 @@ class MessageActionSheetViewModelTest : ArchTest, CoroutinesTest {
messageRepository,
changeMessagesReadStatus,
changeConversationsReadStatus,
changeMessagesStarredStatus,
changeConversationsStarredStatus,
conversationModeEnabled,
accountManager
@ -396,12 +401,18 @@ class MessageActionSheetViewModelTest : ArchTest, CoroutinesTest {
// given
val messageId = "messageId3"
val expected = MessageActionSheetAction.ChangeStarredStatus(true, isSuccessful = true)
val userId = UserId("userId")
every { conversationModeEnabled(any()) } returns true
every { messageRepository.starMessages(listOf(messageId)) } just Runs
coEvery {
changeMessagesStarredStatus(
userId,
listOf(messageId),
ChangeMessagesStarredStatus.Action.ACTION_STAR
)
} just Runs
every {
savedStateHandle.get<ActionSheetTarget>("extra_arg_action_sheet_actions_target")
} returns ActionSheetTarget.MESSAGE_ITEM_WITHIN_CONVERSATION_DETAIL_SCREEN
val userId = UserId("userId")
every { accountManager.getPrimaryUserId() } returns flowOf(userId)
coEvery { changeConversationsStarredStatus(any(), any(), any()) } returns ConversationsActionResult.Success
@ -413,8 +424,13 @@ class MessageActionSheetViewModelTest : ArchTest, CoroutinesTest {
// then
assertEquals(expected, viewModel.actionsFlow.value)
verify { messageRepository.starMessages(listOf(messageId)) }
verify { accountManager wasNot Called }
coVerify {
changeMessagesStarredStatus(
userId,
listOf(messageId),
ChangeMessagesStarredStatus.Action.ACTION_STAR
)
}
}
@Test

View File

@ -0,0 +1,95 @@
/*
* Copyright (c) 2020 Proton Technologies AG
*
* This file is part of ProtonMail.
*
* ProtonMail is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonMail is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonMail. If not, see https://www.gnu.org/licenses/.
*/
package ch.protonmail.android.usecase.message
import ch.protonmail.android.mailbox.domain.ConversationsRepository
import ch.protonmail.android.repository.MessageRepository
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.just
import io.mockk.mockk
import io.mockk.runs
import kotlinx.coroutines.test.runBlockingTest
import me.proton.core.domain.entity.UserId
import kotlin.test.Test
/**
* Tests the behaviour of [ChangeMessagesStarredStatus]
*/
class ChangeMessagesStarredStatusTest {
private val messageIds = listOf("messageId1", "messageId2")
private val userId = UserId("userId")
private val messageRepository: MessageRepository = mockk {
coEvery { starMessages(messageIds) } just runs
coEvery { unStarMessages(messageIds) } just runs
}
private val conversationsRepository: ConversationsRepository = mockk {
coEvery {
updateConvosBasedOnMessagesStarredStatus(
userId,
messageIds,
any()
)
} just runs
}
private val changeMessagesStarredStatus = ChangeMessagesStarredStatus(messageRepository, conversationsRepository)
@Test
fun verifyCorrectMethodsAreCalledWhenActionIsStar() = runBlockingTest {
// given
val action = ChangeMessagesStarredStatus.Action.ACTION_STAR
// when
changeMessagesStarredStatus(userId, messageIds, action)
// then
coVerify {
messageRepository.starMessages(messageIds)
conversationsRepository.updateConvosBasedOnMessagesStarredStatus(
userId,
messageIds,
action
)
}
}
@Test
fun verifyCorrectMethodsAreCalledWhenActionIsUnstar() = runBlockingTest {
// given
val action = ChangeMessagesStarredStatus.Action.ACTION_UNSTAR
// when
changeMessagesStarredStatus(userId, messageIds, action)
// then
coVerify {
messageRepository.unStarMessages(messageIds)
conversationsRepository.updateConvosBasedOnMessagesStarredStatus(
userId,
messageIds,
action
)
}
}
}