Updated on 2026-08-14
This commit is contained in:
parent
d48ba8a8bd
commit
3d5a8a55ed
20 changed files with 899 additions and 134 deletions
|
|
@ -154,7 +154,8 @@ interface TangemTechApi {
|
|||
suspend fun saveWalletAccounts(
|
||||
@Path("walletId") walletId: String,
|
||||
@Header("If-Match") ifMatch: String,
|
||||
): ApiResponse<SaveWalletAccountsResponse>
|
||||
@Body body: SaveWalletAccountsResponse,
|
||||
): ApiResponse<Unit>
|
||||
|
||||
@GET("/v1/wallets/{walletId}/accounts/archived")
|
||||
suspend fun getWalletArchivedAccounts(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.data.account.converter
|
||||
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
|
|
@ -14,7 +16,21 @@ import javax.inject.Inject
|
|||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class AccountConverterFactoryContainer @Inject constructor(
|
||||
val accountsListCF: AccountListConverter.Factory,
|
||||
val getWalletAccountsResponseCF: GetWalletAccountsResponseConverter.Factory,
|
||||
val cryptoPortfolioCF: CryptoPortfolioConverter.Factory,
|
||||
)
|
||||
private val accountsListCF: AccountListConverter.Factory,
|
||||
private val cryptoPortfolioCF: CryptoPortfolioConverter.Factory,
|
||||
private val userWalletsStore: UserWalletsStore,
|
||||
) {
|
||||
|
||||
fun createAccountListConverter(userWalletId: UserWalletId): AccountListConverter {
|
||||
val userWallet = userWalletsStore.getSyncStrict(key = userWalletId)
|
||||
|
||||
return accountsListCF.create(userWallet)
|
||||
}
|
||||
|
||||
fun createCryptoPortfolioConverter(userWalletId: UserWalletId): CryptoPortfolioConverter {
|
||||
val userWallet = userWalletsStore.getSyncStrict(key = userWalletId)
|
||||
|
||||
return cryptoPortfolioCF.create(userWallet)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,13 @@
|
|||
package com.tangem.data.account.di
|
||||
|
||||
import com.tangem.data.account.converter.AccountConverterFactoryContainer
|
||||
import com.tangem.data.account.repository.DefaultAccountsCRUDRepository
|
||||
import com.tangem.datasource.local.datastore.RuntimeSharedStore
|
||||
import com.tangem.data.account.store.AccountsResponseStoreFactory
|
||||
import com.tangem.data.account.store.ArchivedAccountsStoreFactory
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.account.repository.AccountsCRUDRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -16,10 +20,20 @@ internal object AccountDataModule {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideAccountsCRUDRepository(userWalletsStore: UserWalletsStore): AccountsCRUDRepository {
|
||||
fun provideAccountsCRUDRepository(
|
||||
tangemTechApi: TangemTechApi,
|
||||
accountsResponseStoreFactory: AccountsResponseStoreFactory,
|
||||
userWalletsStore: UserWalletsStore,
|
||||
accountConverterFactoryContainer: AccountConverterFactoryContainer,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): AccountsCRUDRepository {
|
||||
return DefaultAccountsCRUDRepository(
|
||||
runtimeStore = RuntimeSharedStore(),
|
||||
tangemTechApi = tangemTechApi,
|
||||
accountsResponseStoreFactory = accountsResponseStoreFactory,
|
||||
archivedAccountsStoreFactory = ArchivedAccountsStoreFactory,
|
||||
userWalletsStore = userWalletsStore,
|
||||
convertersContainer = accountConverterFactoryContainer,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,90 +1,150 @@
|
|||
package com.tangem.data.account.repository
|
||||
|
||||
import arrow.core.Option
|
||||
import arrow.core.Option.Companion.catch
|
||||
import arrow.core.none
|
||||
import arrow.core.raise.option
|
||||
import com.tangem.datasource.local.datastore.RuntimeSharedStore
|
||||
import arrow.core.toOption
|
||||
import com.tangem.data.account.converter.AccountConverterFactoryContainer
|
||||
import com.tangem.data.account.converter.ArchivedAccountConverter
|
||||
import com.tangem.data.account.converter.SaveWalletAccountsResponseConverter
|
||||
import com.tangem.data.account.store.AccountsResponseStore
|
||||
import com.tangem.data.account.store.AccountsResponseStoreFactory
|
||||
import com.tangem.data.account.store.ArchivedAccountsStore
|
||||
import com.tangem.data.account.store.ArchivedAccountsStoreFactory
|
||||
import com.tangem.datasource.api.common.response.getOrThrow
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.api.tangemTech.models.account.GetWalletAccountsResponse
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.account.models.AccountList
|
||||
import com.tangem.domain.account.models.ArchivedAccount
|
||||
import com.tangem.domain.account.repository.AccountsCRUDRepository
|
||||
import com.tangem.domain.models.account.*
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.utils.extensions.addOrReplace
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
// TODO: [REDACTED_JIRA]
|
||||
internal class DefaultAccountsCRUDRepository(
|
||||
private val runtimeStore: RuntimeSharedStore<List<AccountList>>,
|
||||
private val tangemTechApi: TangemTechApi,
|
||||
private val accountsResponseStoreFactory: AccountsResponseStoreFactory,
|
||||
private val archivedAccountsStoreFactory: ArchivedAccountsStoreFactory,
|
||||
private val userWalletsStore: UserWalletsStore,
|
||||
private val convertersContainer: AccountConverterFactoryContainer,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : AccountsCRUDRepository {
|
||||
|
||||
override suspend fun getAccounts(userWalletId: UserWalletId): Option<AccountList> = catch {
|
||||
runtimeStore.getSyncOrNull()
|
||||
?.firstOrNull { it.userWallet.walletId == userWalletId }
|
||||
?: return none()
|
||||
private val saveAccountsMutex = Mutex()
|
||||
|
||||
override suspend fun getAccountListSync(userWalletId: UserWalletId): Option<AccountList> = option {
|
||||
val accountListResponse = getAccountsResponseSync(userWalletId = userWalletId)
|
||||
|
||||
ensureNotNull(accountListResponse)
|
||||
|
||||
val converter = convertersContainer.createAccountListConverter(userWalletId = userWalletId)
|
||||
converter.convert(value = accountListResponse)
|
||||
}
|
||||
|
||||
override suspend fun getAccount(accountId: AccountId): Option<Account.CryptoPortfolio> = catch {
|
||||
runtimeStore.getSyncOrNull().orEmpty()
|
||||
.flatMap { it.accounts }
|
||||
.firstOrNull { it.accountId == accountId } as? Account.CryptoPortfolio
|
||||
?: return none()
|
||||
override suspend fun getAccountSync(accountId: AccountId): Option<Account.CryptoPortfolio> = option {
|
||||
val userWalletId = accountId.userWalletId
|
||||
|
||||
val accountResponse = getAccountsResponseSync(userWalletId = userWalletId)
|
||||
?.accounts?.firstOrNull { it.id == accountId.value }
|
||||
|
||||
ensureNotNull(accountResponse)
|
||||
|
||||
val converter = convertersContainer.createCryptoPortfolioConverter(userWalletId = userWalletId)
|
||||
converter.convert(value = accountResponse)
|
||||
}
|
||||
|
||||
override suspend fun getArchivedAccount(accountId: AccountId): Option<ArchivedAccount> = option {
|
||||
createMockArchivedAccount(userWalletId = accountId.userWalletId)
|
||||
override suspend fun getArchivedAccountSync(accountId: AccountId): Option<ArchivedAccount> {
|
||||
val store = getArchivedAccountsStore(userWalletId = accountId.userWalletId)
|
||||
|
||||
return store.getSyncOrNull()
|
||||
?.firstOrNull { it.accountId == accountId }
|
||||
.toOption()
|
||||
}
|
||||
|
||||
override suspend fun getArchivedAccountsSync(userWalletId: UserWalletId): Option<List<ArchivedAccount>> = option {
|
||||
listOf(
|
||||
createMockArchivedAccount(userWalletId),
|
||||
)
|
||||
override suspend fun getArchivedAccountListSync(userWalletId: UserWalletId): Option<List<ArchivedAccount>> {
|
||||
val store = getArchivedAccountsStore(userWalletId = userWalletId)
|
||||
|
||||
return store.getSyncOrNull().toOption()
|
||||
}
|
||||
|
||||
override fun getArchivedAccounts(userWalletId: UserWalletId): Flow<List<ArchivedAccount>> {
|
||||
return flow {
|
||||
getArchivedAccountsSync(userWalletId).getOrNull().orEmpty()
|
||||
}
|
||||
val store = getArchivedAccountsStore(userWalletId = userWalletId)
|
||||
|
||||
return store.get()
|
||||
}
|
||||
|
||||
override suspend fun fetchArchivedAccounts(userWalletId: UserWalletId) = Unit
|
||||
override suspend fun fetchArchivedAccounts(userWalletId: UserWalletId) {
|
||||
val response = withContext(dispatchers.io) {
|
||||
tangemTechApi.getWalletArchivedAccounts(walletId = userWalletId.stringValue).getOrThrow()
|
||||
}
|
||||
|
||||
val store = getArchivedAccountsStore(userWalletId = userWalletId)
|
||||
val converter = ArchivedAccountConverter(userWalletId = userWalletId)
|
||||
|
||||
val archivedAccounts = converter.convertList(input = response.accounts)
|
||||
|
||||
store.store(value = archivedAccounts)
|
||||
}
|
||||
|
||||
override suspend fun saveAccounts(accountList: AccountList) {
|
||||
runtimeStore.update(emptyList()) {
|
||||
it.addOrReplace(accountList) { it.userWallet.walletId == accountList.userWallet.walletId }
|
||||
saveAccountsMutex.withLock {
|
||||
val store = getAccountsResponseStore(userWalletId = accountList.userWallet.walletId)
|
||||
|
||||
val version = store.data.firstOrNull()?.wallet?.version ?: 0
|
||||
val body = SaveWalletAccountsResponseConverter.convert(value = accountList)
|
||||
|
||||
withContext(dispatchers.io) {
|
||||
tangemTechApi.saveWalletAccounts(
|
||||
walletId = accountList.userWallet.walletId.stringValue,
|
||||
ifMatch = version.toString(),
|
||||
body = body,
|
||||
)
|
||||
.getOrThrow()
|
||||
}
|
||||
|
||||
val converter = convertersContainer.getWalletAccountsResponseCF.create(
|
||||
userWallet = accountList.userWallet,
|
||||
version = version,
|
||||
)
|
||||
|
||||
val accountsResponse = converter.convert(value = accountList)
|
||||
|
||||
store.updateData { accountsResponse }
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getTotalAccountsCount(userWalletId: UserWalletId): Int {
|
||||
val activeAccountsCount = runtimeStore.getSyncOrNull()?.size ?: 1
|
||||
override suspend fun getTotalAccountsCount(userWalletId: UserWalletId): Option<Int> = option {
|
||||
val accountListResponse = getAccountsResponseSync(userWalletId = userWalletId)
|
||||
|
||||
return activeAccountsCount + 1
|
||||
ensureNotNull(accountListResponse)
|
||||
|
||||
return accountListResponse.wallet.totalAccounts.toOption()
|
||||
}
|
||||
|
||||
override fun getUserWallet(userWalletId: UserWalletId): UserWallet {
|
||||
return userWalletsStore.getSyncStrict(userWalletId)
|
||||
}
|
||||
|
||||
private fun createMockArchivedAccount(userWalletId: UserWalletId): ArchivedAccount {
|
||||
val derivationIndex = DerivationIndex(value = 1000).getOrNull()!!
|
||||
private suspend fun getAccountsResponseSync(userWalletId: UserWalletId): GetWalletAccountsResponse? {
|
||||
val store = getAccountsResponseStore(userWalletId = userWalletId)
|
||||
return store.data.firstOrNull()
|
||||
}
|
||||
|
||||
return ArchivedAccount(
|
||||
accountId = AccountId.forCryptoPortfolio(
|
||||
userWalletId = userWalletId,
|
||||
derivationIndex = derivationIndex,
|
||||
),
|
||||
name = AccountName("Archived Account").getOrNull()!!,
|
||||
icon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
|
||||
derivationIndex = derivationIndex,
|
||||
tokensCount = 2,
|
||||
networksCount = 1,
|
||||
)
|
||||
private fun getAccountsResponseStore(userWalletId: UserWalletId): AccountsResponseStore {
|
||||
return accountsResponseStoreFactory.create(userWalletId = userWalletId)
|
||||
}
|
||||
|
||||
private fun getArchivedAccountsStore(userWalletId: UserWalletId): ArchivedAccountsStore {
|
||||
return archivedAccountsStoreFactory.create(userWalletId)
|
||||
}
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ import java.util.concurrent.ConcurrentHashMap
|
|||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class ArchivedAccountsStoreFactory {
|
||||
internal object ArchivedAccountsStoreFactory {
|
||||
|
||||
private val createdRuntimeStores = ConcurrentHashMap<UserWalletId, ArchivedAccountsStore>()
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,664 @@
|
|||
package com.tangem.data.account.repository
|
||||
|
||||
import arrow.core.None
|
||||
import arrow.core.toOption
|
||||
import com.google.common.truth.Truth
|
||||
import com.tangem.common.test.utils.getEmittedValues
|
||||
import com.tangem.data.account.converter.*
|
||||
import com.tangem.data.account.store.AccountsResponseStore
|
||||
import com.tangem.data.account.store.AccountsResponseStoreFactory
|
||||
import com.tangem.data.account.store.ArchivedAccountsStore
|
||||
import com.tangem.data.account.store.ArchivedAccountsStoreFactory
|
||||
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.account.GetWalletAccountsResponse
|
||||
import com.tangem.datasource.api.tangemTech.models.account.GetWalletArchivedAccountsResponse
|
||||
import com.tangem.datasource.api.tangemTech.models.account.WalletAccountDTO
|
||||
import com.tangem.datasource.local.datastore.RuntimeStateStore
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.account.models.AccountList
|
||||
import com.tangem.domain.account.models.ArchivedAccount
|
||||
import com.tangem.domain.models.account.Account.CryptoPortfolio
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.account.AccountName
|
||||
import com.tangem.domain.models.account.CryptoPortfolioIcon
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
import io.mockk.*
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.*
|
||||
import kotlin.time.Duration.Companion.minutes
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class DefaultAccountsCRUDRepositoryTest {
|
||||
|
||||
private val tangemTechApi: TangemTechApi = mockk()
|
||||
|
||||
private val accountsResponseStoreFactory: AccountsResponseStoreFactory = mockk()
|
||||
private val accountsResponseStore: AccountsResponseStore = mockk()
|
||||
private val accountsResponseStoreFlow = MutableStateFlow<GetWalletAccountsResponse?>(value = null)
|
||||
|
||||
private val archivedAccountsStoreFactory: ArchivedAccountsStoreFactory = mockk()
|
||||
private val archivedAccountsInnerStore = RuntimeStateStore<List<ArchivedAccount>?>(defaultValue = null)
|
||||
private val archivedAccountsStore = ArchivedAccountsStore(runtimeStore = archivedAccountsInnerStore)
|
||||
|
||||
private val userWalletsStore: UserWalletsStore = mockk()
|
||||
|
||||
private val convertersContainer: AccountConverterFactoryContainer = mockk()
|
||||
private val accountListConverter: AccountListConverter = mockk()
|
||||
private val cryptoPortfolioConverter: CryptoPortfolioConverter = mockk()
|
||||
|
||||
private val repository = DefaultAccountsCRUDRepository(
|
||||
tangemTechApi = tangemTechApi,
|
||||
accountsResponseStoreFactory = accountsResponseStoreFactory,
|
||||
archivedAccountsStoreFactory = archivedAccountsStoreFactory,
|
||||
userWalletsStore = userWalletsStore,
|
||||
convertersContainer = convertersContainer,
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
)
|
||||
|
||||
private val userWalletId = UserWalletId("011")
|
||||
|
||||
@BeforeAll
|
||||
fun setup() {
|
||||
every { accountsResponseStoreFactory.create(userWalletId) } returns accountsResponseStore
|
||||
every { accountsResponseStore.data } returns accountsResponseStoreFlow
|
||||
|
||||
every { convertersContainer.createAccountListConverter(userWalletId) } returns accountListConverter
|
||||
every { convertersContainer.createCryptoPortfolioConverter(userWalletId) } returns cryptoPortfolioConverter
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
fun setupEach() {
|
||||
every { archivedAccountsStoreFactory.create(userWalletId) } returns archivedAccountsStore
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
fun tearDownEach() {
|
||||
accountsResponseStoreFlow.value = null
|
||||
archivedAccountsInnerStore.clear()
|
||||
|
||||
clearMocks(
|
||||
tangemTechApi,
|
||||
archivedAccountsStoreFactory,
|
||||
accountListConverter,
|
||||
cryptoPortfolioConverter,
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
inner class GetAccountListSync {
|
||||
|
||||
@Test
|
||||
fun `getAccounts should return None when account list response is null`() = runTest {
|
||||
// Arrange
|
||||
accountsResponseStoreFlow.value = null
|
||||
|
||||
// Act
|
||||
val actual = repository.getAccountListSync(userWalletId)
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isEqualTo(None)
|
||||
|
||||
verifyOrder {
|
||||
accountsResponseStoreFactory.create(userWalletId)
|
||||
accountsResponseStore.data
|
||||
}
|
||||
|
||||
verify(inverse = true) { accountListConverter.convert(value = any()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getAccounts should return AccountList when account list response is not null`() = runTest {
|
||||
// Arrange
|
||||
val response = mockk<GetWalletAccountsResponse>()
|
||||
val accountList = mockk<AccountList>()
|
||||
|
||||
accountsResponseStoreFlow.value = response
|
||||
|
||||
every { accountListConverter.convert(response) } returns accountList
|
||||
|
||||
// Act
|
||||
val actual = repository.getAccountListSync(userWalletId)
|
||||
|
||||
// Assert
|
||||
val expected = accountList.toOption()
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
verifyOrder {
|
||||
accountsResponseStoreFactory.create(userWalletId)
|
||||
accountsResponseStore.data
|
||||
convertersContainer.createAccountListConverter(userWalletId = userWalletId)
|
||||
accountListConverter.convert(response)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getAccounts should throw exception if converter throws exception`() = runTest {
|
||||
// Arrange
|
||||
val response = mockk<GetWalletAccountsResponse>()
|
||||
mockk<AccountList>()
|
||||
|
||||
accountsResponseStoreFlow.value = response
|
||||
|
||||
val exception = Exception("Test error")
|
||||
|
||||
every { accountListConverter.convert(response) } throws exception
|
||||
|
||||
// Act
|
||||
val actual = runCatching { repository.getAccountListSync(userWalletId) }.exceptionOrNull()!!
|
||||
|
||||
// Assert
|
||||
val expected = exception
|
||||
Truth.assertThat(actual).isSameInstanceAs(expected)
|
||||
Truth.assertThat(actual).hasMessageThat().isEqualTo(expected.message)
|
||||
|
||||
verifyOrder {
|
||||
accountsResponseStoreFactory.create(userWalletId)
|
||||
accountsResponseStore.data
|
||||
convertersContainer.createAccountListConverter(userWalletId = userWalletId)
|
||||
accountListConverter.convert(response)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
inner class GetAccountSync {
|
||||
|
||||
private val accountId = AccountId.forCryptoPortfolio(userWalletId, DerivationIndex.Main)
|
||||
|
||||
@Test
|
||||
fun `getAccount should return None when account response is null`() = runTest {
|
||||
// Arrange
|
||||
val response = null
|
||||
|
||||
accountsResponseStoreFlow.value = response
|
||||
|
||||
// Act
|
||||
val actual = repository.getAccountSync(accountId)
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isEqualTo(None)
|
||||
|
||||
verifyOrder {
|
||||
accountsResponseStoreFactory.create(userWalletId)
|
||||
accountsResponseStore.data
|
||||
}
|
||||
|
||||
verify(inverse = true) { convertersContainer.createCryptoPortfolioConverter(userWalletId = any()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getAccount should return None when accountDto is not found`() = runTest {
|
||||
// Arrange
|
||||
val response = mockk<GetWalletAccountsResponse> {
|
||||
every { this@mockk.accounts } returns emptyList()
|
||||
}
|
||||
|
||||
accountsResponseStoreFlow.value = response
|
||||
|
||||
// Act
|
||||
val actual = repository.getAccountSync(accountId)
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isEqualTo(None)
|
||||
|
||||
verifyOrder {
|
||||
accountsResponseStoreFactory.create(userWalletId)
|
||||
accountsResponseStore.data
|
||||
}
|
||||
|
||||
verify(inverse = true) { convertersContainer.createCryptoPortfolioConverter(userWalletId = any()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getAccount should return Account_CryptoPortfolio when account response is not null`() = runTest {
|
||||
// Arrange
|
||||
val accountDTO = mockk<WalletAccountDTO> {
|
||||
every { this@mockk.id } returns accountId.value
|
||||
}
|
||||
|
||||
val response = mockk<GetWalletAccountsResponse> {
|
||||
every { this@mockk.accounts } returns listOf(accountDTO)
|
||||
}
|
||||
|
||||
accountsResponseStoreFlow.value = response
|
||||
|
||||
val cryptoPortfolio = mockk<CryptoPortfolio>()
|
||||
|
||||
every { cryptoPortfolioConverter.convert(accountDTO) } returns cryptoPortfolio
|
||||
|
||||
// Act
|
||||
val actual = repository.getAccountSync(accountId)
|
||||
|
||||
// Assert
|
||||
val expected = cryptoPortfolio.toOption()
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
verifyOrder {
|
||||
accountsResponseStoreFactory.create(userWalletId)
|
||||
accountsResponseStore.data
|
||||
convertersContainer.createCryptoPortfolioConverter(userWalletId)
|
||||
cryptoPortfolioConverter.convert(accountDTO)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getAccount should throw exception if converter throws exception`() = runTest {
|
||||
// Arrange
|
||||
val accountDTO = mockk<WalletAccountDTO> {
|
||||
every { this@mockk.id } returns accountId.value
|
||||
}
|
||||
|
||||
val response = mockk<GetWalletAccountsResponse> {
|
||||
every { this@mockk.accounts } returns listOf(accountDTO)
|
||||
}
|
||||
|
||||
accountsResponseStoreFlow.value = response
|
||||
|
||||
val exception = Exception("Test error")
|
||||
|
||||
every { cryptoPortfolioConverter.convert(accountDTO) } throws exception
|
||||
|
||||
// Act
|
||||
val actual = runCatching { repository.getAccountSync(accountId) }.exceptionOrNull()!!
|
||||
|
||||
// Assert
|
||||
val expected = exception
|
||||
Truth.assertThat(actual).isSameInstanceAs(expected)
|
||||
Truth.assertThat(actual).hasMessageThat().isEqualTo(expected.message)
|
||||
|
||||
verifyOrder {
|
||||
accountsResponseStoreFactory.create(userWalletId)
|
||||
accountsResponseStore.data
|
||||
convertersContainer.createCryptoPortfolioConverter(userWalletId)
|
||||
cryptoPortfolioConverter.convert(accountDTO)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
inner class GetArchivedAccountSync {
|
||||
|
||||
private val accountId = AccountId.forCryptoPortfolio(userWalletId, DerivationIndex.Main)
|
||||
|
||||
@Test
|
||||
fun `getArchivedAccount should return None when archived accounts are null`() = runTest {
|
||||
// Arrange
|
||||
archivedAccountsInnerStore.store(value = null)
|
||||
|
||||
// Act
|
||||
val actual = repository.getArchivedAccountSync(accountId)
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isEqualTo(None)
|
||||
|
||||
coVerifyOrder {
|
||||
archivedAccountsStoreFactory.create(userWalletId)
|
||||
archivedAccountsStore.getSyncOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getArchivedAccount should return None when archived account not found`() = runTest {
|
||||
// Arrange
|
||||
archivedAccountsInnerStore.store(value = listOf())
|
||||
archivedAccountsStore.setTimestamp(time = System.currentTimeMillis() + 3.minutes.inWholeMicroseconds)
|
||||
|
||||
// Act
|
||||
val actual = repository.getArchivedAccountSync(accountId)
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isEqualTo(None)
|
||||
|
||||
coVerifyOrder {
|
||||
archivedAccountsStoreFactory.create(userWalletId)
|
||||
archivedAccountsStore.getSyncOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getArchivedAccount should return ArchivedAccount when found`() = runTest {
|
||||
// Arrange
|
||||
val archivedAccount = ArchivedAccount(
|
||||
accountId = accountId,
|
||||
name = AccountName("Archived Account").getOrNull()!!,
|
||||
icon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
|
||||
derivationIndex = DerivationIndex.Main,
|
||||
tokensCount = 0,
|
||||
networksCount = 0,
|
||||
)
|
||||
|
||||
archivedAccountsInnerStore.store(value = listOf(archivedAccount))
|
||||
archivedAccountsStore.setTimestamp(time = System.currentTimeMillis() + 3.minutes.inWholeMicroseconds)
|
||||
|
||||
// Act
|
||||
val actual = repository.getArchivedAccountSync(accountId)
|
||||
|
||||
// Assert
|
||||
val expected = archivedAccount.toOption()
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder {
|
||||
archivedAccountsStoreFactory.create(userWalletId)
|
||||
archivedAccountsStore.getSyncOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getArchivedAccount should throws exception when store throws exception`() = runTest {
|
||||
// Arrange
|
||||
val exception = Exception("Test error")
|
||||
|
||||
coEvery { archivedAccountsStoreFactory.create(userWalletId) } throws exception
|
||||
|
||||
// Act
|
||||
val actual = runCatching { repository.getArchivedAccountSync(accountId) }.exceptionOrNull()!!
|
||||
|
||||
// Assert
|
||||
val expected = exception
|
||||
Truth.assertThat(actual).isSameInstanceAs(expected)
|
||||
Truth.assertThat(actual).hasMessageThat().isEqualTo(expected.message)
|
||||
|
||||
coVerifyOrder { archivedAccountsStoreFactory.create(userWalletId) }
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
inner class GetArchivedAccountListSync {
|
||||
|
||||
@Test
|
||||
fun `getArchivedAccountListSync should return None when archived accounts are null`() = runTest {
|
||||
// Arrange
|
||||
archivedAccountsInnerStore.store(value = null)
|
||||
|
||||
// Act
|
||||
val actual = repository.getArchivedAccountListSync(userWalletId)
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isEqualTo(None)
|
||||
|
||||
coVerifyOrder {
|
||||
archivedAccountsStoreFactory.create(userWalletId)
|
||||
archivedAccountsStore.getSyncOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getArchivedAccountListSync should return Option with list when archived accounts exist`() = runTest {
|
||||
// Arrange
|
||||
val archivedAccount1 = mockk<ArchivedAccount>()
|
||||
val archivedAccount2 = mockk<ArchivedAccount>()
|
||||
val archivedAccounts = listOf(archivedAccount1, archivedAccount2)
|
||||
archivedAccountsInnerStore.store(value = archivedAccounts)
|
||||
archivedAccountsStore.setTimestamp(time = System.currentTimeMillis() + 3.minutes.inWholeMicroseconds)
|
||||
|
||||
// Act
|
||||
val actual = repository.getArchivedAccountListSync(userWalletId)
|
||||
|
||||
// Assert
|
||||
val expected = archivedAccounts.toOption()
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder {
|
||||
archivedAccountsStoreFactory.create(userWalletId)
|
||||
archivedAccountsStore.getSyncOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getArchivedAccountListSync should throw exception when store throws exception`() = runTest {
|
||||
// Arrange
|
||||
val exception = Exception("Test error")
|
||||
coEvery { archivedAccountsStoreFactory.create(userWalletId) } throws exception
|
||||
|
||||
// Act
|
||||
val actual = runCatching { repository.getArchivedAccountListSync(userWalletId) }.exceptionOrNull()!!
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isSameInstanceAs(exception)
|
||||
Truth.assertThat(actual).hasMessageThat().isEqualTo(exception.message)
|
||||
|
||||
coVerifyOrder { archivedAccountsStoreFactory.create(userWalletId) }
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
inner class GetArchivedAccounts {
|
||||
|
||||
@Test
|
||||
fun `getArchivedAccounts should emit empty list when no archived accounts`() = runTest {
|
||||
// Arrange
|
||||
archivedAccountsInnerStore.store(value = null)
|
||||
|
||||
val archivedAccountsFlow = repository.getArchivedAccounts(userWalletId)
|
||||
|
||||
// Act
|
||||
val actual = getEmittedValues(archivedAccountsFlow)
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isEmpty()
|
||||
|
||||
coVerifyOrder {
|
||||
archivedAccountsStoreFactory.create(userWalletId)
|
||||
archivedAccountsStore.get()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getArchivedAccounts should emit list of archived accounts when present`() = runTest {
|
||||
// Arrange
|
||||
val archivedAccount1 = mockk<ArchivedAccount>()
|
||||
val archivedAccount2 = mockk<ArchivedAccount>()
|
||||
val archivedAccounts = listOf(archivedAccount1, archivedAccount2)
|
||||
|
||||
archivedAccountsInnerStore.store(value = archivedAccounts)
|
||||
archivedAccountsStore.setTimestamp(time = System.currentTimeMillis() + 3.minutes.inWholeMicroseconds)
|
||||
|
||||
val archivedAccountsFlow = repository.getArchivedAccounts(userWalletId)
|
||||
|
||||
// Act
|
||||
val actual = getEmittedValues(archivedAccountsFlow)
|
||||
|
||||
// Assert
|
||||
val expected = listOf(archivedAccounts)
|
||||
Truth.assertThat(actual).containsExactlyElementsIn(expected)
|
||||
coVerifyOrder {
|
||||
archivedAccountsStoreFactory.create(userWalletId)
|
||||
archivedAccountsStore.get()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getArchivedAccounts should throw exception when store throws exception`() = runTest {
|
||||
// Arrange
|
||||
val exception = Exception("Test error")
|
||||
coEvery { archivedAccountsStoreFactory.create(userWalletId) } throws exception
|
||||
|
||||
// Act
|
||||
val actual = runCatching { repository.getArchivedAccounts(userWalletId) }.exceptionOrNull()!!
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isSameInstanceAs(exception)
|
||||
Truth.assertThat(actual).hasMessageThat().isEqualTo(exception.message)
|
||||
|
||||
coVerifyOrder { archivedAccountsStoreFactory.create(userWalletId) }
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
inner class FetchArchivedAccounts {
|
||||
|
||||
private val accountId = AccountId.forCryptoPortfolio(userWalletId, DerivationIndex.Main)
|
||||
|
||||
@Test
|
||||
fun `fetchArchivedAccounts should store archived accounts in store`() = runTest {
|
||||
// Arrange
|
||||
val accountDTO = WalletAccountDTO(
|
||||
id = accountId.value,
|
||||
name = "Archived Account",
|
||||
derivationIndex = 0,
|
||||
icon = CryptoPortfolioIcon.Icon.Wallet.name,
|
||||
iconColor = CryptoPortfolioIcon.Color.DullLavender.name,
|
||||
totalNetworks = 0,
|
||||
totalTokens = 0,
|
||||
)
|
||||
|
||||
val apiResponse = mockk<GetWalletArchivedAccountsResponse> {
|
||||
every { this@mockk.accounts } returns listOf(accountDTO)
|
||||
}
|
||||
|
||||
val archivedAccount = ArchivedAccountConverter(userWalletId).convert(accountDTO)
|
||||
|
||||
coEvery {
|
||||
tangemTechApi.getWalletArchivedAccounts(userWalletId.stringValue)
|
||||
} returns ApiResponse.Success(apiResponse)
|
||||
|
||||
// Act
|
||||
repository.fetchArchivedAccounts(userWalletId)
|
||||
val actual = archivedAccountsStore.getSyncOrNull()
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).containsExactly(archivedAccount)
|
||||
|
||||
coVerifyOrder {
|
||||
tangemTechApi.getWalletArchivedAccounts(userWalletId.stringValue)
|
||||
archivedAccountsStoreFactory.create(userWalletId)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fetchArchivedAccounts should throw exception if API returns error`() = runTest { // Arrange
|
||||
val exception = Exception("API error")
|
||||
coEvery { tangemTechApi.getWalletArchivedAccounts(userWalletId.stringValue) } throws exception
|
||||
|
||||
// Act
|
||||
val actual = runCatching { repository.fetchArchivedAccounts(userWalletId) }.exceptionOrNull()!!
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isSameInstanceAs(exception)
|
||||
Truth.assertThat(actual).hasMessageThat().isEqualTo(exception.message)
|
||||
Truth.assertThat(archivedAccountsStore.getSyncOrNull()).isNull()
|
||||
|
||||
coVerify { tangemTechApi.getWalletArchivedAccounts(userWalletId.stringValue) }
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
inner class SaveAccounts {
|
||||
|
||||
private val version = 1
|
||||
|
||||
@Test
|
||||
fun `saveAccounts should call API and update store`() = runTest {
|
||||
// Arrange
|
||||
val userWallet = mockk<UserWallet> {
|
||||
every { this@mockk.walletId } returns userWalletId
|
||||
}
|
||||
|
||||
val accountList = AccountList.empty(userWallet = userWallet)
|
||||
|
||||
val accountsResponse = mockk<GetWalletAccountsResponse> {
|
||||
every { this@mockk.wallet.version } returns version
|
||||
}
|
||||
|
||||
accountsResponseStoreFlow.value = accountsResponse
|
||||
|
||||
val body = SaveWalletAccountsResponseConverter.convert(value = accountList)
|
||||
|
||||
val apiResponse = ApiResponse.Success(Unit)
|
||||
|
||||
coEvery {
|
||||
tangemTechApi.saveWalletAccounts(
|
||||
walletId = userWalletId.stringValue,
|
||||
ifMatch = version.toString(),
|
||||
body = body,
|
||||
)
|
||||
} returns apiResponse
|
||||
|
||||
val converter = mockk<GetWalletAccountsResponseConverter> {
|
||||
every { this@mockk.convert(accountList) } returns accountsResponse
|
||||
}
|
||||
|
||||
every {
|
||||
convertersContainer.getWalletAccountsResponseCF.create(userWallet = userWallet, version = version)
|
||||
} returns converter
|
||||
|
||||
coEvery { accountsResponseStore.updateData(transform = any()) } returns accountsResponse
|
||||
|
||||
// Act
|
||||
repository.saveAccounts(accountList)
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(accountsResponseStoreFlow.value).isEqualTo(accountsResponse)
|
||||
|
||||
coVerifyOrder {
|
||||
accountsResponseStoreFactory.create(userWalletId)
|
||||
accountsResponseStore.data
|
||||
tangemTechApi.saveWalletAccounts(userWalletId.stringValue, version.toString(), body)
|
||||
convertersContainer.getWalletAccountsResponseCF.create(userWallet, version)
|
||||
converter.convert(accountList)
|
||||
accountsResponseStore.updateData(any())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `saveAccounts if API request is failed`() = runTest {
|
||||
// Arrange
|
||||
val userWallet = mockk<UserWallet> {
|
||||
every { this@mockk.walletId } returns userWalletId
|
||||
}
|
||||
|
||||
val accountList = AccountList.empty(userWallet = userWallet)
|
||||
|
||||
val accountsResponse = mockk<GetWalletAccountsResponse> {
|
||||
every { this@mockk.wallet.version } returns version
|
||||
}
|
||||
|
||||
accountsResponseStoreFlow.value = accountsResponse
|
||||
|
||||
val body = SaveWalletAccountsResponseConverter.convert(value = accountList)
|
||||
|
||||
val apiResponse = ApiResponse.Error(cause = ApiResponseError.NetworkException) as ApiResponse<Unit>
|
||||
|
||||
coEvery {
|
||||
tangemTechApi.saveWalletAccounts(
|
||||
walletId = userWalletId.stringValue,
|
||||
ifMatch = version.toString(),
|
||||
body = body,
|
||||
)
|
||||
} returns apiResponse
|
||||
|
||||
// Act
|
||||
val actual = runCatching { repository.saveAccounts(accountList) }.exceptionOrNull()!!
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isEqualTo(ApiResponseError.NetworkException)
|
||||
|
||||
coVerifyOrder {
|
||||
accountsResponseStoreFactory.create(userWalletId)
|
||||
accountsResponseStore.data
|
||||
tangemTechApi.saveWalletAccounts(userWalletId.stringValue, version.toString(), body)
|
||||
}
|
||||
|
||||
coVerify(inverse = true) {
|
||||
convertersContainer.getWalletAccountsResponseCF.create(any(), any())
|
||||
accountsResponseStore.updateData(any())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ import org.junit.jupiter.api.TestInstance
|
|||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class ArchivedAccountsStoreFactoryTest {
|
||||
|
||||
private val factory = ArchivedAccountsStoreFactory()
|
||||
private val factory = ArchivedAccountsStoreFactory
|
||||
|
||||
@AfterEach
|
||||
fun tearDownEach() {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ interface AccountsCRUDRepository {
|
|||
* @param userWalletId the unique identifier of the user wallet
|
||||
* @return an [Option] containing the [AccountList] if found, or `Option.None` if not
|
||||
*/
|
||||
suspend fun getAccounts(userWalletId: UserWalletId): Option<AccountList>
|
||||
suspend fun getAccountListSync(userWalletId: UserWalletId): Option<AccountList>
|
||||
|
||||
/**
|
||||
* Retrieves a specific account by its unique identifier
|
||||
|
|
@ -30,14 +30,14 @@ interface AccountsCRUDRepository {
|
|||
* @param accountId the unique identifier of the account
|
||||
* @return an [Option] containing the [Account.CryptoPortfolio] if found, or `Option.None` if not
|
||||
*/
|
||||
suspend fun getAccount(accountId: AccountId): Option<Account.CryptoPortfolio>
|
||||
suspend fun getAccountSync(accountId: AccountId): Option<Account.CryptoPortfolio>
|
||||
|
||||
/**
|
||||
* Retrieves a archived account by its unique identifier
|
||||
*
|
||||
* @param accountId the unique identifier of the account
|
||||
*/
|
||||
suspend fun getArchivedAccount(accountId: AccountId): Option<ArchivedAccount>
|
||||
suspend fun getArchivedAccountSync(accountId: AccountId): Option<ArchivedAccount>
|
||||
|
||||
/**
|
||||
* Retrieves a list of archived accounts associated with a specific user wallet
|
||||
|
|
@ -45,7 +45,7 @@ interface AccountsCRUDRepository {
|
|||
* @param userWalletId the unique identifier of the user wallet
|
||||
* @return an [Option] containing a list of [ArchivedAccount] if found, or `Option.None` if not
|
||||
*/
|
||||
suspend fun getArchivedAccountsSync(userWalletId: UserWalletId): Option<List<ArchivedAccount>>
|
||||
suspend fun getArchivedAccountListSync(userWalletId: UserWalletId): Option<List<ArchivedAccount>>
|
||||
|
||||
/**
|
||||
* Provides a flow of archived accounts associated with a specific user wallet
|
||||
|
|
@ -73,7 +73,7 @@ interface AccountsCRUDRepository {
|
|||
*
|
||||
* @param userWalletId the unique identifier of the user wallet
|
||||
*/
|
||||
suspend fun getTotalAccountsCount(userWalletId: UserWalletId): Int
|
||||
suspend fun getTotalAccountsCount(userWalletId: UserWalletId): Option<Int>
|
||||
|
||||
/**
|
||||
* Retrieves a user wallet by its unique identifier
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ class AddCryptoPortfolioUseCase(
|
|||
newAccount
|
||||
}
|
||||
|
||||
private fun Raise<Error>.createAccount(
|
||||
private fun createAccount(
|
||||
userWalletId: UserWalletId,
|
||||
accountName: AccountName,
|
||||
icon: CryptoPortfolioIcon,
|
||||
|
|
@ -72,7 +72,7 @@ class AddCryptoPortfolioUseCase(
|
|||
|
||||
private suspend fun Raise<Error>.getAccountList(userWalletId: UserWalletId): Option<AccountList> {
|
||||
return catch(
|
||||
block = { crudRepository.getAccounts(userWalletId = userWalletId) },
|
||||
block = { crudRepository.getAccountListSync(userWalletId = userWalletId) },
|
||||
catch = { raise(Error.DataOperationFailed(cause = it)) },
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class ArchiveCryptoPortfolioUseCase(
|
|||
|
||||
private suspend fun Raise<Error>.getAccountList(userWalletId: UserWalletId): AccountList {
|
||||
return catch(
|
||||
block = { crudRepository.getAccounts(userWalletId = userWalletId) },
|
||||
block = { crudRepository.getAccountListSync(userWalletId = userWalletId) },
|
||||
catch = { raise(Error.DataOperationFailed(cause = it)) },
|
||||
)
|
||||
.getOrElse { raise(Error.CriticalTechError.AccountsNotCreated(userWalletId = userWalletId)) }
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class GetArchivedAccountsUseCase(
|
|||
|
||||
private suspend fun getArchivedAccounts(userWalletId: UserWalletId): Either<Throwable, ArchivedAccountList> {
|
||||
return Either.catch {
|
||||
crudRepository.getArchivedAccountsSync(userWalletId = userWalletId).getOrElse {
|
||||
crudRepository.getArchivedAccountListSync(userWalletId = userWalletId).getOrElse {
|
||||
error("Archived accounts not found for user wallet: $userWalletId")
|
||||
}
|
||||
}
|
||||
|
|
@ -70,7 +70,11 @@ class GetArchivedAccountsUseCase(
|
|||
private suspend fun ProducerScope<Lce<Throwable, ArchivedAccountList>>.subscribeOnArchivedAccounts(
|
||||
userWalletId: UserWalletId,
|
||||
) {
|
||||
crudRepository.getArchivedAccounts(userWalletId)
|
||||
runCatching { crudRepository.getArchivedAccounts(userWalletId) }
|
||||
.getOrElse {
|
||||
send(it.lceError())
|
||||
return
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.retryWhen { cause, _ ->
|
||||
send(cause.lceError())
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ class GetUnoccupiedAccountIndexUseCase(
|
|||
block = { crudRepository.getTotalAccountsCount(userWalletId = userWalletId) },
|
||||
catch = { raise(Error.DataOperationFailed(cause = it)) },
|
||||
)
|
||||
.getOrElse { raise(Error.DataNotFound) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -48,6 +49,10 @@ class GetUnoccupiedAccountIndexUseCase(
|
|||
val tag: String
|
||||
get() = this::class.simpleName ?: "GetUnoccupiedAccountIndexUseCase.Error"
|
||||
|
||||
data object DataNotFound : Error {
|
||||
override fun toString(): String = "$tag: Data not found"
|
||||
}
|
||||
|
||||
/** Error indicating that the derivation index is invalid */
|
||||
data class InvalidDerivationIndex(val cause: DerivationIndex.Error) : Error {
|
||||
override fun toString(): String = "$tag: Invalid derivation index: $cause"
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class RecoverCryptoPortfolioUseCase(
|
|||
|
||||
private suspend fun Raise<Error>.getAccountList(userWalletId: UserWalletId): AccountList {
|
||||
return catch(
|
||||
block = { crudRepository.getAccounts(userWalletId = userWalletId) },
|
||||
block = { crudRepository.getAccountListSync(userWalletId = userWalletId) },
|
||||
catch = { raise(Error.DataOperationFailed(cause = it)) },
|
||||
)
|
||||
.getOrElse { raise(Error.CriticalTechError.AccountsNotCreated(userWalletId = userWalletId)) }
|
||||
|
|
@ -52,7 +52,7 @@ class RecoverCryptoPortfolioUseCase(
|
|||
|
||||
private suspend fun Raise<Error>.getArchivedAccount(accountId: AccountId): ArchivedAccount {
|
||||
return catch(
|
||||
block = { crudRepository.getArchivedAccount(accountId = accountId) },
|
||||
block = { crudRepository.getArchivedAccountSync(accountId = accountId) },
|
||||
catch = { raise(Error.DataOperationFailed(cause = it)) },
|
||||
)
|
||||
.getOrElse {
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ class UpdateCryptoPortfolioUseCase(
|
|||
|
||||
private suspend fun Raise<Error>.getAccountList(userWalletId: UserWalletId): AccountList {
|
||||
return catch(
|
||||
block = { crudRepository.getAccounts(userWalletId = userWalletId) },
|
||||
block = { crudRepository.getAccountListSync(userWalletId = userWalletId) },
|
||||
catch = { raise(Error.DataOperationFailed(cause = it)) },
|
||||
)
|
||||
.getOrElse { raise(Error.CriticalTechError.AccountsNotCreated(userWalletId = userWalletId)) }
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class AddCryptoPortfolioUseCaseTest {
|
|||
val accountList = AccountList.empty(userWallet)
|
||||
val updatedAccountList = (accountList + newAccount).getOrNull()!!
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId) } returns accountList.toOption()
|
||||
|
||||
// Act
|
||||
val actual = useCase(
|
||||
|
|
@ -56,7 +56,7 @@ class AddCryptoPortfolioUseCaseTest {
|
|||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder {
|
||||
crudRepository.getAccounts(userWalletId)
|
||||
crudRepository.getAccountListSync(userWalletId)
|
||||
crudRepository.saveAccounts(updatedAccountList)
|
||||
}
|
||||
|
||||
|
|
@ -69,7 +69,7 @@ class AddCryptoPortfolioUseCaseTest {
|
|||
val newAccount = createNewAccount()
|
||||
val newAccountList = (AccountList.empty(userWallet) + newAccount).getOrNull()!!
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId) } returns None
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId) } returns None
|
||||
coEvery { crudRepository.getUserWallet(userWalletId) } returns userWallet
|
||||
|
||||
// Act
|
||||
|
|
@ -85,7 +85,7 @@ class AddCryptoPortfolioUseCaseTest {
|
|||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder {
|
||||
crudRepository.getAccounts(userWalletId)
|
||||
crudRepository.getAccountListSync(userWalletId)
|
||||
crudRepository.getUserWallet(userWalletId)
|
||||
crudRepository.saveAccounts(newAccountList)
|
||||
}
|
||||
|
|
@ -102,7 +102,7 @@ class AddCryptoPortfolioUseCaseTest {
|
|||
|
||||
val newAccount = createNewAccount(derivationIndex = 21)
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId) } returns accountList.toOption()
|
||||
|
||||
// Act
|
||||
val actual = useCase(
|
||||
|
|
@ -119,7 +119,7 @@ class AddCryptoPortfolioUseCaseTest {
|
|||
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder { crudRepository.getAccounts(userWalletId) }
|
||||
coVerifyOrder { crudRepository.getAccountListSync(userWalletId) }
|
||||
|
||||
coVerify(inverse = true) {
|
||||
crudRepository.getUserWallet(any())
|
||||
|
|
@ -133,7 +133,7 @@ class AddCryptoPortfolioUseCaseTest {
|
|||
val newAccount = createNewAccount()
|
||||
val exception = IllegalStateException("Test error")
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId) } throws exception
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId) } throws exception
|
||||
|
||||
// Act
|
||||
val actual = useCase(
|
||||
|
|
@ -147,7 +147,7 @@ class AddCryptoPortfolioUseCaseTest {
|
|||
val expected = AddCryptoPortfolioUseCase.Error.DataOperationFailed(cause = exception).left()
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder { crudRepository.getAccounts(userWalletId) }
|
||||
coVerifyOrder { crudRepository.getAccountListSync(userWalletId) }
|
||||
|
||||
coVerify(inverse = true) {
|
||||
crudRepository.getUserWallet(any())
|
||||
|
|
@ -164,7 +164,7 @@ class AddCryptoPortfolioUseCaseTest {
|
|||
|
||||
val exception = IllegalStateException("Test error")
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.saveAccounts(updatedAccountList) } throws exception
|
||||
|
||||
// Act
|
||||
|
|
@ -180,7 +180,7 @@ class AddCryptoPortfolioUseCaseTest {
|
|||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder {
|
||||
crudRepository.getAccounts(userWalletId)
|
||||
crudRepository.getAccountListSync(userWalletId)
|
||||
crudRepository.saveAccounts(updatedAccountList)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class ArchiveCryptoPortfolioUseCaseTest {
|
|||
|
||||
val updatedAccountList = (accountList - account).getOrNull()!!
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId) } returns accountList.toOption()
|
||||
|
||||
// Act
|
||||
val actual = useCase(accountId)
|
||||
|
|
@ -51,7 +51,7 @@ class ArchiveCryptoPortfolioUseCaseTest {
|
|||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder {
|
||||
crudRepository.getAccounts(userWalletId)
|
||||
crudRepository.getAccountListSync(userWalletId)
|
||||
crudRepository.saveAccounts(updatedAccountList)
|
||||
}
|
||||
}
|
||||
|
|
@ -64,7 +64,7 @@ class ArchiveCryptoPortfolioUseCaseTest {
|
|||
derivationIndex = DerivationIndex.Main,
|
||||
)
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId) } returns None
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId) } returns None
|
||||
|
||||
// Act
|
||||
val actual = useCase(accountId)
|
||||
|
|
@ -73,7 +73,7 @@ class ArchiveCryptoPortfolioUseCaseTest {
|
|||
val expected = Error.CriticalTechError.AccountsNotCreated(userWalletId).left()
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder { crudRepository.getAccounts(userWalletId) }
|
||||
coVerifyOrder { crudRepository.getAccountListSync(userWalletId) }
|
||||
coVerify(inverse = true) { crudRepository.saveAccounts(any()) }
|
||||
}
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ class ArchiveCryptoPortfolioUseCaseTest {
|
|||
|
||||
val exception = IllegalStateException("Test error")
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId) } throws exception
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId) } throws exception
|
||||
|
||||
// Act
|
||||
val actual = useCase(accountId)
|
||||
|
|
@ -96,7 +96,7 @@ class ArchiveCryptoPortfolioUseCaseTest {
|
|||
val expected = Error.DataOperationFailed(exception).left()
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder { crudRepository.getAccounts(userWalletId) }
|
||||
coVerifyOrder { crudRepository.getAccountListSync(userWalletId) }
|
||||
coVerify(inverse = true) { crudRepository.saveAccounts(any()) }
|
||||
}
|
||||
|
||||
|
|
@ -109,7 +109,7 @@ class ArchiveCryptoPortfolioUseCaseTest {
|
|||
derivationIndex = DerivationIndex(1).getOrNull()!!,
|
||||
)
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId) } returns accountList.toOption()
|
||||
|
||||
// Act
|
||||
val actual = useCase(accountId)
|
||||
|
|
@ -118,7 +118,7 @@ class ArchiveCryptoPortfolioUseCaseTest {
|
|||
val expected = Error.CriticalTechError.AccountNotFound(accountId).left()
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder { crudRepository.getAccounts(userWalletId) }
|
||||
coVerifyOrder { crudRepository.getAccountListSync(userWalletId) }
|
||||
coVerify(inverse = true) { crudRepository.saveAccounts(any()) }
|
||||
}
|
||||
|
||||
|
|
@ -133,7 +133,7 @@ class ArchiveCryptoPortfolioUseCaseTest {
|
|||
|
||||
val exception = IllegalStateException("Save failed")
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.saveAccounts(updatedAccountList) } throws exception
|
||||
|
||||
// Act
|
||||
|
|
@ -144,7 +144,7 @@ class ArchiveCryptoPortfolioUseCaseTest {
|
|||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder {
|
||||
crudRepository.getAccounts(userWalletId)
|
||||
crudRepository.getAccountListSync(userWalletId)
|
||||
crudRepository.saveAccounts(updatedAccountList)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class GetArchivedAccountsUseCaseTest {
|
|||
mockk<ArchivedAccount>(),
|
||||
mockk<ArchivedAccount>(),
|
||||
)
|
||||
coEvery { crudRepository.getArchivedAccountsSync(userWalletId) } returns archivedAccounts.toOption()
|
||||
coEvery { crudRepository.getArchivedAccountListSync(userWalletId) } returns archivedAccounts.toOption()
|
||||
every { crudRepository.getArchivedAccounts(userWalletId) } returns flowOf(archivedAccounts)
|
||||
|
||||
// Act
|
||||
|
|
@ -54,7 +54,7 @@ class GetArchivedAccountsUseCaseTest {
|
|||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder {
|
||||
crudRepository.getArchivedAccountsSync(userWalletId)
|
||||
crudRepository.getArchivedAccountListSync(userWalletId)
|
||||
crudRepository.getArchivedAccounts(userWalletId)
|
||||
}
|
||||
|
||||
|
|
@ -69,7 +69,7 @@ class GetArchivedAccountsUseCaseTest {
|
|||
mockk<ArchivedAccount>(),
|
||||
)
|
||||
|
||||
coEvery { crudRepository.getArchivedAccountsSync(userWalletId) } returns None
|
||||
coEvery { crudRepository.getArchivedAccountListSync(userWalletId) } returns None
|
||||
every { crudRepository.getArchivedAccounts(userWalletId) } returns flowOf(archivedAccounts)
|
||||
|
||||
// Act
|
||||
|
|
@ -83,7 +83,7 @@ class GetArchivedAccountsUseCaseTest {
|
|||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerify(exactly = 1) {
|
||||
crudRepository.getArchivedAccountsSync(userWalletId)
|
||||
crudRepository.getArchivedAccountListSync(userWalletId)
|
||||
crudRepository.fetchArchivedAccounts(userWalletId)
|
||||
crudRepository.getArchivedAccounts(userWalletId)
|
||||
}
|
||||
|
|
@ -98,7 +98,7 @@ class GetArchivedAccountsUseCaseTest {
|
|||
mockk<ArchivedAccount>(),
|
||||
)
|
||||
|
||||
coEvery { crudRepository.getArchivedAccountsSync(userWalletId) } throws exception
|
||||
coEvery { crudRepository.getArchivedAccountListSync(userWalletId) } throws exception
|
||||
every { crudRepository.getArchivedAccounts(userWalletId) } returns flowOf(archivedAccounts)
|
||||
|
||||
// Act
|
||||
|
|
@ -112,7 +112,7 @@ class GetArchivedAccountsUseCaseTest {
|
|||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerify(exactly = 1) {
|
||||
crudRepository.getArchivedAccountsSync(userWalletId)
|
||||
crudRepository.getArchivedAccountListSync(userWalletId)
|
||||
crudRepository.fetchArchivedAccounts(userWalletId)
|
||||
crudRepository.getArchivedAccounts(userWalletId)
|
||||
}
|
||||
|
|
@ -123,7 +123,7 @@ class GetArchivedAccountsUseCaseTest {
|
|||
// Arrange
|
||||
val exception = IllegalStateException("Fetch error")
|
||||
|
||||
coEvery { crudRepository.getArchivedAccountsSync(userWalletId) } returns None
|
||||
coEvery { crudRepository.getArchivedAccountListSync(userWalletId) } returns None
|
||||
every { crudRepository.getArchivedAccounts(userWalletId) } returns emptyFlow()
|
||||
coEvery { crudRepository.fetchArchivedAccounts(userWalletId) } throws exception
|
||||
|
||||
|
|
@ -139,7 +139,7 @@ class GetArchivedAccountsUseCaseTest {
|
|||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerify(exactly = 1) {
|
||||
crudRepository.getArchivedAccountsSync(userWalletId)
|
||||
crudRepository.getArchivedAccountListSync(userWalletId)
|
||||
crudRepository.fetchArchivedAccounts(userWalletId)
|
||||
crudRepository.getArchivedAccounts(userWalletId)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.domain.account.usecase
|
||||
|
||||
import arrow.core.left
|
||||
import arrow.core.toOption
|
||||
import com.google.common.truth.Truth
|
||||
import com.tangem.domain.account.repository.AccountsCRUDRepository
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
|
|
@ -29,7 +30,7 @@ class GetUnoccupiedAccountIndexUseCaseTest {
|
|||
@Test
|
||||
fun `invoke should return next unoccupied index when repository returns count`() = runTest {
|
||||
// Arrange
|
||||
coEvery { crudRepository.getTotalAccountsCount(userWalletId) } returns 3
|
||||
coEvery { crudRepository.getTotalAccountsCount(userWalletId) } returns 3.toOption()
|
||||
|
||||
// Act
|
||||
val actual = useCase(userWalletId = userWalletId)
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ class RecoverCryptoPortfolioUseCaseTest {
|
|||
|
||||
val updatedAccountList = (accountList + account).getOrNull()!!
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.getArchivedAccount(account.accountId) } returns archivedAccount.toOption()
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.getArchivedAccountSync(account.accountId) } returns archivedAccount.toOption()
|
||||
|
||||
// Act
|
||||
val actual = useCase(account.accountId)
|
||||
|
|
@ -63,8 +63,8 @@ class RecoverCryptoPortfolioUseCaseTest {
|
|||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder {
|
||||
crudRepository.getAccounts(userWalletId)
|
||||
crudRepository.getArchivedAccount(account.accountId)
|
||||
crudRepository.getAccountListSync(userWalletId)
|
||||
crudRepository.getArchivedAccountSync(account.accountId)
|
||||
crudRepository.saveAccounts(updatedAccountList)
|
||||
}
|
||||
}
|
||||
|
|
@ -77,7 +77,7 @@ class RecoverCryptoPortfolioUseCaseTest {
|
|||
derivationIndex = DerivationIndex.Main,
|
||||
)
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId) } returns None
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId) } returns None
|
||||
|
||||
// Act
|
||||
val actual = useCase(accountId)
|
||||
|
|
@ -86,9 +86,9 @@ class RecoverCryptoPortfolioUseCaseTest {
|
|||
val expected = Error.CriticalTechError.AccountsNotCreated(userWalletId).left()
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder { crudRepository.getAccounts(userWalletId) }
|
||||
coVerifyOrder { crudRepository.getAccountListSync(userWalletId) }
|
||||
coVerify(inverse = true) {
|
||||
crudRepository.getArchivedAccount(any())
|
||||
crudRepository.getArchivedAccountSync(any())
|
||||
crudRepository.saveAccounts(any())
|
||||
}
|
||||
}
|
||||
|
|
@ -102,7 +102,7 @@ class RecoverCryptoPortfolioUseCaseTest {
|
|||
)
|
||||
val exception = IllegalStateException("Test error")
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId) } throws exception
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId) } throws exception
|
||||
|
||||
// Act
|
||||
val actual = useCase(accountId)
|
||||
|
|
@ -111,9 +111,9 @@ class RecoverCryptoPortfolioUseCaseTest {
|
|||
val expected = Error.DataOperationFailed(exception).left()
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder { crudRepository.getAccounts(userWalletId) }
|
||||
coVerifyOrder { crudRepository.getAccountListSync(userWalletId) }
|
||||
coVerify(inverse = true) {
|
||||
crudRepository.getArchivedAccount(any())
|
||||
crudRepository.getArchivedAccountSync(any())
|
||||
crudRepository.saveAccounts(any())
|
||||
}
|
||||
}
|
||||
|
|
@ -125,8 +125,8 @@ class RecoverCryptoPortfolioUseCaseTest {
|
|||
val accountList = AccountList.empty(userWallet)
|
||||
val exception = IllegalStateException("Test error")
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.getArchivedAccount(account.accountId) } throws exception
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.getArchivedAccountSync(account.accountId) } throws exception
|
||||
|
||||
// Act
|
||||
val actual = useCase(account.accountId)
|
||||
|
|
@ -136,8 +136,8 @@ class RecoverCryptoPortfolioUseCaseTest {
|
|||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder {
|
||||
crudRepository.getAccounts(userWalletId)
|
||||
crudRepository.getArchivedAccount(account.accountId)
|
||||
crudRepository.getAccountListSync(userWalletId)
|
||||
crudRepository.getArchivedAccountSync(account.accountId)
|
||||
}
|
||||
coVerify(inverse = true) { crudRepository.saveAccounts(any()) }
|
||||
}
|
||||
|
|
@ -148,8 +148,8 @@ class RecoverCryptoPortfolioUseCaseTest {
|
|||
val account = createAccount(userWalletId)
|
||||
val accountList = AccountList.empty(userWallet)
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.getArchivedAccount(account.accountId) } returns None
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.getArchivedAccountSync(account.accountId) } returns None
|
||||
|
||||
// Act
|
||||
val actual = useCase(account.accountId)
|
||||
|
|
@ -159,8 +159,8 @@ class RecoverCryptoPortfolioUseCaseTest {
|
|||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder {
|
||||
crudRepository.getAccounts(userWalletId)
|
||||
crudRepository.getArchivedAccount(account.accountId)
|
||||
crudRepository.getAccountListSync(userWalletId)
|
||||
crudRepository.getArchivedAccountSync(account.accountId)
|
||||
}
|
||||
coVerify(inverse = true) { crudRepository.saveAccounts(any()) }
|
||||
}
|
||||
|
|
@ -182,8 +182,8 @@ class RecoverCryptoPortfolioUseCaseTest {
|
|||
val updatedAccountList = (accountList + account).getOrNull()!!
|
||||
val exception = IllegalStateException("Save failed")
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.getArchivedAccount(account.accountId) } returns archivedAccount.toOption()
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.getArchivedAccountSync(account.accountId) } returns archivedAccount.toOption()
|
||||
coEvery { crudRepository.saveAccounts(updatedAccountList) } throws exception
|
||||
|
||||
// Act
|
||||
|
|
@ -194,8 +194,8 @@ class RecoverCryptoPortfolioUseCaseTest {
|
|||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder {
|
||||
crudRepository.getAccounts(userWalletId)
|
||||
crudRepository.getArchivedAccount(account.accountId)
|
||||
crudRepository.getAccountListSync(userWalletId)
|
||||
crudRepository.getArchivedAccountSync(account.accountId)
|
||||
crudRepository.saveAccounts(updatedAccountList)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ class UpdateCryptoPortfolioUseCaseTest {
|
|||
val updatedAccount = accountList.mainAccount.copy(accountName = newAccountName)
|
||||
val updatedAccountList = (accountList + updatedAccount).getOrNull()!!
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId = userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId = userWalletId) } returns accountList.toOption()
|
||||
|
||||
// Act
|
||||
val actual = useCase(accountId = accountId, accountName = newAccountName)
|
||||
|
|
@ -58,7 +58,7 @@ class UpdateCryptoPortfolioUseCaseTest {
|
|||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder {
|
||||
crudRepository.getAccounts(userWalletId = userWalletId)
|
||||
crudRepository.getAccountListSync(userWalletId = userWalletId)
|
||||
crudRepository.saveAccounts(accountList = updatedAccountList)
|
||||
}
|
||||
}
|
||||
|
|
@ -76,7 +76,7 @@ class UpdateCryptoPortfolioUseCaseTest {
|
|||
val updatedAccount = accountList.mainAccount.copy(icon = newAccountIcon)
|
||||
val updatedAccountList = (accountList + updatedAccount).getOrNull()!!
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId = userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId = userWalletId) } returns accountList.toOption()
|
||||
|
||||
// Act
|
||||
val actual = useCase(accountId = accountId, icon = newAccountIcon)
|
||||
|
|
@ -86,7 +86,7 @@ class UpdateCryptoPortfolioUseCaseTest {
|
|||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder {
|
||||
crudRepository.getAccounts(userWalletId = userWalletId)
|
||||
crudRepository.getAccountListSync(userWalletId = userWalletId)
|
||||
crudRepository.saveAccounts(accountList = updatedAccountList)
|
||||
}
|
||||
}
|
||||
|
|
@ -105,7 +105,7 @@ class UpdateCryptoPortfolioUseCaseTest {
|
|||
val updatedAccount = accountList.mainAccount.copy(accountName = newAccountName, icon = newAccountIcon)
|
||||
val updatedAccountList = (accountList + updatedAccount).getOrNull()!!
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId = userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId = userWalletId) } returns accountList.toOption()
|
||||
|
||||
// Act
|
||||
val actual = useCase(accountId = accountId, accountName = newAccountName, icon = newAccountIcon)
|
||||
|
|
@ -115,7 +115,7 @@ class UpdateCryptoPortfolioUseCaseTest {
|
|||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder {
|
||||
crudRepository.getAccounts(userWalletId = userWalletId)
|
||||
crudRepository.getAccountListSync(userWalletId = userWalletId)
|
||||
crudRepository.saveAccounts(accountList = updatedAccountList)
|
||||
}
|
||||
}
|
||||
|
|
@ -126,7 +126,7 @@ class UpdateCryptoPortfolioUseCaseTest {
|
|||
val accountList = AccountList.empty(userWallet = userWallet)
|
||||
val accountId = accountList.mainAccount.accountId
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId = userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId = userWalletId) } returns accountList.toOption()
|
||||
|
||||
// Act
|
||||
val actual = useCase(accountId = accountId)
|
||||
|
|
@ -136,7 +136,7 @@ class UpdateCryptoPortfolioUseCaseTest {
|
|||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerify(inverse = true) {
|
||||
crudRepository.getAccounts(userWalletId = any())
|
||||
crudRepository.getAccountListSync(userWalletId = any())
|
||||
crudRepository.saveAccounts(accountList = any())
|
||||
}
|
||||
}
|
||||
|
|
@ -151,7 +151,7 @@ class UpdateCryptoPortfolioUseCaseTest {
|
|||
|
||||
val exception = IllegalStateException("Test exception")
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId = userWalletId) } throws exception
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId = userWalletId) } throws exception
|
||||
|
||||
// Act
|
||||
val actual = useCase(accountId = accountId, accountName = newAccountName)
|
||||
|
|
@ -160,7 +160,7 @@ class UpdateCryptoPortfolioUseCaseTest {
|
|||
val expected = Error.DataOperationFailed(cause = exception).left()
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder { crudRepository.getAccounts(userWalletId = userWalletId) }
|
||||
coVerifyOrder { crudRepository.getAccountListSync(userWalletId = userWalletId) }
|
||||
coVerify(inverse = true) { crudRepository.saveAccounts(accountList = any()) }
|
||||
}
|
||||
|
||||
|
|
@ -175,7 +175,7 @@ class UpdateCryptoPortfolioUseCaseTest {
|
|||
|
||||
val newAccountName = AccountName("New name").getOrNull()!!
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId = userWalletId) } returns accountList
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId = userWalletId) } returns accountList
|
||||
|
||||
// Act
|
||||
val actual = useCase(accountId = accountId, accountName = newAccountName)
|
||||
|
|
@ -184,7 +184,7 @@ class UpdateCryptoPortfolioUseCaseTest {
|
|||
val expected = Error.CriticalTechError.AccountsNotCreated(userWalletId = userWalletId).left()
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder { crudRepository.getAccounts(userWalletId = userWalletId) }
|
||||
coVerifyOrder { crudRepository.getAccountListSync(userWalletId = userWalletId) }
|
||||
coVerify(inverse = true) { crudRepository.saveAccounts(accountList = any()) }
|
||||
}
|
||||
|
||||
|
|
@ -199,7 +199,7 @@ class UpdateCryptoPortfolioUseCaseTest {
|
|||
|
||||
val newAccountName = AccountName("New name").getOrNull()!!
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId = userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId = userWalletId) } returns accountList.toOption()
|
||||
|
||||
// Act
|
||||
val actual = useCase(accountId = accountId, accountName = newAccountName)
|
||||
|
|
@ -208,7 +208,7 @@ class UpdateCryptoPortfolioUseCaseTest {
|
|||
val expected = Error.CriticalTechError.AccountNotFound(accountId = accountId).left()
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder { crudRepository.getAccounts(userWalletId = userWalletId) }
|
||||
coVerifyOrder { crudRepository.getAccountListSync(userWalletId = userWalletId) }
|
||||
coVerify(inverse = true) { crudRepository.saveAccounts(accountList = any()) }
|
||||
}
|
||||
|
||||
|
|
@ -224,7 +224,7 @@ class UpdateCryptoPortfolioUseCaseTest {
|
|||
|
||||
val exception = IllegalStateException("Save failed")
|
||||
|
||||
coEvery { crudRepository.getAccounts(userWalletId = userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.getAccountListSync(userWalletId = userWalletId) } returns accountList.toOption()
|
||||
coEvery { crudRepository.saveAccounts(accountList = updatedAccountList) } throws exception
|
||||
|
||||
// Act
|
||||
|
|
@ -235,7 +235,7 @@ class UpdateCryptoPortfolioUseCaseTest {
|
|||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
|
||||
coVerifyOrder {
|
||||
crudRepository.getAccounts(userWalletId = userWalletId)
|
||||
crudRepository.getAccountListSync(userWalletId = userWalletId)
|
||||
crudRepository.saveAccounts(accountList = updatedAccountList)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue