From 24fd2feb3eb16f9a9de2f823cb95966618da6724 Mon Sep 17 00:00:00 2001
From: "sergei.bakhtiarov" <sbakhtiarov@gmail.com>
Date: Wed, 15 Jan 2025 11:50:23 +0100
Subject: [PATCH] fix: ignored connection stays in conversations list
 [#WPB-WPB-15212]

---
 .../data/connection/ConnectionRepository.kt   | 21 +++---
 .../connection/ConnectionRepositoryTest.kt    | 65 +++++++++++++++++--
 2 files changed, 73 insertions(+), 13 deletions(-)

diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/connection/ConnectionRepository.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/connection/ConnectionRepository.kt
index a881f84a3c5..1a3aaae82ce 100644
--- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/connection/ConnectionRepository.kt
+++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/connection/ConnectionRepository.kt
@@ -52,9 +52,9 @@ import com.wire.kalium.logic.functional.onSuccess
 import com.wire.kalium.logic.kaliumLogger
 import com.wire.kalium.logic.wrapApiRequest
 import com.wire.kalium.logic.wrapStorageRequest
-import com.wire.kalium.network.api.base.authenticated.connection.ConnectionApi
 import com.wire.kalium.network.api.authenticated.connection.ConnectionDTO
 import com.wire.kalium.network.api.authenticated.connection.ConnectionStateDTO
+import com.wire.kalium.network.api.base.authenticated.connection.ConnectionApi
 import com.wire.kalium.persistence.dao.ConnectionDAO
 import com.wire.kalium.persistence.dao.ConnectionEntity
 import com.wire.kalium.persistence.dao.UserDAO
@@ -150,15 +150,18 @@ internal class ConnectionDataSource(
     override suspend fun ignoreConnectionRequest(userId: UserId): Either<CoreFailure, Unit> =
         updateRemoteConnectionStatus(userId, IGNORED)
             .flatMapLeft {
-                if (it is NetworkFailure.FederatedBackendFailure.FailedDomains)
-                    wrapStorageRequest { connectionDAO.getConnectionByUser(userId.toDao()) }
-                        .map { connectionEntity ->
-                            val updatedConnection = connectionMapper.fromDaoToModel(connectionEntity).copy(status = IGNORED)
-                            handleUserConnectionStatusPersistence(updatedConnection)
-                        }
-                else it.left()
+                if (it is NetworkFailure.FederatedBackendFailure.FailedDomains) Either.Right(Unit) else it.left()
+            }
+            .onSuccess {
+                setConnectionStatus(userId, IGNORED)
+            }.map { Unit }
+
+    private suspend fun setConnectionStatus(userId: UserId, status: ConnectionState): Either<CoreFailure, Unit> =
+        wrapStorageRequest { connectionDAO.getConnectionByUser(userId.toDao()) }
+            .map { connectionEntity ->
+                val updatedConnection = connectionMapper.fromDaoToModel(connectionEntity).copy(status = status)
+                handleUserConnectionStatusPersistence(updatedConnection)
             }
-            .map { Unit }
 
     /**
      * Check if we can transition to the correct connection status
diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/connection/ConnectionRepositoryTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/connection/ConnectionRepositoryTest.kt
index 31b79f400ee..820b1c0969c 100644
--- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/connection/ConnectionRepositoryTest.kt
+++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/connection/ConnectionRepositoryTest.kt
@@ -318,7 +318,7 @@ class ConnectionRepositoryTest {
     }
 
     @Test
-    fun givenAConnectionRequestIgnore_WhenSendingAConnectionStatusValid_thenTheConnectionShouldBePersisted() = runTest {
+    fun givenAConnectionRequestIgnore_WhenSendingAConnectionStatusValid_thenTheConnectionShouldBeUpdated() = runTest {
         // given
         val userId = NetworkUserId("user_id", "domain_id")
         val (arrangement, connectionRepository) = Arrangement().arrange()
@@ -336,6 +336,29 @@ class ConnectionRepositoryTest {
         }.wasInvoked(exactly = once)
     }
 
+    @Test
+    fun givenAConnectionRequestIgnore_WhenSendingAConnectionStatusValid_thenTheConnectionShouldBePersisted() = runTest {
+        // given
+        val userId = NetworkUserId("user_id", "domain_id")
+        val (arrangement, connectionRepository) = Arrangement().arrange()
+        arrangement
+            .withGetConnectionByUser()
+            .withSuccessfulUpdateConnectionStatusResponse(userId)
+            .withSuccessfulFetchSelfUserConnectionsResponse(arrangement.stubUserProfileDTO)
+
+        // when
+        val result = connectionRepository.ignoreConnectionRequest(UserId(userId.value, userId.domain))
+        result.shouldSucceed { arrangement.stubConnectionOne }
+
+        // then
+        coVerify {
+            arrangement.connectionDAO.insertConnection(arrangement.stubConnectionEntity.copy(
+                lastUpdateDate = any(),
+                status = ConnectionEntity.State.IGNORED
+            ))
+        }.wasInvoked(exactly = once)
+    }
+
     @Test
     fun givenConnectionDoesNotExist_whenGettingConnection_thenErrorNotFoundShouldBeReturned() = runTest {
         // given
@@ -354,7 +377,7 @@ class ConnectionRepositoryTest {
     }
 
     @Test
-    fun givenAConnectionRequestIgnore_WhenApiUpdateFailedWithFederatedFailedDomains_thenTheConnectionShouldBePersisted() = runTest {
+    fun givenAConnectionRequestIgnore_WhenApiUpdateFailedWithFederatedFailedDomains_thenTheConnectionShouldBeUpdated() = runTest {
         // given
         val userId = NetworkUserId("user_id", "domain_id")
         val (arrangement, connectionRepository) = Arrangement().arrange()
@@ -376,6 +399,32 @@ class ConnectionRepositoryTest {
         }.wasInvoked(exactly = once)
     }
 
+    @Test
+    fun givenAConnectionRequestIgnore_WhenApiUpdateFailedWithFederatedFailedDomains_thenTheConnectionShouldBePersisted() = runTest {
+        // given
+        val userId = NetworkUserId("user_id", "domain_id")
+        val (arrangement, connectionRepository) = Arrangement().arrange()
+        arrangement
+            .withErrorUpdatingConnectionStatusResponse(
+                userId,
+                KaliumException.FederationUnreachableException(FederationUnreachableResponse())
+            )
+            .withConnectionEntityByUser()
+            .withSuccessfulFetchSelfUserConnectionsResponse(arrangement.stubUserProfileDTO)
+
+        // when
+        val result = connectionRepository.ignoreConnectionRequest(UserId(userId.value, userId.domain))
+        result.shouldSucceed { arrangement.stubConnectionOne }
+
+        // then
+        coVerify {
+            arrangement.connectionDAO.insertConnection(arrangement.stubConnectionEntity.copy(
+                lastUpdateDate = any(),
+                status = ConnectionEntity.State.IGNORED
+            ))
+        }.wasInvoked(exactly = once)
+    }
+
     @Test
     fun givenAConnectionRequestIgnore_WhenApiUpdateFailedWithNonFederatedFailedDomains_thenTheConnectionNotShouldBePersisted() =
         runTest {
@@ -392,8 +441,10 @@ class ConnectionRepositoryTest {
 
             // then
             coVerify {
-                arrangement.connectionApi.updateConnection(userId, ConnectionStateDTO.IGNORED)
-            }.wasInvoked(exactly = once)
+                arrangement.connectionDAO.insertConnection(arrangement.stubConnectionEntity.copy(
+                    status = ConnectionEntity.State.IGNORED
+                ))
+            }.wasInvoked(exactly = 0)
         }
 
     private class Arrangement :
@@ -622,6 +673,12 @@ class ConnectionRepositoryTest {
             }.returns(connection)
         }
 
+        suspend fun withGetConnectionByUser(): Arrangement = apply {
+            coEvery {
+                connectionDAO.getConnectionByUser(any())
+            }.returns(connectionEntity)
+        }
+
         fun arrange() = this to connectionRepository
     }
 }