Updated on 2026-08-14
This commit is contained in:
parent
b9bb9e1086
commit
058a6ab4d5
15 changed files with 969 additions and 256 deletions
|
|
@ -1,18 +1,18 @@
|
|||
package com.tangem.data.quotes.multi
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.data.common.api.safeApiCallWithTimeout
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.data.common.quote.QuotesFetcher
|
||||
import com.tangem.data.common.quote.QuotesFetcher.Field
|
||||
import com.tangem.data.quotes.store.QuotesStatusesStore
|
||||
import com.tangem.data.quotes.store.setSourceAsCache
|
||||
import com.tangem.data.quotes.store.setSourceAsOnlyCache
|
||||
import com.tangem.data.quotes.utils.QuotesUnsupportedCurrenciesIdAdapter
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.appcurrency.AppCurrencyResponseStore
|
||||
import com.tangem.domain.core.utils.catchOn
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
|
@ -20,16 +20,16 @@ import javax.inject.Singleton
|
|||
/**
|
||||
* Default implementation of [MultiQuoteStatusFetcher]
|
||||
*
|
||||
* @property tangemTechApi tangemTech api
|
||||
* @property quotesFetcher quotes fetcher
|
||||
* @property appCurrencyResponseStore app currency response store
|
||||
* @property quotesStatusesStore quotes store
|
||||
* @property quotesStatusesStore quotes statuses store
|
||||
* @property dispatchers dispatchers
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@Singleton
|
||||
internal class DefaultMultiQuoteStatusFetcher @Inject constructor(
|
||||
private val tangemTechApi: TangemTechApi,
|
||||
private val quotesFetcher: QuotesFetcher,
|
||||
private val appCurrencyResponseStore: AppCurrencyResponseStore,
|
||||
private val quotesStatusesStore: QuotesStatusesStore,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
|
|
@ -51,16 +51,13 @@ internal class DefaultMultiQuoteStatusFetcher @Inject constructor(
|
|||
)
|
||||
|
||||
val appCurrencyId = getAppCurrencyId(params = params)
|
||||
val coinIds = replacementIdsResult.idsForRequest.joinToString(separator = ",")
|
||||
|
||||
val response = safeApiCallWithTimeout(
|
||||
call = {
|
||||
withContext(dispatchers.io) {
|
||||
tangemTechApi.getQuotes(currencyId = appCurrencyId, coinIds = coinIds).bind()
|
||||
}
|
||||
},
|
||||
onError = { error -> throw error },
|
||||
val response = quotesFetcher.fetch(
|
||||
fiatCurrencyId = appCurrencyId,
|
||||
currenciesIds = replacementIdsResult.idsForRequest,
|
||||
fields = setOf(Field.PRICE, Field.PRICE_CHANGE_24H),
|
||||
)
|
||||
.getOrElse { error("Cause: $it") }
|
||||
|
||||
val updatedResponse = QuotesUnsupportedCurrenciesIdAdapter.getResponseWithUnsupportedCurrencies(
|
||||
response = response,
|
||||
|
|
|
|||
|
|
@ -1,107 +1,125 @@
|
|||
package com.tangem.data.quotes.multi
|
||||
|
||||
import arrow.core.left
|
||||
import arrow.core.right
|
||||
import com.google.common.truth.Truth
|
||||
import com.tangem.common.test.data.quote.MockQuoteResponseFactory
|
||||
import com.tangem.common.test.utils.assertEither
|
||||
import com.tangem.data.common.quote.QuotesFetcher
|
||||
import com.tangem.data.quotes.store.QuotesStatusesStore
|
||||
import com.tangem.data.quotes.store.setSourceAsCache
|
||||
import com.tangem.data.quotes.store.setSourceAsOnlyCache
|
||||
import com.tangem.datasource.api.common.response.ApiResponse
|
||||
import com.tangem.datasource.api.common.response.ApiResponseError
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.api.tangemTech.models.CurrenciesResponse
|
||||
import com.tangem.datasource.api.tangemTech.models.QuotesResponse
|
||||
import com.tangem.datasource.appcurrency.AppCurrencyResponseStore
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.coVerifyOrder
|
||||
import io.mockk.mockk
|
||||
import io.mockk.*
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
internal class DefaultMultiQuoteStatusFetcherTest {
|
||||
|
||||
private val tangemTechApi = mockk<TangemTechApi>(relaxed = true)
|
||||
private val appCurrencyResponseStore = mockk<AppCurrencyResponseStore>(relaxed = true)
|
||||
private val quotesFetcher = mockk<QuotesFetcher>()
|
||||
private val appCurrencyResponseStore = mockk<AppCurrencyResponseStore>()
|
||||
private val quotesStore = mockk<QuotesStatusesStore>(relaxed = true)
|
||||
|
||||
private val fetcher = DefaultMultiQuoteStatusFetcher(
|
||||
tangemTechApi = tangemTechApi,
|
||||
quotesFetcher = quotesFetcher,
|
||||
appCurrencyResponseStore = appCurrencyResponseStore,
|
||||
quotesStatusesStore = quotesStore,
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
)
|
||||
|
||||
@BeforeEach
|
||||
fun resetMocks() {
|
||||
clearMocks(quotesFetcher, appCurrencyResponseStore, quotesStore)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fetch quotes successfully`() = runTest {
|
||||
fun `fetch successfully`() = runTest {
|
||||
// Arrange
|
||||
val params = MultiQuoteStatusFetcher.Params(currenciesIds = currenciesIds, appCurrencyId = null)
|
||||
|
||||
coEvery { appCurrencyResponseStore.getSyncOrNull() } returns usdAppCurrency
|
||||
|
||||
val coinIds = "BTC,ETH"
|
||||
coEvery {
|
||||
tangemTechApi.getQuotes(currencyId = "usd", coinIds = coinIds)
|
||||
} returns ApiResponse.Success(successResponse)
|
||||
val currenciesIds = setOf("BTC", "ETH")
|
||||
|
||||
coEvery {
|
||||
quotesFetcher.fetch(fiatCurrencyId = "usd", currenciesIds = currenciesIds, fields = fields)
|
||||
} returns successResponse.right()
|
||||
|
||||
// Act
|
||||
val actual = fetcher(params)
|
||||
|
||||
// Assert
|
||||
val expected = Unit.right()
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder {
|
||||
quotesStore.setSourceAsCache(currenciesIds = params.currenciesIds)
|
||||
|
||||
appCurrencyResponseStore.getSyncOrNull()
|
||||
|
||||
tangemTechApi.getQuotes(currencyId = "usd", coinIds = coinIds)
|
||||
|
||||
quotesFetcher.fetch(fiatCurrencyId = "usd", currenciesIds = currenciesIds, fields = fields)
|
||||
quotesStore.store(values = successResponse.quotes)
|
||||
}
|
||||
|
||||
coVerify(inverse = true) {
|
||||
quotesStore.setSourceAsOnlyCache(currenciesIds = any())
|
||||
}
|
||||
|
||||
Truth.assertThat(actual.isRight()).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fetch quotes successfully if currenciesIds from params is empty`() = runTest {
|
||||
fun `fetch successfully if currenciesIds from params is empty`() = runTest {
|
||||
// Arrange
|
||||
val params = MultiQuoteStatusFetcher.Params(currenciesIds = emptySet(), appCurrencyId = null)
|
||||
|
||||
// Act
|
||||
val actual = fetcher(params)
|
||||
|
||||
// Assert
|
||||
val expected = Unit.right()
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerify(inverse = true) {
|
||||
quotesStore.setSourceAsCache(currenciesIds = any())
|
||||
appCurrencyResponseStore.getSyncOrNull()
|
||||
tangemTechApi.getQuotes(currencyId = any(), coinIds = any())
|
||||
quotesFetcher.fetch(fiatCurrencyId = any(), currenciesIds = any(), fields = any())
|
||||
quotesStore.store(values = any())
|
||||
quotesStore.setSourceAsOnlyCache(currenciesIds = any())
|
||||
}
|
||||
|
||||
Truth.assertThat(actual.isRight()).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fetch quotes successfully if appCurrencyId from params is not null`() = runTest {
|
||||
fun `fetch successfully if appCurrencyId from params is not null`() = runTest {
|
||||
// Arrange
|
||||
val appCurrencyId = "usd"
|
||||
val params = MultiQuoteStatusFetcher.Params(currenciesIds = currenciesIds, appCurrencyId = appCurrencyId)
|
||||
|
||||
val coinIds = "BTC,ETH"
|
||||
coEvery {
|
||||
tangemTechApi.getQuotes(currencyId = appCurrencyId, coinIds = coinIds)
|
||||
} returns ApiResponse.Success(successResponse)
|
||||
val currenciesIds = setOf("BTC", "ETH")
|
||||
|
||||
coEvery {
|
||||
quotesFetcher.fetch(fiatCurrencyId = appCurrencyId, currenciesIds = currenciesIds, fields = fields)
|
||||
} returns successResponse.right()
|
||||
|
||||
// Act
|
||||
val actual = fetcher(params)
|
||||
|
||||
// Assert
|
||||
val expected = Unit.right()
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder {
|
||||
quotesStore.setSourceAsCache(currenciesIds = params.currenciesIds)
|
||||
|
||||
tangemTechApi.getQuotes(currencyId = "usd", coinIds = coinIds)
|
||||
|
||||
quotesFetcher.fetch(fiatCurrencyId = appCurrencyId, currenciesIds = currenciesIds, fields = fields)
|
||||
quotesStore.store(values = successResponse.quotes)
|
||||
}
|
||||
|
||||
|
|
@ -109,17 +127,22 @@ internal class DefaultMultiQuoteStatusFetcherTest {
|
|||
appCurrencyResponseStore.getSyncOrNull()
|
||||
quotesStore.setSourceAsOnlyCache(currenciesIds = any())
|
||||
}
|
||||
|
||||
Truth.assertThat(actual.isRight()).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fetch quotes failure because appCurrencyId from params is blank`() = runTest {
|
||||
fun `fetch failure because appCurrencyId from params is blank`() = runTest {
|
||||
// Arrange
|
||||
val appCurrencyId = ""
|
||||
val params = MultiQuoteStatusFetcher.Params(currenciesIds = currenciesIds, appCurrencyId = appCurrencyId)
|
||||
|
||||
// Act
|
||||
val actual = fetcher(params)
|
||||
|
||||
// Assert
|
||||
val expected = IllegalStateException("Unable to get AppCurrency for updating quotes").left()
|
||||
|
||||
assertEither(actual, expected)
|
||||
|
||||
coVerifyOrder {
|
||||
quotesStore.setSourceAsCache(currenciesIds = params.currenciesIds)
|
||||
quotesStore.setSourceAsOnlyCache(currenciesIds = params.currenciesIds)
|
||||
|
|
@ -127,55 +150,59 @@ internal class DefaultMultiQuoteStatusFetcherTest {
|
|||
|
||||
coVerify(inverse = true) {
|
||||
appCurrencyResponseStore.getSyncOrNull()
|
||||
tangemTechApi.getQuotes(currencyId = any(), coinIds = any())
|
||||
quotesFetcher.fetch(fiatCurrencyId = any(), currenciesIds = any(), fields = any())
|
||||
quotesStore.store(values = any())
|
||||
}
|
||||
|
||||
Truth.assertThat(actual.isLeft()).isTrue()
|
||||
Truth.assertThat(actual.leftOrNull()).isInstanceOf(IllegalStateException::class.java)
|
||||
Truth.assertThat(actual.leftOrNull()).hasMessageThat()
|
||||
.isEqualTo("Unable to get AppCurrency for updating quotes")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fetch quotes failure because api request failed`() = runTest {
|
||||
fun `fetch failure because api request failed`() = runTest {
|
||||
// Arrange
|
||||
val params = MultiQuoteStatusFetcher.Params(currenciesIds = currenciesIds, appCurrencyId = null)
|
||||
|
||||
val currenciesIds = setOf("BTC", "ETH")
|
||||
val error = QuotesFetcher.Error.ApiOperationError(ApiResponseError.NetworkException)
|
||||
|
||||
coEvery { appCurrencyResponseStore.getSyncOrNull() } returns usdAppCurrency
|
||||
|
||||
val coinIds = "BTC,ETH"
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val errorResponse = ApiResponse.Error(ApiResponseError.NetworkException) as ApiResponse<QuotesResponse>
|
||||
coEvery { tangemTechApi.getQuotes(currencyId = "usd", coinIds = coinIds) } returns errorResponse
|
||||
coEvery {
|
||||
quotesFetcher.fetch(fiatCurrencyId = "usd", currenciesIds = currenciesIds, fields = fields)
|
||||
} returns error.left()
|
||||
|
||||
// Act
|
||||
val actual = fetcher(params)
|
||||
|
||||
// Assert
|
||||
val expected = IllegalStateException("Cause: ApiOperationError(apiError=NetworkException)").left()
|
||||
assertEither(actual, expected)
|
||||
|
||||
coVerifyOrder {
|
||||
quotesStore.setSourceAsCache(currenciesIds = params.currenciesIds)
|
||||
|
||||
appCurrencyResponseStore.getSyncOrNull()
|
||||
|
||||
tangemTechApi.getQuotes(currencyId = "usd", coinIds = coinIds)
|
||||
|
||||
quotesFetcher.fetch(fiatCurrencyId = "usd", currenciesIds = currenciesIds, fields = fields)
|
||||
quotesStore.setSourceAsOnlyCache(currenciesIds = params.currenciesIds)
|
||||
}
|
||||
|
||||
coVerify(inverse = true) {
|
||||
quotesStore.store(values = any())
|
||||
}
|
||||
|
||||
Truth.assertThat(actual.isLeft()).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fetch quotes failure because app currency not found`() = runTest {
|
||||
fun `fetch failure because app currency not found`() = runTest {
|
||||
// Arrange
|
||||
val params = MultiQuoteStatusFetcher.Params(currenciesIds = currenciesIds, appCurrencyId = null)
|
||||
|
||||
coEvery { appCurrencyResponseStore.getSyncOrNull() } returns null
|
||||
|
||||
// Act
|
||||
val actual = fetcher(params)
|
||||
|
||||
// Assert
|
||||
val expected = IllegalStateException("Unable to get AppCurrency for updating quotes").left()
|
||||
|
||||
assertEither(actual, expected)
|
||||
|
||||
coVerifyOrder {
|
||||
quotesStore.setSourceAsCache(currenciesIds = params.currenciesIds)
|
||||
appCurrencyResponseStore.getSyncOrNull()
|
||||
|
|
@ -183,11 +210,9 @@ internal class DefaultMultiQuoteStatusFetcherTest {
|
|||
}
|
||||
|
||||
coVerify(inverse = true) {
|
||||
tangemTechApi.getQuotes(currencyId = any(), coinIds = any())
|
||||
quotesFetcher.fetch(fiatCurrencyId = any(), currenciesIds = any(), fields = any())
|
||||
quotesStore.store(values = any())
|
||||
}
|
||||
|
||||
Truth.assertThat(actual.isLeft()).isTrue()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
|
@ -212,5 +237,7 @@ internal class DefaultMultiQuoteStatusFetcherTest {
|
|||
"ETH" to MockQuoteResponseFactory.createSinglePrice(value = BigDecimal.TEN),
|
||||
),
|
||||
)
|
||||
|
||||
val fields = setOf(QuotesFetcher.Field.PRICE, QuotesFetcher.Field.PRICE_CHANGE_24H)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,176 +1,79 @@
|
|||
package com.tangem.data.quotes.single
|
||||
|
||||
import arrow.core.left
|
||||
import arrow.core.right
|
||||
import com.google.common.truth.Truth
|
||||
import com.tangem.common.test.data.quote.MockQuoteResponseFactory
|
||||
import com.tangem.data.quotes.multi.DefaultMultiQuoteStatusFetcher
|
||||
import com.tangem.data.quotes.store.QuotesStatusesStore
|
||||
import com.tangem.data.quotes.store.setSourceAsCache
|
||||
import com.tangem.data.quotes.store.setSourceAsOnlyCache
|
||||
import com.tangem.datasource.api.common.response.ApiResponse
|
||||
import com.tangem.datasource.api.common.response.ApiResponseError
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.api.tangemTech.models.CurrenciesResponse
|
||||
import com.tangem.datasource.api.tangemTech.models.QuotesResponse
|
||||
import com.tangem.datasource.appcurrency.AppCurrencyResponseStore
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
|
||||
import com.tangem.domain.quotes.single.SingleQuoteStatusFetcher
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
import io.mockk.clearMocks
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.coVerifyOrder
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.math.BigDecimal
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
internal class DefaultSingleQuoteStatusFetcherTest {
|
||||
|
||||
private val tangemTechApi = mockk<TangemTechApi>(relaxed = true)
|
||||
private val appCurrencyResponseStore = mockk<AppCurrencyResponseStore>(relaxed = true)
|
||||
private val quotesStore = mockk<QuotesStatusesStore>(relaxed = true)
|
||||
|
||||
private val multiFetcher = DefaultMultiQuoteStatusFetcher(
|
||||
tangemTechApi = tangemTechApi,
|
||||
appCurrencyResponseStore = appCurrencyResponseStore,
|
||||
quotesStatusesStore = quotesStore,
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
)
|
||||
|
||||
private val multiFetcher = mockk<MultiQuoteStatusFetcher>()
|
||||
private val singleFetcher = DefaultSingleQuoteStatusFetcher(multiFetcher)
|
||||
|
||||
@Test
|
||||
fun `fetch single quote successfully`() = runTest {
|
||||
val params = SingleQuoteStatusFetcher.Params(rawCurrencyId = currenciesId, appCurrencyId = null)
|
||||
|
||||
coEvery { appCurrencyResponseStore.getSyncOrNull() } returns usdAppCurrency
|
||||
|
||||
val coinIds = "BTC"
|
||||
coEvery {
|
||||
tangemTechApi.getQuotes(currencyId = "usd", coinIds = coinIds)
|
||||
} returns ApiResponse.Success(successResponse)
|
||||
|
||||
val actual = singleFetcher(params)
|
||||
|
||||
coVerifyOrder {
|
||||
quotesStore.setSourceAsCache(currenciesIds = setOf(params.rawCurrencyId))
|
||||
appCurrencyResponseStore.getSyncOrNull()
|
||||
tangemTechApi.getQuotes(currencyId = "usd", coinIds = coinIds)
|
||||
quotesStore.store(values = successResponse.quotes)
|
||||
}
|
||||
|
||||
coVerify(inverse = true) {
|
||||
quotesStore.setSourceAsOnlyCache(currenciesIds = any())
|
||||
}
|
||||
|
||||
Truth.assertThat(actual.isRight()).isTrue()
|
||||
@BeforeEach
|
||||
fun resetMocks() {
|
||||
clearMocks(multiFetcher)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fetch single quote successfully if appCurrencyId from params is not null`() = runTest {
|
||||
val appCurrencyId = "usd"
|
||||
val params = SingleQuoteStatusFetcher.Params(rawCurrencyId = currenciesId, appCurrencyId = appCurrencyId)
|
||||
fun `fetch successfully if multiFetcher returns success`() = runTest {
|
||||
// Arrange
|
||||
val params = SingleQuoteStatusFetcher.Params(rawCurrencyId = currencyId, appCurrencyId = null)
|
||||
|
||||
val coinIds = "BTC"
|
||||
coEvery {
|
||||
tangemTechApi.getQuotes(currencyId = appCurrencyId, coinIds = coinIds)
|
||||
} returns ApiResponse.Success(successResponse)
|
||||
val multiFetcherParams = MultiQuoteStatusFetcher.Params(
|
||||
currenciesIds = setOf(params.rawCurrencyId),
|
||||
appCurrencyId = params.appCurrencyId,
|
||||
)
|
||||
|
||||
coEvery { multiFetcher(multiFetcherParams) } returns Unit.right()
|
||||
|
||||
// Act
|
||||
val actual = singleFetcher(params)
|
||||
|
||||
coVerifyOrder {
|
||||
quotesStore.setSourceAsCache(currenciesIds = setOf(currenciesId))
|
||||
tangemTechApi.getQuotes(currencyId = "usd", coinIds = coinIds)
|
||||
quotesStore.store(values = successResponse.quotes)
|
||||
}
|
||||
// Assert
|
||||
val expected = Unit.right()
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
Truth.assertThat(actual.isRight()).isTrue()
|
||||
coVerify(exactly = 1) { multiFetcher(multiFetcherParams) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fetch single quote failure because appCurrencyId from params is blank`() = runTest {
|
||||
val appCurrencyId = ""
|
||||
val params = SingleQuoteStatusFetcher.Params(rawCurrencyId = currenciesId, appCurrencyId = appCurrencyId)
|
||||
fun `fetch failure if multiFetcher returns erro`() = runTest {
|
||||
// Arrange
|
||||
val params = SingleQuoteStatusFetcher.Params(rawCurrencyId = currencyId, appCurrencyId = null)
|
||||
|
||||
val multiFetcherParams = MultiQuoteStatusFetcher.Params(
|
||||
currenciesIds = setOf(params.rawCurrencyId),
|
||||
appCurrencyId = params.appCurrencyId,
|
||||
)
|
||||
|
||||
val multiFetcherError = IllegalStateException("").left()
|
||||
|
||||
coEvery { multiFetcher(multiFetcherParams) } returns multiFetcherError
|
||||
|
||||
// Act
|
||||
val actual = singleFetcher(params)
|
||||
|
||||
coVerifyOrder {
|
||||
quotesStore.setSourceAsCache(currenciesIds = setOf(currenciesId))
|
||||
quotesStore.setSourceAsOnlyCache(currenciesIds = setOf(currenciesId))
|
||||
}
|
||||
// Assert
|
||||
val expected = multiFetcherError
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
Truth.assertThat(actual.isLeft()).isTrue()
|
||||
Truth.assertThat(actual.leftOrNull()).isInstanceOf(IllegalStateException::class.java)
|
||||
Truth.assertThat(actual.leftOrNull()).hasMessageThat()
|
||||
.isEqualTo("Unable to get AppCurrency for updating quotes")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fetch single quote failure because api request failed`() = runTest {
|
||||
val params = SingleQuoteStatusFetcher.Params(rawCurrencyId = currenciesId, appCurrencyId = null)
|
||||
|
||||
coEvery { appCurrencyResponseStore.getSyncOrNull() } returns usdAppCurrency
|
||||
|
||||
val coinIds = "BTC"
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val errorResponse = ApiResponse.Error(ApiResponseError.NetworkException) as ApiResponse<QuotesResponse>
|
||||
coEvery { tangemTechApi.getQuotes(currencyId = "usd", coinIds = coinIds) } returns errorResponse
|
||||
|
||||
val actual = singleFetcher(params)
|
||||
|
||||
coVerifyOrder {
|
||||
quotesStore.setSourceAsCache(currenciesIds = setOf(currenciesId))
|
||||
appCurrencyResponseStore.getSyncOrNull()
|
||||
tangemTechApi.getQuotes(currencyId = "usd", coinIds = coinIds)
|
||||
quotesStore.setSourceAsOnlyCache(currenciesIds = setOf(currenciesId))
|
||||
}
|
||||
|
||||
coVerify(inverse = true) {
|
||||
quotesStore.store(values = any())
|
||||
}
|
||||
|
||||
Truth.assertThat(actual.isLeft()).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fetch single quote failure because app currency not found`() = runTest {
|
||||
val params = SingleQuoteStatusFetcher.Params(rawCurrencyId = currenciesId, appCurrencyId = null)
|
||||
|
||||
coEvery { appCurrencyResponseStore.getSyncOrNull() } returns null
|
||||
|
||||
val actual = singleFetcher(params)
|
||||
|
||||
coVerifyOrder {
|
||||
quotesStore.setSourceAsCache(currenciesIds = setOf(currenciesId))
|
||||
appCurrencyResponseStore.getSyncOrNull()
|
||||
quotesStore.setSourceAsOnlyCache(currenciesIds = setOf(currenciesId))
|
||||
}
|
||||
|
||||
coVerify(inverse = true) {
|
||||
tangemTechApi.getQuotes(currencyId = any(), coinIds = any())
|
||||
quotesStore.store(values = any())
|
||||
}
|
||||
|
||||
Truth.assertThat(actual.isLeft()).isTrue()
|
||||
coVerify(exactly = 1) { multiFetcher(multiFetcherParams) }
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
||||
val currenciesId = CryptoCurrency.RawID(value = "BTC")
|
||||
|
||||
val usdAppCurrency = CurrenciesResponse.Currency(
|
||||
id = "USD".lowercase(),
|
||||
code = "USD",
|
||||
name = "US Dollar",
|
||||
unit = "$",
|
||||
type = "fiat",
|
||||
rateBTC = "",
|
||||
)
|
||||
|
||||
val successResponse = QuotesResponse(
|
||||
quotes = mapOf(
|
||||
"BTC" to MockQuoteResponseFactory.createSinglePrice(value = BigDecimal.ONE),
|
||||
),
|
||||
)
|
||||
val currencyId = CryptoCurrency.RawID(value = "BTC")
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue