From f3f69f5bb122265773aa34bf39fe9b29398df4f7 Mon Sep 17 00:00:00 2001 From: Joao Victor Sena Date: Tue, 2 Sep 2025 07:37:51 -0300 Subject: [PATCH 01/10] chore: rename method --- app/src/main/java/to/bitkit/repositories/ActivityRepo.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt b/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt index cedb68f2b..78d6cf753 100644 --- a/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt +++ b/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt @@ -64,7 +64,7 @@ class ActivityRepo @Inject constructor( return@withContext Result.failure(e) } updateActivitiesMetadata() - syncTagsMetaData() + syncTagsMetadata() boostPendingActivities() updateInProgressTransfers() isSyncingLdkNodePayments.value = false @@ -322,7 +322,7 @@ class ActivityRepo @Inject constructor( } } - private suspend fun syncTagsMetaData( + private suspend fun syncTagsMetadata( ) = withContext(context = bgDispatcher) { runCatching { if (db.tagMetadataDao().getAll().isEmpty()) return@withContext From 8b580a87527bee737bf20e5239cc9040143202f5 Mon Sep 17 00:00:00 2001 From: Joao Victor Sena Date: Tue, 2 Sep 2025 07:40:04 -0300 Subject: [PATCH 02/10] chore: implement require method --- app/src/main/java/to/bitkit/repositories/ActivityRepo.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt b/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt index 78d6cf753..273c33ccd 100644 --- a/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt +++ b/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt @@ -579,7 +579,7 @@ class ActivityRepo @Inject constructor( ): Result = withContext(bgDispatcher) { return@withContext runCatching { - if (tags.isEmpty()) throw InvalidParameterException("tags must not be empty") + require(tags.isNotEmpty()) val entity = TagMetadataEntity( id = id, From c31345e9fa3eae7193a51086378879bd8e881f7c Mon Sep 17 00:00:00 2001 From: Joao Victor Sena Date: Tue, 2 Sep 2025 07:47:56 -0300 Subject: [PATCH 03/10] refactor: parallelize tag syncing --- .../to/bitkit/repositories/ActivityRepo.kt | 120 ++++++++++-------- 1 file changed, 65 insertions(+), 55 deletions(-) diff --git a/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt b/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt index 273c33ccd..8d771de00 100644 --- a/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt +++ b/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt @@ -7,6 +7,8 @@ import com.synonym.bitkitcore.PaymentType import com.synonym.bitkitcore.SortDirection import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.TimeoutCancellationException +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map @@ -26,7 +28,6 @@ import to.bitkit.ext.rawId import to.bitkit.services.CoreService import to.bitkit.utils.AddressChecker import to.bitkit.utils.Logger -import java.security.InvalidParameterException import javax.inject.Inject import javax.inject.Singleton @@ -322,76 +323,85 @@ class ActivityRepo @Inject constructor( } } - private suspend fun syncTagsMetadata( - ) = withContext(context = bgDispatcher) { + private suspend fun syncTagsMetadata() = withContext(context = bgDispatcher) { runCatching { if (db.tagMetadataDao().getAll().isEmpty()) return@withContext val lastActivities = getActivities(limit = 10u).getOrNull() ?: return@withContext - Logger.debug("syncTagsMetaData called") - lastActivities.forEach { activity -> - when (activity) { - is Activity.Lightning -> { - val paymentHash = activity.rawId() - db.tagMetadataDao().searchByPaymentHash(paymentHash = paymentHash)?.let { tagMetadata -> - Logger.debug("Tags metadata found! $tagMetadata", context = TAG) - addTagsToTransaction( - paymentHashOrTxId = paymentHash, - type = ActivityFilter.LIGHTNING, - txType = if (tagMetadata.isReceive) PaymentType.RECEIVED else PaymentType.SENT, - tags = tagMetadata.tags - ).onSuccess { - Logger.debug("Tags synced with success!", context = TAG) - db.tagMetadataDao().deleteByPaymentHash(paymentHash = paymentHash) + Logger.debug("syncTagsMetadata called") + + lastActivities.map { activity -> + async { + when (activity) { + is Activity.Lightning -> { + val paymentHash = activity.rawId() + db.tagMetadataDao().searchByPaymentHash(paymentHash = paymentHash)?.let { tagMetadata -> + Logger.debug("Tags metadata found! $tagMetadata", context = TAG) + addTagsToTransaction( + paymentHashOrTxId = paymentHash, + type = ActivityFilter.LIGHTNING, + txType = if (tagMetadata.isReceive) PaymentType.RECEIVED else PaymentType.SENT, + tags = tagMetadata.tags + ).onSuccess { + Logger.debug("Tags synced with success!", context = TAG) + db.tagMetadataDao().deleteByPaymentHash(paymentHash = paymentHash) + } } } - } - is Onchain -> { - when (activity.v1.txType) { - PaymentType.RECEIVED -> { - // TODO Temporary solution while whe ldk-node doesn't return the address directly - Logger.debug("Fetching data for txId: ${activity.v1.txId}", context = TAG) - runCatching { addressChecker.getTransaction(activity.v1.txId) }.onSuccess { txDetails -> - Logger.debug("Tx detail fetched with success: $txDetails", context = TAG) - txDetails.vout.forEach { vOut -> - vOut.scriptpubkey_address?.let { - Logger.debug("Extracted address: $it", context = TAG) - db.tagMetadataDao().searchByAddress(it) - }?.let { tagMetadata -> - Logger.debug("Tags metadata found! $tagMetadata", context = TAG) - addTagsToTransaction( - paymentHashOrTxId = txDetails.txid, - type = ActivityFilter.ONCHAIN, - txType = PaymentType.RECEIVED, - tags = tagMetadata.tags - ).onSuccess { - Logger.debug("Tags synced with success! $tagMetadata", context = TAG) - db.tagMetadataDao().deleteByTxId(activity.v1.txId) + is Onchain -> { + when (activity.v1.txType) { + PaymentType.RECEIVED -> { + // TODO Temporary solution while whe ldk-node doesn't return the address directly + Logger.debug("Fetching data for txId: ${activity.v1.txId}", context = TAG) + runCatching { + addressChecker.getTransaction(activity.v1.txId) + }.onSuccess { txDetails -> + Logger.debug("Tx detail fetched with success: $txDetails", context = TAG) + txDetails.vout.map { vOut -> + async { + vOut.scriptpubkey_address?.let { + Logger.debug("Extracted address: $it", context = TAG) + db.tagMetadataDao().searchByAddress(it) + }?.let { tagMetadata -> + Logger.debug("Tags metadata found! $tagMetadata", context = TAG) + addTagsToTransaction( + paymentHashOrTxId = txDetails.txid, + type = ActivityFilter.ONCHAIN, + txType = PaymentType.RECEIVED, + tags = tagMetadata.tags + ).onSuccess { + Logger.debug( + "Tags synced with success! $tagMetadata", + context = TAG + ) + db.tagMetadataDao().deleteByTxId(activity.v1.txId) + } + } } - } + }.awaitAll() + }.onFailure { + Logger.warn("Failed getting transaction detail", context = TAG) } - }.onFailure { - Logger.warn("Failed getting transaction detail", context = TAG) } - } - PaymentType.SENT -> { - db.tagMetadataDao().searchByTxId(activity.v1.txId)?.let { tagMetadata -> - addTagsToTransaction( - paymentHashOrTxId = activity.v1.txId, - type = ActivityFilter.ONCHAIN, - txType = PaymentType.SENT, - tags = tagMetadata.tags - ).onSuccess { - Logger.debug("Tags synced with success! $tagMetadata", context = TAG) - db.tagMetadataDao().deleteByTxId(activity.v1.txId) + PaymentType.SENT -> { + db.tagMetadataDao().searchByTxId(activity.v1.txId)?.let { tagMetadata -> + addTagsToTransaction( + paymentHashOrTxId = activity.v1.txId, + type = ActivityFilter.ONCHAIN, + txType = PaymentType.SENT, + tags = tagMetadata.tags + ).onSuccess { + Logger.debug("Tags synced with success! $tagMetadata", context = TAG) + db.tagMetadataDao().deleteByTxId(activity.v1.txId) + } } } } } } } - } + }.awaitAll() } } From 48407d0e5155da1f62ade179e802e9d8e4d0c626 Mon Sep 17 00:00:00 2001 From: Joao Victor Sena Date: Tue, 2 Sep 2025 08:00:59 -0300 Subject: [PATCH 04/10] refactor: parallelize updateActivitiesMetadata --- .../to/bitkit/repositories/ActivityRepo.kt | 83 ++++++++++--------- 1 file changed, 44 insertions(+), 39 deletions(-) diff --git a/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt b/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt index 8d771de00..637754b45 100644 --- a/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt +++ b/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt @@ -276,51 +276,56 @@ class ActivityRepo @Inject constructor( } private suspend fun updateActivitiesMetadata() = withContext(bgDispatcher) { - cacheStore.data.first().transactionsMetadata.forEach { activityMetaData -> - findActivityByPaymentId( - paymentHashOrTxId = activityMetaData.txId, - type = ActivityFilter.ALL, - txType = PaymentType.SENT - ).onSuccess { activityToUpdate -> - Logger.debug("updateActivitiesMetaData = Activity found: ${activityToUpdate.rawId()}", context = TAG) - - when (activityToUpdate) { - is Activity.Onchain -> { - val onChainActivity = activityToUpdate.v1.copy( - feeRate = activityMetaData.feeRate.toULong(), - address = activityMetaData.address, - isTransfer = activityMetaData.isTransfer, - channelId = activityMetaData.channelId, - transferTxId = activityMetaData.transferTxId - ) - val updatedActivity = Onchain( - v1 = onChainActivity - ) - - updateActivity( - id = updatedActivity.v1.id, - activity = updatedActivity - ).onSuccess { - if (onChainActivity.isTransfer && onChainActivity.doesExist) { - cacheStore.addInProgressTransfer( - InProgressTransfer( - activityId = updatedActivity.v1.id, - type = if (onChainActivity.txType == PaymentType.SENT) { - TransferType.TO_SPENDING - } else { - TransferType.TO_SAVINGS - } + cacheStore.data.first().transactionsMetadata.map { activityMetaData -> + async { + findActivityByPaymentId( + paymentHashOrTxId = activityMetaData.txId, + type = ActivityFilter.ALL, + txType = PaymentType.SENT + ).onSuccess { activityToUpdate -> + Logger.debug( + "updateActivitiesMetaData - Activity found: ${activityToUpdate.rawId()}", + context = TAG + ) + + when (activityToUpdate) { + is Activity.Onchain -> { + val onChainActivity = activityToUpdate.v1.copy( + feeRate = activityMetaData.feeRate.toULong(), + address = activityMetaData.address, + isTransfer = activityMetaData.isTransfer, + channelId = activityMetaData.channelId, + transferTxId = activityMetaData.transferTxId + ) + val updatedActivity = Onchain( + v1 = onChainActivity + ) + + updateActivity( + id = updatedActivity.v1.id, + activity = updatedActivity + ).onSuccess { + if (onChainActivity.isTransfer && onChainActivity.doesExist) { + cacheStore.addInProgressTransfer( + InProgressTransfer( + activityId = updatedActivity.v1.id, + type = if (onChainActivity.txType == PaymentType.SENT) { + TransferType.TO_SPENDING + } else { + TransferType.TO_SAVINGS + } + ) ) - ) + } + cacheStore.removeTransactionMetadata(activityMetaData) } - cacheStore.removeTransactionMetadata(activityMetaData) } - } - is Activity.Lightning -> Unit + is Activity.Lightning -> Unit + } } } - } + }.awaitAll() } private suspend fun syncTagsMetadata() = withContext(context = bgDispatcher) { From c2d6dd8d7f09d93bb5a120304ddd28ecf84d5604 Mon Sep 17 00:00:00 2001 From: Joao Victor Sena Date: Tue, 2 Sep 2025 08:02:10 -0300 Subject: [PATCH 05/10] refactor: parallelize deletePendingActivities --- .../main/java/to/bitkit/repositories/ActivityRepo.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt b/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt index 637754b45..e2ac066dd 100644 --- a/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt +++ b/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt @@ -268,11 +268,13 @@ class ActivityRepo @Inject constructor( } private suspend fun deletePendingActivities() = withContext(bgDispatcher) { - cacheStore.data.first().activitiesPendingDelete.forEach { activityId -> - deleteActivity(id = activityId).onSuccess { - cacheStore.removeActivityFromPendingDelete(activityId) + cacheStore.data.first().activitiesPendingDelete.map { activityId -> + async { + deleteActivity(id = activityId).onSuccess { + cacheStore.removeActivityFromPendingDelete(activityId) + } } - } + }.awaitAll() } private suspend fun updateActivitiesMetadata() = withContext(bgDispatcher) { From 0f8bb52857e63b639209d48b89e8fac6f1e4dff6 Mon Sep 17 00:00:00 2001 From: Joao Victor Sena Date: Tue, 2 Sep 2025 08:03:07 -0300 Subject: [PATCH 06/10] refactor: parallelize boostPendingActivities --- .../to/bitkit/repositories/ActivityRepo.kt | 68 ++++++++++--------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt b/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt index e2ac066dd..34d541f84 100644 --- a/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt +++ b/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt @@ -425,46 +425,48 @@ class ActivityRepo @Inject constructor( } private suspend fun boostPendingActivities() = withContext(bgDispatcher) { - cacheStore.data.first().pendingBoostActivities.forEach { pendingBoostActivity -> - findActivityByPaymentId( - paymentHashOrTxId = pendingBoostActivity.txId, - type = ActivityFilter.ONCHAIN, - txType = PaymentType.SENT - ).onSuccess { activityToUpdate -> - Logger.debug("boostPendingActivities = Activity found: ${activityToUpdate.rawId()}", context = TAG) - - val newOnChainActivity = activityToUpdate as? Activity.Onchain ?: return@onSuccess - - if ((newOnChainActivity.v1.updatedAt ?: 0u) > pendingBoostActivity.updatedAt) { - cacheStore.removeActivityFromPendingBoost(pendingBoostActivity) - return@onSuccess - } + cacheStore.data.first().pendingBoostActivities.map { pendingBoostActivity -> + async { + findActivityByPaymentId( + paymentHashOrTxId = pendingBoostActivity.txId, + type = ActivityFilter.ONCHAIN, + txType = PaymentType.SENT + ).onSuccess { activityToUpdate -> + Logger.debug("boostPendingActivities = Activity found: ${activityToUpdate.rawId()}", context = TAG) - val updatedActivity = Activity.Onchain( - v1 = newOnChainActivity.v1.copy( - isBoosted = true, - updatedAt = pendingBoostActivity.updatedAt - ) - ) + val newOnChainActivity = activityToUpdate as? Activity.Onchain ?: return@onSuccess - if (pendingBoostActivity.activityToDelete != null) { - replaceActivity( - id = updatedActivity.v1.id, - activity = updatedActivity, - activityIdToDelete = pendingBoostActivity.activityToDelete - ).onSuccess { + if ((newOnChainActivity.v1.updatedAt ?: 0u) > pendingBoostActivity.updatedAt) { cacheStore.removeActivityFromPendingBoost(pendingBoostActivity) + return@onSuccess } - } else { - updateActivity( - id = updatedActivity.v1.id, - activity = updatedActivity - ).onSuccess { - cacheStore.removeActivityFromPendingBoost(pendingBoostActivity) + + val updatedActivity = Activity.Onchain( + v1 = newOnChainActivity.v1.copy( + isBoosted = true, + updatedAt = pendingBoostActivity.updatedAt + ) + ) + + if (pendingBoostActivity.activityToDelete != null) { + replaceActivity( + id = updatedActivity.v1.id, + activity = updatedActivity, + activityIdToDelete = pendingBoostActivity.activityToDelete + ).onSuccess { + cacheStore.removeActivityFromPendingBoost(pendingBoostActivity) + } + } else { + updateActivity( + id = updatedActivity.v1.id, + activity = updatedActivity + ).onSuccess { + cacheStore.removeActivityFromPendingBoost(pendingBoostActivity) + } } } } - } + }.awaitAll() } /** From 81fe3547a73a73664d2eb41b0fa410f9a7e31281 Mon Sep 17 00:00:00 2001 From: Joao Victor Sena Date: Tue, 2 Sep 2025 09:00:26 -0300 Subject: [PATCH 07/10] fix: add tags to RBF --- app/src/main/java/to/bitkit/repositories/ActivityRepo.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt b/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt index 34d541f84..a5acf5fc2 100644 --- a/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt +++ b/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt @@ -5,6 +5,7 @@ import com.synonym.bitkitcore.Activity.Onchain import com.synonym.bitkitcore.ActivityFilter import com.synonym.bitkitcore.PaymentType import com.synonym.bitkitcore.SortDirection +import com.synonym.bitkitcore.getTags import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.TimeoutCancellationException import kotlinx.coroutines.async @@ -246,6 +247,10 @@ class ActivityRepo @Inject constructor( "Activity $id updated with success. new data: $activity. Deleting activity $activityIdToDelete", context = TAG ) + + val tags = getTags(activityIdToDelete) + addTagsToActivity(activityId = id, tags = tags) + deleteActivity(activityIdToDelete).onFailure { e -> Logger.warn( "Failed to delete $activityIdToDelete caching to retry on next sync", From c1b357e3810a209e7ae4033825638a58ac17d536 Mon Sep 17 00:00:00 2001 From: Joao Victor Sena Date: Tue, 2 Sep 2025 09:32:10 -0300 Subject: [PATCH 08/10] test: remove test because mockito doesn't support top-level function mock --- .../bitkit/repositories/ActivityRepoTest.kt | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/app/src/test/java/to/bitkit/repositories/ActivityRepoTest.kt b/app/src/test/java/to/bitkit/repositories/ActivityRepoTest.kt index fe7d206cf..19b999260 100644 --- a/app/src/test/java/to/bitkit/repositories/ActivityRepoTest.kt +++ b/app/src/test/java/to/bitkit/repositories/ActivityRepoTest.kt @@ -6,6 +6,7 @@ import com.synonym.bitkitcore.LightningActivity import com.synonym.bitkitcore.OnchainActivity import com.synonym.bitkitcore.PaymentType import com.synonym.bitkitcore.SortDirection +import com.synonym.bitkitcore.getTags import kotlinx.coroutines.flow.flowOf import org.junit.Before import org.junit.Test @@ -228,24 +229,6 @@ class ActivityRepoTest : BaseUnitTest() { verify(coreService.activity).update(activityId, testActivity) } - @Test - fun `replaceActivity updates and deletes successfully`() = test { - val activityId = "activity123" - val activityToDeleteId = "activity456" - val cacheData = AppCacheData(deletedActivities = emptyList()) - whenever(cacheStore.data).thenReturn(flowOf(cacheData)) - - wheneverBlocking { coreService.activity.update(activityId, testActivity) }.thenReturn(Unit) - wheneverBlocking { coreService.activity.delete(activityToDeleteId) }.thenReturn(true) - wheneverBlocking { cacheStore.addActivityToDeletedList(activityToDeleteId) }.thenReturn(Unit) - - val result = sut.replaceActivity(activityId, activityToDeleteId, testActivity) - - assertTrue(result.isSuccess) - verify(coreService.activity).update(activityId, testActivity) - verify(coreService.activity).delete(activityToDeleteId) - } - @Test fun `deleteActivity deletes successfully`() = test { val activityId = "activity123" From 57d530c1f7dd2747ca5648182465bc90a3cb325a Mon Sep 17 00:00:00 2001 From: Joao Victor Sena Date: Tue, 2 Sep 2025 09:35:22 -0300 Subject: [PATCH 09/10] chore: lint --- app/src/test/java/to/bitkit/repositories/ActivityRepoTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/test/java/to/bitkit/repositories/ActivityRepoTest.kt b/app/src/test/java/to/bitkit/repositories/ActivityRepoTest.kt index 19b999260..7f67b6e4f 100644 --- a/app/src/test/java/to/bitkit/repositories/ActivityRepoTest.kt +++ b/app/src/test/java/to/bitkit/repositories/ActivityRepoTest.kt @@ -6,7 +6,6 @@ import com.synonym.bitkitcore.LightningActivity import com.synonym.bitkitcore.OnchainActivity import com.synonym.bitkitcore.PaymentType import com.synonym.bitkitcore.SortDirection -import com.synonym.bitkitcore.getTags import kotlinx.coroutines.flow.flowOf import org.junit.Before import org.junit.Test From 563ec0768da821dc8c9e6aec6f42f6194e058583 Mon Sep 17 00:00:00 2001 From: Joao Victor Sena Date: Thu, 4 Sep 2025 07:16:21 -0300 Subject: [PATCH 10/10] fix: use core service instance instead of calling high-level function --- .../to/bitkit/repositories/ActivityRepo.kt | 3 +-- .../bitkit/repositories/ActivityRepoTest.kt | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt b/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt index a5acf5fc2..05b743878 100644 --- a/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt +++ b/app/src/main/java/to/bitkit/repositories/ActivityRepo.kt @@ -5,7 +5,6 @@ import com.synonym.bitkitcore.Activity.Onchain import com.synonym.bitkitcore.ActivityFilter import com.synonym.bitkitcore.PaymentType import com.synonym.bitkitcore.SortDirection -import com.synonym.bitkitcore.getTags import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.TimeoutCancellationException import kotlinx.coroutines.async @@ -248,7 +247,7 @@ class ActivityRepo @Inject constructor( context = TAG ) - val tags = getTags(activityIdToDelete) + val tags = coreService.activity.tags(activityIdToDelete) addTagsToActivity(activityId = id, tags = tags) deleteActivity(activityIdToDelete).onFailure { e -> diff --git a/app/src/test/java/to/bitkit/repositories/ActivityRepoTest.kt b/app/src/test/java/to/bitkit/repositories/ActivityRepoTest.kt index 7f67b6e4f..4421aadb5 100644 --- a/app/src/test/java/to/bitkit/repositories/ActivityRepoTest.kt +++ b/app/src/test/java/to/bitkit/repositories/ActivityRepoTest.kt @@ -228,6 +228,27 @@ class ActivityRepoTest : BaseUnitTest() { verify(coreService.activity).update(activityId, testActivity) } + @Test + fun `replaceActivity updates and deletes successfully`() = test { + val activityId = "activity123" + val activityToDeleteId = "activity456" + val tagsMock = listOf("tag1", "tag2") + val cacheData = AppCacheData(deletedActivities = emptyList()) + whenever(cacheStore.data).thenReturn(flowOf(cacheData)) + + wheneverBlocking { coreService.activity.update(activityId, testActivity) }.thenReturn(Unit) + wheneverBlocking { coreService.activity.delete(activityToDeleteId) }.thenReturn(true) + wheneverBlocking { cacheStore.addActivityToDeletedList(activityToDeleteId) }.thenReturn(Unit) + + whenever(coreService.activity.tags(activityId)).thenAnswer { tagsMock } + + val result = sut.replaceActivity(activityId, activityToDeleteId, testActivity) + + assertTrue(result.isSuccess) + verify(coreService.activity).update(activityId, testActivity) + verify(coreService.activity).delete(activityToDeleteId) + } + @Test fun `deleteActivity deletes successfully`() = test { val activityId = "activity123"