Updated on 2026-08-14

This commit is contained in:
Tangem 2026-01-22 14:33:20 +03:00
parent 45e78f3985
commit 4eb9f0e87c
2 changed files with 93 additions and 3 deletions

View file

@ -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

View file

@ -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<GetWalletAccountsResponse?>(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<GetWalletAccountsResponse>
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<GetWalletAccountsResponse>
// 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