From 7132123ccf1382f265c78aea0e1ec4777391ac2f Mon Sep 17 00:00:00 2001 From: Wally Hackenslacker Date: Mon, 16 Mar 2026 20:43:44 -0400 Subject: [PATCH] fix: preserve activity snapshot when comment refresh fails --- .../app/carddetail/CardDetailRepository.kt | 8 ++++- .../carddetail/CardDetailRepositoryTest.kt | 30 ++++++++++++++----- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/space/hackenslacker/kanbn4droid/app/carddetail/CardDetailRepository.kt b/app/src/main/java/space/hackenslacker/kanbn4droid/app/carddetail/CardDetailRepository.kt index cf427d4..0961b64 100644 --- a/app/src/main/java/space/hackenslacker/kanbn4droid/app/carddetail/CardDetailRepository.kt +++ b/app/src/main/java/space/hackenslacker/kanbn4droid/app/carddetail/CardDetailRepository.kt @@ -190,6 +190,12 @@ class CardDetailRepository( return Result.Failure.Generic("Comment is required") } + val preAddSnapshot = when (val preAddActivitiesResult = listActivities(normalizedCardId)) { + is Result.Success -> preAddActivitiesResult.value + is Result.Failure.SessionExpired -> return preAddActivitiesResult + is Result.Failure.Generic -> emptyList() + } + val session = when (val sessionResult = session()) { is Result.Success -> sessionResult.value is Result.Failure -> return sessionResult @@ -210,7 +216,7 @@ class CardDetailRepository( return when (val refreshResult = listActivities(normalizedCardId)) { is Result.Success -> refreshResult is Result.Failure.SessionExpired -> refreshResult - is Result.Failure.Generic -> Result.Success(emptyList()) + is Result.Failure.Generic -> Result.Success(preAddSnapshot) } } diff --git a/app/src/test/java/space/hackenslacker/kanbn4droid/app/carddetail/CardDetailRepositoryTest.kt b/app/src/test/java/space/hackenslacker/kanbn4droid/app/carddetail/CardDetailRepositoryTest.kt index ccd8637..b9616c4 100644 --- a/app/src/test/java/space/hackenslacker/kanbn4droid/app/carddetail/CardDetailRepositoryTest.kt +++ b/app/src/test/java/space/hackenslacker/kanbn4droid/app/carddetail/CardDetailRepositoryTest.kt @@ -99,7 +99,8 @@ class CardDetailRepositoryTest { fun addComment_success_refreshesActivities() = runTest { val apiClient = FakeCardDetailApiClient().apply { addCommentResult = BoardsApiResult.Success(Unit) - listActivitiesResult = BoardsApiResult.Success( + listActivitiesResults += BoardsApiResult.Success(emptyList()) + listActivitiesResults += BoardsApiResult.Success( listOf( CardActivity( id = "a-1", @@ -116,15 +117,24 @@ class CardDetailRepositoryTest { assertTrue(result is CardDetailRepository.Result.Success) assertEquals(1, apiClient.addCommentCalls) - assertEquals(1, apiClient.listActivitiesCalls) + assertEquals(2, apiClient.listActivitiesCalls) assertEquals("hello", apiClient.lastComment) } @Test - fun addComment_refreshGenericFailure_returnsSuccessWithEmptyActivities() = runTest { + fun addComment_refreshGenericFailure_returnsSuccessWithPreAddSnapshot() = runTest { + val preAddSnapshot = listOf( + CardActivity( + id = "a-existing", + type = "comment", + text = "existing", + createdAtEpochMillis = 10L, + ), + ) val apiClient = FakeCardDetailApiClient().apply { addCommentResult = BoardsApiResult.Success(Unit) - listActivitiesResult = BoardsApiResult.Failure("Server temporarily unavailable") + listActivitiesResults += BoardsApiResult.Success(preAddSnapshot) + listActivitiesResults += BoardsApiResult.Failure("Server temporarily unavailable") } val repository = createRepository(apiClient = apiClient) @@ -132,22 +142,24 @@ class CardDetailRepositoryTest { assertTrue(result is CardDetailRepository.Result.Success) val activities = (result as CardDetailRepository.Result.Success>).value - assertTrue(activities.isEmpty()) + assertEquals(preAddSnapshot, activities) assertEquals(1, apiClient.addCommentCalls) - assertEquals(1, apiClient.listActivitiesCalls) + assertEquals(2, apiClient.listActivitiesCalls) } @Test fun addComment_refreshAuthFailure_mapsToSessionExpired() = runTest { val apiClient = FakeCardDetailApiClient().apply { addCommentResult = BoardsApiResult.Success(Unit) - listActivitiesResult = BoardsApiResult.Failure("Server error: 403") + listActivitiesResults += BoardsApiResult.Success(emptyList()) + listActivitiesResults += BoardsApiResult.Failure("Server error: 403") } val repository = createRepository(apiClient = apiClient) val result = repository.addComment(cardId = "card-1", comment = "hello") assertTrue(result is CardDetailRepository.Result.Failure.SessionExpired) + assertEquals(2, apiClient.listActivitiesCalls) } @Test @@ -263,6 +275,7 @@ class CardDetailRepositoryTest { ) var updateCardResult: BoardsApiResult = BoardsApiResult.Success(Unit) var listActivitiesResult: BoardsApiResult> = BoardsApiResult.Success(emptyList()) + val listActivitiesResults: MutableList>> = mutableListOf() var addCommentResult: BoardsApiResult = BoardsApiResult.Success(Unit) var lastUpdatedTitle: String? = null @@ -300,6 +313,9 @@ class CardDetailRepositoryTest { cardId: String, ): BoardsApiResult> { listActivitiesCalls += 1 + if (listActivitiesResults.isNotEmpty()) { + return listActivitiesResults.removeAt(0) + } return listActivitiesResult }