Updated on 2026-08-14
This commit is contained in:
parent
45bd51c738
commit
717b8e2df2
4 changed files with 134 additions and 17 deletions
|
|
@ -1,14 +1,22 @@
|
|||
package com.tangem.common.test.data.quote
|
||||
|
||||
import com.tangem.datasource.api.tangemTech.models.QuotesResponse
|
||||
import com.tangem.datasource.local.quote.converter.QuoteStatusConverter
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.quote.QuoteStatus
|
||||
import com.tangem.utils.extensions.orZero
|
||||
|
||||
fun QuotesResponse.Quote.toDomain(rawCurrencyId: String, source: StatusSource = StatusSource.ACTUAL): QuoteStatus {
|
||||
return QuoteStatusConverter(source = source).convert(value = mapOf(rawCurrencyId to this).entries.first())
|
||||
return QuoteStatus(
|
||||
rawCurrencyId = CryptoCurrency.RawID(rawCurrencyId),
|
||||
value = QuoteStatus.Data(
|
||||
source = source,
|
||||
fiatRate = price.orZero(),
|
||||
priceChange = priceChange24h.orZero().movePointLeft(2),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fun Pair<String, QuotesResponse.Quote>.toDomain(source: StatusSource = StatusSource.ACTUAL): QuoteStatus {
|
||||
return QuoteStatusConverter(source = source).convert(value = mapOf(this).entries.first())
|
||||
return second.toDomain(rawCurrencyId = first, source = source)
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.datasource.local.quote.converter
|
||||
package com.tangem.data.quotes.converter
|
||||
|
||||
import com.tangem.datasource.api.tangemTech.models.QuotesResponse
|
||||
import com.tangem.domain.models.StatusSource
|
||||
|
|
@ -14,19 +14,10 @@ import com.tangem.utils.extensions.orZero
|
|||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class QuoteStatusConverter(
|
||||
internal class QuoteStatusConverter(
|
||||
private val source: StatusSource,
|
||||
) : Converter<Map.Entry<String, QuotesResponse.Quote>, QuoteStatus> {
|
||||
|
||||
/**
|
||||
* Secondary constructor
|
||||
*
|
||||
* @param isCached flag that determines whether the quote is a cache
|
||||
*/
|
||||
constructor(isCached: Boolean) : this(
|
||||
source = if (isCached) StatusSource.CACHE else StatusSource.ACTUAL,
|
||||
)
|
||||
|
||||
override fun convert(value: Map.Entry<String, QuotesResponse.Quote>): QuoteStatus {
|
||||
val (currencyId, quote) = value
|
||||
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package com.tangem.data.quotes.store
|
||||
|
||||
import androidx.datastore.core.DataStore
|
||||
import com.tangem.data.quotes.converter.QuoteStatusConverter
|
||||
import com.tangem.datasource.api.tangemTech.models.QuotesResponse
|
||||
import com.tangem.datasource.local.datastore.RuntimeSharedStore
|
||||
import com.tangem.datasource.local.quote.converter.QuoteStatusConverter
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.quote.QuoteStatus
|
||||
|
|
@ -41,7 +41,7 @@ internal class DefaultQuotesStatusesStore(
|
|||
if (cachedStatuses.isNullOrEmpty()) return@launch
|
||||
|
||||
runtimeStore.store(
|
||||
value = QuoteStatusConverter(isCached = true).convertSet(input = cachedStatuses.entries),
|
||||
value = QuoteStatusConverter(source = StatusSource.CACHE).convertSet(input = cachedStatuses.entries),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -95,7 +95,7 @@ internal class DefaultQuotesStatusesStore(
|
|||
}
|
||||
|
||||
private suspend fun storeInRuntime(values: CurrencyIdWithQuote) {
|
||||
val quotes = QuoteStatusConverter(isCached = false).convertSet(input = values.entries)
|
||||
val quotes = QuoteStatusConverter(source = StatusSource.ACTUAL).convertSet(input = values.entries)
|
||||
|
||||
runtimeStore.update(default = emptySet()) { saved ->
|
||||
saved.addOrReplace(items = quotes) { prev, new -> prev.rawCurrencyId == new.rawCurrencyId }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,118 @@
|
|||
package com.tangem.data.quotes.converter
|
||||
|
||||
import com.google.common.truth.Truth
|
||||
import com.tangem.common.test.data.quote.MockQuoteResponseFactory
|
||||
import com.tangem.common.test.data.quote.toDomain
|
||||
import com.tangem.common.test.utils.ProvideTestModels
|
||||
import com.tangem.datasource.api.tangemTech.models.QuotesResponse
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.quote.QuoteStatus
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.params.ParameterizedTest
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
internal class QuoteStatusConverterTest {
|
||||
|
||||
private val ethQuoteDM = "ETH" to MockQuoteResponseFactory.createSinglePrice(value = BigDecimal.ONE)
|
||||
|
||||
@ParameterizedTest
|
||||
@ProvideTestModels
|
||||
fun convert(model: ConvertTestModel) {
|
||||
// Act
|
||||
val actual = QuoteStatusConverter(source = model.source).convert(value = model.value)
|
||||
|
||||
// Assert
|
||||
val expected = model.expected
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
private fun provideTestModels() = listOf(
|
||||
ConvertTestModel(
|
||||
source = StatusSource.CACHE,
|
||||
value = createEntry(value = ethQuoteDM),
|
||||
expected = ethQuoteDM.toDomain(source = StatusSource.CACHE),
|
||||
),
|
||||
ConvertTestModel(
|
||||
source = StatusSource.ONLY_CACHE,
|
||||
value = createEntry(value = ethQuoteDM),
|
||||
expected = ethQuoteDM.toDomain(source = StatusSource.ONLY_CACHE),
|
||||
),
|
||||
ConvertTestModel(
|
||||
source = StatusSource.ACTUAL,
|
||||
value = createEntry(value = ethQuoteDM),
|
||||
expected = ethQuoteDM.toDomain(source = StatusSource.ACTUAL),
|
||||
),
|
||||
ConvertTestModel(
|
||||
source = StatusSource.ACTUAL,
|
||||
value = createEntry(
|
||||
value = "ETH" to QuotesResponse.Quote(
|
||||
price = null,
|
||||
priceChange24h = null,
|
||||
priceChange1w = null,
|
||||
priceChange30d = null,
|
||||
),
|
||||
),
|
||||
expected = QuoteStatus(
|
||||
rawCurrencyId = CryptoCurrency.RawID("ETH"),
|
||||
value = QuoteStatus.Data(
|
||||
source = StatusSource.ACTUAL,
|
||||
fiatRate = BigDecimal.ZERO,
|
||||
priceChange = BigDecimal("0.00"),
|
||||
),
|
||||
),
|
||||
),
|
||||
ConvertTestModel(
|
||||
source = StatusSource.ACTUAL,
|
||||
value = createEntry(
|
||||
value = "ETH" to QuotesResponse.Quote(
|
||||
price = null,
|
||||
priceChange24h = null,
|
||||
priceChange1w = BigDecimal.ZERO,
|
||||
priceChange30d = BigDecimal.ZERO,
|
||||
),
|
||||
),
|
||||
expected = QuoteStatus(
|
||||
rawCurrencyId = CryptoCurrency.RawID("ETH"),
|
||||
value = QuoteStatus.Data(
|
||||
source = StatusSource.ACTUAL,
|
||||
fiatRate = BigDecimal.ZERO,
|
||||
priceChange = BigDecimal("0.00"),
|
||||
),
|
||||
),
|
||||
),
|
||||
ConvertTestModel(
|
||||
source = StatusSource.ACTUAL,
|
||||
value = createEntry(
|
||||
value = "ETH" to QuotesResponse.Quote(
|
||||
price = BigDecimal.ONE,
|
||||
priceChange24h = BigDecimal.ONE,
|
||||
priceChange1w = null,
|
||||
priceChange30d = null,
|
||||
),
|
||||
),
|
||||
expected = QuoteStatus(
|
||||
rawCurrencyId = CryptoCurrency.RawID("ETH"),
|
||||
value = QuoteStatus.Data(
|
||||
source = StatusSource.ACTUAL,
|
||||
fiatRate = BigDecimal.ONE,
|
||||
priceChange = BigDecimal("0.01"),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
private fun createEntry(value: Pair<String, QuotesResponse.Quote>): Map.Entry<String, QuotesResponse.Quote> {
|
||||
return mapOf(value).entries.first()
|
||||
}
|
||||
|
||||
data class ConvertTestModel(
|
||||
val source: StatusSource,
|
||||
val value: Map.Entry<String, QuotesResponse.Quote>,
|
||||
val expected: QuoteStatus,
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue