diff --git a/data/account/src/main/kotlin/com/tangem/data/account/fetcher/DefaultWalletAccountsFetcher.kt b/data/account/src/main/kotlin/com/tangem/data/account/fetcher/DefaultWalletAccountsFetcher.kt index bd25eb1add..12c40f608d 100644 --- a/data/account/src/main/kotlin/com/tangem/data/account/fetcher/DefaultWalletAccountsFetcher.kt +++ b/data/account/src/main/kotlin/com/tangem/data/account/fetcher/DefaultWalletAccountsFetcher.kt @@ -206,7 +206,12 @@ internal class DefaultWalletAccountsFetcher @Inject constructor( store(userWalletId = userWalletId, response = response) - push(userWalletId = userWalletId, accounts = response.accounts) + val isFailed = push(userWalletId = userWalletId, accounts = response.accounts) == null + if (isFailed) { + // Clear ETags if push failed to avoid different state in the cache and API + eTagsStore.clear(userWalletId, ETagsStore.Key.WalletAccounts) + } + userTokensSaver.push(userWalletId = userWalletId, response = response.toUserTokensResponse()) return response diff --git a/data/account/src/test/java/com/tangem/data/account/fetcher/DefaultWalletAccountsFetcherTest.kt b/data/account/src/test/java/com/tangem/data/account/fetcher/DefaultWalletAccountsFetcherTest.kt index 4f358b2d09..49586e40b0 100644 --- a/data/account/src/test/java/com/tangem/data/account/fetcher/DefaultWalletAccountsFetcherTest.kt +++ b/data/account/src/test/java/com/tangem/data/account/fetcher/DefaultWalletAccountsFetcherTest.kt @@ -18,6 +18,7 @@ import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.datasource.api.tangemTech.models.UserTokensResponse import com.tangem.datasource.api.tangemTech.models.account.GetWalletAccountsResponse import com.tangem.datasource.api.tangemTech.models.account.SaveWalletAccountsResponse +import com.tangem.datasource.api.tangemTech.models.account.toUserTokensResponse import com.tangem.domain.models.wallet.UserWalletId import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import io.mockk.* @@ -37,10 +38,10 @@ class DefaultWalletAccountsFetcherTest { private val accountsResponseStoreFactory: AccountsResponseStoreFactory = mockk() private val accountsResponseStore: AccountsResponseStore = mockk() private val accountsResponseStoreFlow = MutableStateFlow(value = null) - private val tokensMigration: DefaultMainAccountTokensMigration = mockk(relaxed = true) + private val tokensMigration: DefaultMainAccountTokensMigration = mockk() private val userTokensSaver: UserTokensSaver = mockk(relaxUnitFun = true) - private val fetchWalletAccountsErrorHandler: FetchWalletAccountsErrorHandler = mockk(relaxUnitFun = true) + private val fetchWalletAccountsErrorHandler: FetchWalletAccountsErrorHandler = mockk() private val defaultWalletAccountsResponseFactory: DefaultWalletAccountsResponseFactory = mockk() private val eTagsStore: ETagsStore = mockk(relaxUnitFun = true) @@ -253,6 +254,90 @@ class DefaultWalletAccountsFetcherTest { userTokensSaver.push(userWalletId = any(), response = any()) } } + + @Test + fun `GIVEN response with empty accounts and push request is failed THEN eTag will be cleared`() = runTest { + // Arrange + val savedAccountsResponse = GetWalletAccountsResponse( + wallet = GetWalletAccountsResponse.Wallet( + group = null, + sort = null, + totalAccounts = 0, + totalArchivedAccounts = 0, + ), + accounts = emptyList(), + unassignedTokens = emptyList(), + ) + val getResponse = ApiResponse.Error( + cause = ApiResponseError.HttpException( + code = ApiResponseError.HttpException.Code.NOT_MODIFIED, + message = null, + errorBody = null, + ), + headers = mapOf(ETAG_HEADER to listOf(eTag)), + ) + + accountsResponseStoreFlow.value = savedAccountsResponse + + coEvery { + tangemTechApi.getWalletAccounts(walletId = userWalletId.stringValue, eTag = eTag) + } returns getResponse as ApiResponse + + coEvery { + fetchWalletAccountsErrorHandler.handle( + error = getResponse.cause, + userWalletId = userWalletId, + savedAccountsResponse = savedAccountsResponse, + pushWalletAccounts = any(), + storeWalletAccounts = any(), + ) + } returns FetchResult(savedAccountsResponse) + + coEvery { + defaultWalletAccountsResponseFactory.create(userWalletId = userWalletId, userTokensResponse = null) + } returns savedAccountsResponse + + coEvery { accountsResponseStore.updateData(any()) } returns savedAccountsResponse + + val saveResponse = ApiResponse.Error(ApiResponseError.TimeoutException()) + coEvery { + tangemTechApi.saveWalletAccounts( + walletId = userWalletId.stringValue, + eTag = eTag, + body = SaveWalletAccountsResponse(savedAccountsResponse.accounts), + ) + } returns saveResponse as ApiResponse + + // Act + fetcher.fetch(userWalletId) + + // Assert + coVerify { + accountsResponseStoreFactory.create(userWalletId = userWalletId) + accountsResponseStore.data + eTagsStore.getSyncOrNull(userWalletId = userWalletId, key = ETagsStore.Key.WalletAccounts) + tangemTechApi.getWalletAccounts(walletId = userWalletId.stringValue, eTag = eTag) + eTagsStore.store(userWalletId = userWalletId, key = ETagsStore.Key.WalletAccounts, value = eTag) + accountsResponseStore.updateData(any()) + fetchWalletAccountsErrorHandler.handle( + error = getResponse.cause, + userWalletId = userWalletId, + savedAccountsResponse = savedAccountsResponse, + pushWalletAccounts = any(), + storeWalletAccounts = any(), + ) + defaultWalletAccountsResponseFactory.create(userWalletId = userWalletId, userTokensResponse = null) + eTagsStore.getSyncOrNull(userWalletId = userWalletId, key = ETagsStore.Key.WalletAccounts) + tangemTechApi.saveWalletAccounts( + walletId = userWalletId.stringValue, + eTag = eTag, + body = SaveWalletAccountsResponse(savedAccountsResponse.accounts), + ) + eTagsStore.clear(userWalletId, ETagsStore.Key.WalletAccounts) + userTokensSaver.push(userWalletId = userWalletId, response = savedAccountsResponse.toUserTokensResponse()) + tokensMigration.migrate(userWalletId) + } + } } @Nested