Updated on 2026-08-14
This commit is contained in:
parent
95ca24f18d
commit
73a6042277
5 changed files with 96 additions and 209 deletions
|
|
@ -1,65 +1,35 @@
|
|||
package com.tangem.domain.account.usecase
|
||||
|
||||
import arrow.core.Option
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.domain.account.repository.AccountsCRUDRepository
|
||||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.common.wallets.loadAndGet
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.isMultiCurrency
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.*
|
||||
import com.tangem.domain.account.models.AccountList
|
||||
import com.tangem.domain.account.supplier.MultiAccountListSupplier
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
/**
|
||||
* Use case to determine if the accounts mode is enabled.
|
||||
* Accounts mode is considered enabled if there are at least two accounts in any of the user wallets that support
|
||||
* multiple currencies.
|
||||
* Accounts mode is considered enabled if any [AccountList] produced for the user's wallets contains at least two
|
||||
* active accounts.
|
||||
*
|
||||
* @property crudRepository repository to perform CRUD operations on accounts.
|
||||
* @property userWalletsListRepository repository to get the list of user wallets.
|
||||
* @property multiAccountListSupplier supplier that provides a list of [AccountList]s for all user wallets
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class IsAccountsModeEnabledUseCase(
|
||||
private val crudRepository: AccountsCRUDRepository,
|
||||
private val userWalletsListRepository: UserWalletsListRepository,
|
||||
private val multiAccountListSupplier: MultiAccountListSupplier,
|
||||
) {
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
operator fun invoke(): Flow<Boolean> {
|
||||
return userWalletsListRepository.loadAndGet()
|
||||
.flatMapLatest { userWallets ->
|
||||
val totalAccountsCountList = getTotalAccountsCountList(userWallets)
|
||||
|
||||
combine(flows = totalAccountsCountList) { it.toList().isModeEnabled() }
|
||||
}
|
||||
.onEmpty { emit(false) }
|
||||
return multiAccountListSupplier.invoke()
|
||||
.map { accountsList -> accountsList.map(AccountList::activeAccounts).isModeEnabled() }
|
||||
.distinctUntilChanged()
|
||||
}
|
||||
|
||||
suspend fun invokeSync(): Boolean {
|
||||
return userWalletsListRepository.userWallets.value.orEmpty()
|
||||
.map { userWallet ->
|
||||
// If the wallet does not support multiple currencies, we consider its account count as 0
|
||||
if (!userWallet.isMultiCurrency) return@map 0
|
||||
|
||||
crudRepository.getTotalActiveAccountsCountSync(userWalletId = userWallet.walletId).getOrZero()
|
||||
}
|
||||
.isModeEnabled()
|
||||
return multiAccountListSupplier.getSyncOrNull(Unit)
|
||||
?.map(AccountList::activeAccounts)
|
||||
?.isModeEnabled() == true
|
||||
}
|
||||
|
||||
private fun getTotalAccountsCountList(userWallets: List<UserWallet>): List<Flow<Int>> {
|
||||
return userWallets
|
||||
.map { userWallet ->
|
||||
// If the wallet does not support multiple currencies, we consider its account count as 0
|
||||
if (!userWallet.isMultiCurrency) return@map flowOf(0)
|
||||
|
||||
crudRepository.getTotalActiveAccountsCount(userWalletId = userWallet.walletId)
|
||||
.map { maybeCount -> maybeCount.getOrZero() }
|
||||
}
|
||||
}
|
||||
|
||||
private fun Option<Int>.getOrZero(): Int = getOrElse { 0 }
|
||||
|
||||
private fun List<Int>.isModeEnabled(): Boolean = any { it >= 2 }
|
||||
}
|
||||
|
|
@ -1,15 +1,12 @@
|
|||
package com.tangem.domain.account.usecase
|
||||
|
||||
import arrow.core.none
|
||||
import arrow.core.some
|
||||
import com.google.common.truth.Truth
|
||||
import com.tangem.domain.account.repository.AccountsCRUDRepository
|
||||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.models.wallet.isMultiCurrency
|
||||
import io.mockk.*
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import com.tangem.domain.account.models.AccountList
|
||||
import com.tangem.domain.account.supplier.MultiAccountListSupplier
|
||||
import io.mockk.clearMocks
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.test.runTest
|
||||
|
|
@ -18,21 +15,16 @@ import org.junit.jupiter.api.Nested
|
|||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
|
||||
@Suppress("UnusedFlow")
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class IsAccountsModeEnabledUseCaseTest {
|
||||
|
||||
private val accountsCRUDRepository: AccountsCRUDRepository = mockk()
|
||||
private val userWalletsListRepository: UserWalletsListRepository = mockk(relaxUnitFun = true)
|
||||
private val multiAccountListSupplier: MultiAccountListSupplier = mockk()
|
||||
|
||||
private val useCase = IsAccountsModeEnabledUseCase(
|
||||
crudRepository = accountsCRUDRepository,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
)
|
||||
private val useCase = IsAccountsModeEnabledUseCase(multiAccountListSupplier = multiAccountListSupplier)
|
||||
|
||||
@AfterEach
|
||||
fun tearDown() {
|
||||
clearMocks(userWalletsListRepository, accountsCRUDRepository)
|
||||
clearMocks(multiAccountListSupplier)
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
|
@ -40,90 +32,55 @@ class IsAccountsModeEnabledUseCaseTest {
|
|||
inner class Invoke {
|
||||
|
||||
@Test
|
||||
fun `returns false when loadAndGet emits one wallet with isMultiCurrency false`() = runTest {
|
||||
fun `returns false when supplier emits empty list`() = runTest {
|
||||
// Arrange
|
||||
val wallet = createUserWallet(isMultiCurrency = false)
|
||||
|
||||
every { userWalletsListRepository.userWallets } returns MutableStateFlow(listOf(wallet))
|
||||
every { multiAccountListSupplier.invoke() } returns flowOf(emptyList())
|
||||
|
||||
// Act
|
||||
val actual = useCase.invoke().first()
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isFalse()
|
||||
|
||||
coVerifyOrder {
|
||||
userWalletsListRepository.load()
|
||||
userWalletsListRepository.userWallets
|
||||
}
|
||||
|
||||
verify(inverse = true) { accountsCRUDRepository.getTotalActiveAccountsCount(any()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns true when loadAndGet emits one wallet with isMultiCurrency true`() = runTest {
|
||||
fun `returns false when supplier emits account list with one account`() = runTest {
|
||||
// Arrange
|
||||
val wallet = createUserWallet(isMultiCurrency = true)
|
||||
|
||||
every { userWalletsListRepository.userWallets } returns MutableStateFlow(listOf(wallet))
|
||||
every { accountsCRUDRepository.getTotalActiveAccountsCount(wallet.walletId) } returns flowOf(2.some())
|
||||
|
||||
// Act
|
||||
val actual = useCase.invoke().first()
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isTrue()
|
||||
|
||||
coVerifyOrder {
|
||||
userWalletsListRepository.load()
|
||||
userWalletsListRepository.userWallets
|
||||
accountsCRUDRepository.getTotalActiveAccountsCount(wallet.walletId)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns false when loadAndGet emits one wallet with isMultiCurrency true and None counts`() = runTest {
|
||||
// Arrange
|
||||
val wallet = createUserWallet(isMultiCurrency = true)
|
||||
|
||||
every { userWalletsListRepository.userWallets } returns MutableStateFlow(listOf(wallet))
|
||||
every { accountsCRUDRepository.getTotalActiveAccountsCount(wallet.walletId) } returns flowOf(none())
|
||||
val accountList = createAccountList(activeAccounts = 1)
|
||||
every { multiAccountListSupplier.invoke() } returns flowOf(listOf(accountList))
|
||||
|
||||
// Act
|
||||
val actual = useCase.invoke().first()
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isFalse()
|
||||
|
||||
coVerifyOrder {
|
||||
userWalletsListRepository.load()
|
||||
userWalletsListRepository.userWallets
|
||||
accountsCRUDRepository.getTotalActiveAccountsCount(wallet.walletId)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns true when loadAndGet emits two wallets, one isMultiCurrency false, one true`() = runTest {
|
||||
fun `returns true when supplier emits account list with two accounts`() = runTest {
|
||||
// Arrange
|
||||
val wallet1 = createUserWallet(isMultiCurrency = false)
|
||||
val wallet2 = createUserWallet(isMultiCurrency = true)
|
||||
|
||||
every { userWalletsListRepository.userWallets } returns MutableStateFlow(listOf(wallet1, wallet2))
|
||||
every { accountsCRUDRepository.getTotalActiveAccountsCount(wallet2.walletId) } returns flowOf(2.some())
|
||||
val accountList = createAccountList(activeAccounts = 2)
|
||||
every { multiAccountListSupplier.invoke() } returns flowOf(listOf(accountList))
|
||||
|
||||
// Act
|
||||
val actual = useCase.invoke().first()
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isTrue()
|
||||
}
|
||||
|
||||
coVerifyOrder {
|
||||
userWalletsListRepository.load()
|
||||
userWalletsListRepository.userWallets
|
||||
accountsCRUDRepository.getTotalActiveAccountsCount(wallet2.walletId)
|
||||
}
|
||||
@Test
|
||||
fun `returns true when supplier emits multiple account lists, one with two accounts`() = runTest {
|
||||
// Arrange
|
||||
val accountList1 = createAccountList(activeAccounts = 1)
|
||||
val accountList2 = createAccountList(activeAccounts = 2)
|
||||
every { multiAccountListSupplier.invoke() } returns flowOf(listOf(accountList1, accountList2))
|
||||
|
||||
verify(inverse = true) { accountsCRUDRepository.getTotalActiveAccountsCount(wallet1.walletId) }
|
||||
// Act
|
||||
val actual = useCase.invoke().first()
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -132,109 +89,71 @@ class IsAccountsModeEnabledUseCaseTest {
|
|||
inner class InvokeSync {
|
||||
|
||||
@Test
|
||||
fun `returns false when getUserWalletsSync returns empty list`() = runTest {
|
||||
fun `returns false when getSyncOrNull returns null`() = runTest {
|
||||
// Arrange
|
||||
every { userWalletsListRepository.userWallets.value } returns emptyList()
|
||||
coEvery { multiAccountListSupplier.getSyncOrNull(Unit, any()) } returns null
|
||||
|
||||
// Act
|
||||
val actual = useCase.invokeSync()
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isFalse()
|
||||
|
||||
verifyOrder {
|
||||
userWalletsListRepository.userWallets.value
|
||||
}
|
||||
|
||||
coVerify(inverse = true) { accountsCRUDRepository.getTotalActiveAccountsCountSync(any()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns false when getUserWalletsSync returns one wallet with isMultiCurrency false`() = runTest {
|
||||
fun `returns false when getSyncOrNull returns empty list`() = runTest {
|
||||
// Arrange
|
||||
val wallet = createUserWallet(isMultiCurrency = false)
|
||||
|
||||
every { userWalletsListRepository.userWallets.value } returns listOf(wallet)
|
||||
coEvery { multiAccountListSupplier.getSyncOrNull(Unit, any()) } returns emptyList()
|
||||
|
||||
// Act
|
||||
val actual = useCase.invokeSync()
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isFalse()
|
||||
|
||||
verifyOrder {
|
||||
userWalletsListRepository.userWallets.value
|
||||
}
|
||||
|
||||
coVerify(inverse = true) { accountsCRUDRepository.getTotalActiveAccountsCountSync(any()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns true when getUserWalletsSync returns one wallet with isMultiCurrency true`() = runTest {
|
||||
fun `returns false when getSyncOrNull returns account list with one account`() = runTest {
|
||||
// Arrange
|
||||
val wallet = createUserWallet(isMultiCurrency = true)
|
||||
val accountList = createAccountList(activeAccounts = 1)
|
||||
coEvery { multiAccountListSupplier.getSyncOrNull(Unit, any()) } returns listOf(accountList)
|
||||
|
||||
every { userWalletsListRepository.userWallets.value } returns listOf(wallet)
|
||||
coEvery { accountsCRUDRepository.getTotalActiveAccountsCountSync(wallet.walletId) } returns 2.some()
|
||||
// Act
|
||||
val actual = useCase.invokeSync()
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns true when getSyncOrNull returns account list with two accounts`() = runTest {
|
||||
// Arrange
|
||||
val accountList = createAccountList(activeAccounts = 2)
|
||||
coEvery { multiAccountListSupplier.getSyncOrNull(Unit, any()) } returns listOf(accountList)
|
||||
|
||||
// Act
|
||||
val actual = useCase.invokeSync()
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isTrue()
|
||||
|
||||
coVerifyOrder {
|
||||
userWalletsListRepository.userWallets.value
|
||||
accountsCRUDRepository.getTotalActiveAccountsCountSync(wallet.walletId)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns false when getUserWalletsSync returns multi wallet with None counts`() = runTest {
|
||||
fun `returns true when getSyncOrNull returns multiple account lists, one with two accounts`() = runTest {
|
||||
// Arrange
|
||||
val wallet = createUserWallet(isMultiCurrency = true)
|
||||
|
||||
every { userWalletsListRepository.userWallets.value } returns listOf(wallet)
|
||||
coEvery { accountsCRUDRepository.getTotalActiveAccountsCountSync(wallet.walletId) } returns none()
|
||||
|
||||
// Act
|
||||
val actual = useCase.invokeSync()
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isFalse()
|
||||
|
||||
coVerifyOrder {
|
||||
userWalletsListRepository.userWallets.value
|
||||
accountsCRUDRepository.getTotalActiveAccountsCountSync(wallet.walletId)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `returns true when getUserWalletsSync returns multi and single wallets`() = runTest {
|
||||
// Arrange
|
||||
val wallet1 = createUserWallet(isMultiCurrency = false)
|
||||
val wallet2 = createUserWallet(isMultiCurrency = true)
|
||||
|
||||
every { userWalletsListRepository.userWallets.value } returns listOf(wallet1, wallet2)
|
||||
coEvery { accountsCRUDRepository.getTotalActiveAccountsCountSync(wallet2.walletId) } returns 2.some()
|
||||
val accountList1 = createAccountList(activeAccounts = 1)
|
||||
val accountList2 = createAccountList(activeAccounts = 2)
|
||||
coEvery { multiAccountListSupplier.getSyncOrNull(Unit, any()) } returns listOf(accountList1, accountList2)
|
||||
|
||||
// Act
|
||||
val actual = useCase.invokeSync()
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isTrue()
|
||||
|
||||
coVerifyOrder {
|
||||
userWalletsListRepository.userWallets.value
|
||||
accountsCRUDRepository.getTotalActiveAccountsCountSync(wallet2.walletId)
|
||||
}
|
||||
|
||||
coVerify(inverse = true) { accountsCRUDRepository.getTotalActiveAccountsCountSync(wallet1.walletId) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun createUserWallet(isMultiCurrency: Boolean): UserWallet = mockk {
|
||||
every { this@mockk.walletId } returns UserWalletId(stringValue = "011")
|
||||
every { this@mockk.isMultiCurrency } returns isMultiCurrency
|
||||
private fun createAccountList(activeAccounts: Int): AccountList = mockk {
|
||||
every { this@mockk.activeAccounts } returns activeAccounts
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue