Updated on 2026-08-14
This commit is contained in:
parent
bfd371bc33
commit
c9e78f485d
10 changed files with 164 additions and 47 deletions
|
|
@ -1,26 +0,0 @@
|
|||
package com.tangem.data.quotes
|
||||
|
||||
import com.tangem.data.quotes.store.QuotesStatusesStore
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.quotes.QuotesRepositoryV2
|
||||
import com.tangem.domain.tokens.model.QuoteStatus
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Default implementation of [QuotesRepositoryV2]
|
||||
*
|
||||
* @property quotesStore quotes store
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class DefaultQuotesRepositoryV2 @Inject constructor(
|
||||
private val quotesStore: QuotesStatusesStore,
|
||||
) : QuotesRepositoryV2 {
|
||||
|
||||
override suspend fun getMultiQuoteSyncOrNull(currenciesIds: Set<CryptoCurrency.RawID>): Set<QuoteStatus>? {
|
||||
return quotesStore.getAllSyncOrNull()?.mapTo(hashSetOf()) {
|
||||
it.takeIf { it.rawCurrencyId in currenciesIds }
|
||||
?: QuoteStatus(rawCurrencyId = it.rawCurrencyId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ import android.content.Context
|
|||
import androidx.datastore.core.DataStoreFactory
|
||||
import androidx.datastore.dataStoreFile
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.tangem.data.quotes.DefaultQuotesRepositoryV2
|
||||
import com.tangem.data.quotes.repository.DefaultQuotesRepository
|
||||
import com.tangem.data.quotes.store.DefaultQuotesStatusesStore
|
||||
import com.tangem.data.quotes.store.QuotesStatusesStore
|
||||
import com.tangem.datasource.api.tangemTech.models.QuotesResponse
|
||||
|
|
@ -12,7 +12,7 @@ import com.tangem.datasource.di.NetworkMoshi
|
|||
import com.tangem.datasource.local.datastore.RuntimeSharedStore
|
||||
import com.tangem.datasource.utils.MoshiDataStoreSerializer
|
||||
import com.tangem.datasource.utils.mapWithStringKeyTypes
|
||||
import com.tangem.domain.quotes.QuotesRepositoryV2
|
||||
import com.tangem.domain.quotes.QuotesRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
|
@ -51,5 +51,5 @@ internal object QuotesDataModule {
|
|||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun providesQuotesRepositoryV2(impl: DefaultQuotesRepositoryV2): QuotesRepositoryV2 = impl
|
||||
fun providesQuotesRepository(impl: DefaultQuotesRepository): QuotesRepository = impl
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package com.tangem.data.quotes.repository
|
||||
|
||||
import com.tangem.data.quotes.store.QuotesStatusesStore
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.quotes.QuotesRepository
|
||||
import com.tangem.domain.tokens.model.QuoteStatus
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Default implementation of [QuotesRepository]
|
||||
*
|
||||
* @property quotesStatusesStore quotes statuses store
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class DefaultQuotesRepository @Inject constructor(
|
||||
private val quotesStatusesStore: QuotesStatusesStore,
|
||||
) : QuotesRepository {
|
||||
|
||||
override suspend fun getMultiQuoteSyncOrNull(currenciesIds: Set<CryptoCurrency.RawID>): Set<QuoteStatus> {
|
||||
if (currenciesIds.isEmpty()) {
|
||||
Timber.e("currenciesIds are empty")
|
||||
return emptySet()
|
||||
}
|
||||
|
||||
val storedQuotes = quotesStatusesStore.getAllSyncOrNull()
|
||||
?.filter { it.rawCurrencyId in currenciesIds }
|
||||
|
||||
return currenciesIds.mapTo(hashSetOf()) { currencyId ->
|
||||
storedQuotes?.firstOrNull { it.rawCurrencyId == currencyId }
|
||||
?: QuoteStatus(rawCurrencyId = currencyId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
package com.tangem.data.quotes.repository
|
||||
|
||||
import com.google.common.truth.Truth
|
||||
import com.tangem.common.test.utils.ProvideTestModels
|
||||
import com.tangem.data.quotes.store.QuotesStatusesStore
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.quotes.QuotesRepository
|
||||
import com.tangem.domain.tokens.model.QuoteStatus
|
||||
import io.mockk.clearMocks
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Nested
|
||||
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 DefaultQuotesRepositoryTest {
|
||||
|
||||
private val quotesStatusesStore = mockk<QuotesStatusesStore>()
|
||||
private val repository: QuotesRepository = DefaultQuotesRepository(quotesStatusesStore = quotesStatusesStore)
|
||||
|
||||
@BeforeEach
|
||||
fun resetMocks() {
|
||||
clearMocks(quotesStatusesStore)
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
inner class GetMultiQuoteSyncOrNull {
|
||||
|
||||
private val btcRawId = CryptoCurrency.RawID(value = "BTC")
|
||||
private val ethRawId = CryptoCurrency.RawID(value = "ETH")
|
||||
|
||||
private val ethQuote = QuoteStatus(
|
||||
rawCurrencyId = ethRawId,
|
||||
value = QuoteStatus.Data(
|
||||
source = StatusSource.ACTUAL,
|
||||
fiatRate = BigDecimal.ZERO,
|
||||
priceChange = BigDecimal.ZERO,
|
||||
),
|
||||
)
|
||||
|
||||
@ParameterizedTest
|
||||
@ProvideTestModels
|
||||
fun getMultiQuoteSyncOrNull(model: GetMultiQuoteSyncOrNullModel) = runTest {
|
||||
// Arrange
|
||||
coEvery { quotesStatusesStore.getAllSyncOrNull() } returns model.initialStore
|
||||
|
||||
// Act
|
||||
val actual = repository.getMultiQuoteSyncOrNull(currenciesIds = model.currencyIds)
|
||||
|
||||
// Assert
|
||||
val expected = model.expected
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
private fun provideTestModels() = listOf(
|
||||
GetMultiQuoteSyncOrNullModel(
|
||||
initialStore = null,
|
||||
currencyIds = emptySet(),
|
||||
expected = emptySet(),
|
||||
),
|
||||
GetMultiQuoteSyncOrNullModel(
|
||||
initialStore = null,
|
||||
currencyIds = setOf(ethRawId),
|
||||
expected = setOf(QuoteStatus(rawCurrencyId = ethRawId)),
|
||||
),
|
||||
GetMultiQuoteSyncOrNullModel(
|
||||
initialStore = emptySet(),
|
||||
currencyIds = emptySet(),
|
||||
expected = emptySet(),
|
||||
),
|
||||
GetMultiQuoteSyncOrNullModel(
|
||||
initialStore = emptySet(),
|
||||
currencyIds = setOf(ethRawId),
|
||||
expected = setOf(QuoteStatus(rawCurrencyId = ethRawId)),
|
||||
),
|
||||
GetMultiQuoteSyncOrNullModel(
|
||||
initialStore = setOf(ethQuote),
|
||||
currencyIds = setOf(ethRawId),
|
||||
expected = setOf(ethQuote),
|
||||
),
|
||||
GetMultiQuoteSyncOrNullModel(
|
||||
initialStore = setOf(QuoteStatus(rawCurrencyId = btcRawId)),
|
||||
currencyIds = setOf(ethRawId),
|
||||
expected = setOf(QuoteStatus(rawCurrencyId = ethRawId)),
|
||||
),
|
||||
GetMultiQuoteSyncOrNullModel(
|
||||
initialStore = setOf(ethQuote, QuoteStatus(rawCurrencyId = btcRawId)),
|
||||
currencyIds = setOf(ethRawId),
|
||||
expected = setOf(ethQuote),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
data class GetMultiQuoteSyncOrNullModel(
|
||||
val initialStore: Set<QuoteStatus>?,
|
||||
val currencyIds: Set<CryptoCurrency.RawID>,
|
||||
val expected: Set<QuoteStatus>?,
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue