Skip to content

Commit

Permalink
fix: muting conversations when archiving (#2123)
Browse files Browse the repository at this point in the history
  • Loading branch information
gongracr authored Oct 10, 2023
1 parent 78e9b2f commit fa037c3
Show file tree
Hide file tree
Showing 2 changed files with 191 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package com.wire.kalium.logic.feature.conversation

import com.wire.kalium.logic.data.conversation.ConversationRepository
import com.wire.kalium.logic.data.conversation.MutedConversationStatus
import com.wire.kalium.logic.data.id.ConversationId
import com.wire.kalium.logic.functional.flatMap
import com.wire.kalium.logic.functional.fold
Expand Down Expand Up @@ -63,6 +64,27 @@ internal class UpdateConversationArchivedStatusUseCaseImpl(
}, {
kaliumLogger.d("Successfully updated remotely and locally convId (${conversationId.toLogString()}) archiving " +
"status to archived = ($shouldArchiveConversation)")

// Now we should make sure the conversation gets muted if it's archived or un-muted if it's unarchived
val updatedMutedStatus = if (shouldArchiveConversation) {
MutedConversationStatus.AllMuted
} else {
MutedConversationStatus.AllAllowed
}
conversationRepository.updateMutedStatusRemotely(conversationId, updatedMutedStatus, archivedStatusTimestamp)
.flatMap {
conversationRepository.updateMutedStatusLocally(conversationId, updatedMutedStatus, archivedStatusTimestamp)
}.fold({
kaliumLogger.e(
"Something went wrong when updating the muting status of the convId: " +
"(${conversationId.toLogString()}) to (${updatedMutedStatus.status}"
)
}, {
kaliumLogger.d(
"Successfully updated remotely and locally the muting status of the convId: " +
"(${conversationId.toLogString()}) to (${updatedMutedStatus.status}")
})
// Even if the muting status update fails, we should still return success as the archived status update was successful
ArchiveStatusUpdateResult.Success
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,49 +31,37 @@ import io.mockative.mock
import io.mockative.once
import io.mockative.verify
import kotlinx.coroutines.test.runTest
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue

class UpdateConversationArchivedStatusUseCaseTest {
@Mock
private val conversationRepository: ConversationRepository = mock(ConversationRepository::class)

private lateinit var updateConversationArchivedStatus: UpdateConversationArchivedStatusUseCase

@BeforeTest
fun setup() {
updateConversationArchivedStatus = UpdateConversationArchivedStatusUseCaseImpl(conversationRepository)
}

@Test
fun givenAConversationId_whenInvokingAnArchivedStatusChange_thenShouldDelegateTheCallAndReturnASuccessResult() = runTest {
val conversationId = TestConversation.ID
val isConversationArchived = true
val archivedStatusTimestamp = 123456789L

given(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusRemotely)
.whenInvokedWith(any(), any(), any())
.thenReturn(Either.Right(Unit))

given(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusLocally)
.whenInvokedWith(any(), any(), any())
.thenReturn(Either.Right(Unit))
val (arrangement, updateConversationArchivedStatus) = Arrangement()
.withSuccessfulMutingUpdates()
.withUpdateArchivedStatusFullSuccess()
.arrange()

val result = updateConversationArchivedStatus(conversationId, isConversationArchived, archivedStatusTimestamp)
assertEquals(ArchiveStatusUpdateResult.Success::class, result::class)

verify(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusRemotely)
.with(any(), eq(isConversationArchived), matching { it == archivedStatusTimestamp })
.wasInvoked(exactly = once)

verify(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusLocally)
.with(any(), eq(isConversationArchived), matching { it == archivedStatusTimestamp })
.wasInvoked(exactly = once)
with(arrangement) {
verify(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusRemotely)
.with(any(), eq(isConversationArchived), matching { it == archivedStatusTimestamp })
.wasInvoked(exactly = once)

verify(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusLocally)
.with(any(), eq(isConversationArchived), matching { it == archivedStatusTimestamp })
.wasInvoked(exactly = once)
}
}

@Test
Expand All @@ -82,24 +70,25 @@ class UpdateConversationArchivedStatusUseCaseTest {
val isConversationArchived = true
val archivedStatusTimestamp = 123456789L

given(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusRemotely)
.whenInvokedWith(any(), any(), any())
.thenReturn(Either.Left(NetworkFailure.ServerMiscommunication(RuntimeException("some error"))))
val (arrangement, updateConversationArchivedStatus) = Arrangement()
.withSuccessfulMutingUpdates()
.withRemoteUpdateArchivedStatusFailure()
.arrange()

val result = updateConversationArchivedStatus(conversationId, isConversationArchived, archivedStatusTimestamp)
assertEquals(ArchiveStatusUpdateResult.Failure::class, result::class)

verify(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusRemotely)
.with(any(), eq(isConversationArchived), matching { it == archivedStatusTimestamp })
.wasInvoked(exactly = once)

verify(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusLocally)
.with(any(), eq(isConversationArchived), matching { it == archivedStatusTimestamp })
.wasNotInvoked()

with(arrangement) {
verify(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusRemotely)
.with(any(), eq(isConversationArchived), matching { it == archivedStatusTimestamp })
.wasInvoked(exactly = once)

verify(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusLocally)
.with(any(), eq(isConversationArchived), matching { it == archivedStatusTimestamp })
.wasNotInvoked()
}
}

@Test
Expand All @@ -108,26 +97,148 @@ class UpdateConversationArchivedStatusUseCaseTest {
val isConversationArchived = true
val archivedStatusTimestamp = 123456789L

given(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusRemotely)
.whenInvokedWith(any(), any(), any())
.thenReturn(Either.Right(Unit))
given(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusLocally)
.whenInvokedWith(any(), any(), any())
.thenReturn(Either.Left(StorageFailure.DataNotFound))
val (arrangement, updateConversationArchivedStatus) = Arrangement()
.withLocalUpdateArchivedStatusFailure()
.withSuccessfulMutingUpdates()
.arrange()

val result = updateConversationArchivedStatus(conversationId, isConversationArchived, archivedStatusTimestamp)
assertEquals(ArchiveStatusUpdateResult.Failure::class, result::class)

verify(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusRemotely)
.with(any(), eq(isConversationArchived), matching { it == archivedStatusTimestamp })
.wasInvoked(exactly = once)
with(arrangement) {
verify(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusRemotely)
.with(any(), eq(isConversationArchived), matching { it == archivedStatusTimestamp })
.wasInvoked(exactly = once)

verify(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusLocally)
.with(any(), eq(isConversationArchived), matching { it == archivedStatusTimestamp })
.wasInvoked(exactly = once)
}
}

verify(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusLocally)
.with(any(), eq(isConversationArchived), matching { it == archivedStatusTimestamp })
.wasInvoked(exactly = once)
@Test
fun givenAConversationId_whenInvokingAnArchivedStatusChangeAndFailsUpdatingRemoteMutingStatus_thenItShouldStillReturnASuccessResult() =
runTest {
val conversationId = TestConversation.ID
val isConversationArchived = true
val archivedStatusTimestamp = 123456789L

val (arrangement, updateConversationArchivedStatus) = Arrangement()
.withUpdateArchivedStatusFullSuccess()
.withRemoteErrorMutingUpdates()
.arrange()

val result = updateConversationArchivedStatus(conversationId, isConversationArchived, archivedStatusTimestamp)
assertTrue(result is ArchiveStatusUpdateResult.Success)

with(arrangement) {
verify(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusRemotely)
.with(any(), eq(isConversationArchived), matching { it == archivedStatusTimestamp })
.wasInvoked(exactly = once)

verify(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusLocally)
.with(any(), eq(isConversationArchived), matching { it == archivedStatusTimestamp })
.wasInvoked(exactly = once)
}
}

@Test
fun givenAConversationId_whenInvokingAnArchivedStatusChangeAndFailsUpdatingLocalMutingStatus_thenItShouldStillReturnASuccessResult() =
runTest {
val conversationId = TestConversation.ID
val isConversationArchived = true
val archivedStatusTimestamp = 123456789L

val (arrangement, updateConversationArchivedStatus) = Arrangement()
.withUpdateArchivedStatusFullSuccess()
.withLocalErrorMutingUpdates()
.arrange()

val result = updateConversationArchivedStatus(conversationId, isConversationArchived, archivedStatusTimestamp)
assertTrue(result is ArchiveStatusUpdateResult.Success)

with(arrangement) {
verify(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusRemotely)
.with(any(), eq(isConversationArchived), matching { it == archivedStatusTimestamp })
.wasInvoked(exactly = once)

verify(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusLocally)
.with(any(), eq(isConversationArchived), matching { it == archivedStatusTimestamp })
.wasInvoked(exactly = once)
}
}

private class Arrangement {
@Mock
val conversationRepository: ConversationRepository = mock(ConversationRepository::class)

private val updateArchivedStatus = UpdateConversationArchivedStatusUseCaseImpl(conversationRepository)

fun withUpdateArchivedStatusFullSuccess() = apply {
given(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusRemotely)
.whenInvokedWith(any(), any(), any())
.thenReturn(Either.Right(Unit))

given(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusLocally)
.whenInvokedWith(any(), any(), any())
.thenReturn(Either.Right(Unit))
}

fun withRemoteUpdateArchivedStatusFailure() = apply {
given(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusRemotely)
.whenInvokedWith(any(), any(), any())
.thenReturn(Either.Left(NetworkFailure.ServerMiscommunication(RuntimeException("some error"))))
}

fun withLocalUpdateArchivedStatusFailure() = apply {
given(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusRemotely)
.whenInvokedWith(any(), any(), any())
.thenReturn(Either.Right(Unit))
given(conversationRepository)
.suspendFunction(conversationRepository::updateArchivedStatusLocally)
.whenInvokedWith(any(), any(), any())
.thenReturn(Either.Left(StorageFailure.DataNotFound))
}

fun withSuccessfulMutingUpdates() = apply {
given(conversationRepository)
.suspendFunction(conversationRepository::updateMutedStatusRemotely)
.whenInvokedWith(any(), any(), any())
.thenReturn(Either.Right(Unit))
given(conversationRepository)
.suspendFunction(conversationRepository::updateMutedStatusLocally)
.whenInvokedWith(any(), any(), any())
.thenReturn(Either.Right(Unit))
}

fun withRemoteErrorMutingUpdates() = apply {
given(conversationRepository)
.suspendFunction(conversationRepository::updateMutedStatusRemotely)
.whenInvokedWith(any(), any(), any())
.thenReturn(Either.Left(NetworkFailure.NoNetworkConnection(RuntimeException("some error"))))
}

fun withLocalErrorMutingUpdates() = apply {
given(conversationRepository)
.suspendFunction(conversationRepository::updateMutedStatusRemotely)
.whenInvokedWith(any(), any(), any())
.thenReturn(Either.Right(Unit))
given(conversationRepository)
.suspendFunction(conversationRepository::updateMutedStatusLocally)
.whenInvokedWith(any(), any(), any())
.thenReturn(Either.Left(StorageFailure.DataNotFound))
}

fun arrange() = this to updateArchivedStatus
}
}

0 comments on commit fa037c3

Please sign in to comment.