Updated on 2026-08-14

This commit is contained in:
Tangem 2026-04-29 17:58:33 +04:00
parent b6f31df9d1
commit 655eeb61ba
3 changed files with 189 additions and 147 deletions

View file

@ -6,8 +6,10 @@ import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier
import com.tangem.domain.account.status.usecase.* import com.tangem.domain.account.status.usecase.*
import com.tangem.domain.account.status.utils.CryptoCurrencyBalanceFetcher import com.tangem.domain.account.status.utils.CryptoCurrencyBalanceFetcher
import com.tangem.domain.account.status.utils.CryptoCurrencyMetadataCleaner import com.tangem.domain.account.status.utils.CryptoCurrencyMetadataCleaner
import com.tangem.domain.account.supplier.MultiAccountListSupplier
import com.tangem.domain.account.supplier.SingleAccountListSupplier import com.tangem.domain.account.supplier.SingleAccountListSupplier
import com.tangem.domain.common.wallets.UserWalletsListRepository import com.tangem.domain.common.wallets.UserWalletsListRepository
import com.tangem.domain.pay.flow.PaymentAccountStatusSupplier
import com.tangem.domain.express.ExpressServiceFetcher import com.tangem.domain.express.ExpressServiceFetcher
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
import com.tangem.domain.networks.multi.MultiNetworkStatusSupplier import com.tangem.domain.networks.multi.MultiNetworkStatusSupplier
@ -51,9 +53,13 @@ internal object AccountStatusUseCaseModule {
@Provides @Provides
@Singleton @Singleton
fun provideIsAccountsModeEnabledUseCase( fun provideIsAccountsModeEnabledUseCase(
multiAccountStatusListSupplier: MultiAccountStatusListSupplier, multiAccountListSupplier: MultiAccountListSupplier,
paymentAccountStatusSupplier: PaymentAccountStatusSupplier,
): IsAccountsModeEnabledUseCase { ): IsAccountsModeEnabledUseCase {
return IsAccountsModeEnabledUseCase(multiAccountStatusListSupplier = multiAccountStatusListSupplier) return IsAccountsModeEnabledUseCase(
multiAccountListSupplier = multiAccountListSupplier,
paymentAccountStatusSupplier = paymentAccountStatusSupplier,
)
} }
@Provides @Provides

View file

@ -1,49 +1,76 @@
package com.tangem.domain.account.status.usecase package com.tangem.domain.account.status.usecase
import com.tangem.domain.account.status.supplier.MultiAccountStatusListSupplier import com.tangem.domain.account.models.AccountList
import com.tangem.domain.models.account.AccountStatus import com.tangem.domain.account.supplier.MultiAccountListSupplier
import com.tangem.domain.models.account.Account
import com.tangem.domain.models.account.PaymentAccountStatusValue import com.tangem.domain.models.account.PaymentAccountStatusValue
import kotlinx.coroutines.flow.Flow import com.tangem.domain.pay.flow.PaymentAccountStatusProducer
import kotlinx.coroutines.flow.distinctUntilChanged import com.tangem.domain.pay.flow.PaymentAccountStatusSupplier
import kotlinx.coroutines.flow.map import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.*
/** /**
* Use case to determine if the accounts mode is enabled. * Use case to determine if the accounts mode is enabled.
* Accounts mode is considered enabled if any [com.tangem.domain.account.models.AccountStatusList] produced for the
* user's wallets has more than one [AccountStatus.CryptoPortfolio], or has a [AccountStatus.Payment] with any
* [PaymentAccountStatusValue.Empty].
* *
* @property multiAccountStatusListSupplier supplier that provides a list of * Accounts mode is considered enabled if any user wallet either:
* [com.tangem.domain.account.models.AccountStatusList]s for all user wallets * - contains more than one [Account.CryptoPortfolio], or
* - has a [com.tangem.domain.models.account.AccountStatus.Payment] in an active state.
* *
[REDACTED_AUTHOR] * Splits the structural check (via [MultiAccountListSupplier]) and the payment-status check
* (via [PaymentAccountStatusSupplier] per wallet) so that the structural answer doesn't wait for
* slow per-wallet status pipelines on cold start.
*/ */
class IsAccountsModeEnabledUseCase( class IsAccountsModeEnabledUseCase(
private val multiAccountStatusListSupplier: MultiAccountStatusListSupplier, private val multiAccountListSupplier: MultiAccountListSupplier,
private val paymentAccountStatusSupplier: PaymentAccountStatusSupplier,
) { ) {
@OptIn(ExperimentalCoroutinesApi::class)
operator fun invoke(): Flow<Boolean> { operator fun invoke(): Flow<Boolean> {
return multiAccountStatusListSupplier.invoke() val cryptoMode = multiAccountListSupplier.invoke()
.map { accountStatusLists -> accountStatusLists.any { it.accountStatuses.isModeEnabled() } } .map { lists -> lists.any { it.hasMultipleCryptoPortfolios() } }
val paymentMode = multiAccountListSupplier.invoke().flatMapLatest { lists ->
val walletIdsWithPayment = lists.mapNotNull { list ->
if (list.accounts.any { it is Account.Payment }) list.userWalletId else null
}
if (walletIdsWithPayment.isEmpty()) {
flowOf(false)
} else {
val flows = walletIdsWithPayment.map { walletId ->
paymentAccountStatusSupplier.invoke(walletId)
.map { it.value.isActivePayment() }
.onStart { emit(false) }
}
combine(flows) { results -> results.any { it } }
}
}
return combine(cryptoMode, paymentMode) { crypto, payment -> crypto || payment }
.distinctUntilChanged() .distinctUntilChanged()
} }
suspend fun invokeSync(): Boolean { suspend fun invokeSync(): Boolean {
return multiAccountStatusListSupplier.getSyncOrNull(Unit) val accountLists = multiAccountListSupplier.getSyncOrNull(Unit).orEmpty()
?.any { it.accountStatuses.isModeEnabled() } == true if (accountLists.any { it.hasMultipleCryptoPortfolios() }) return true
val walletIdsWithPayment = accountLists.mapNotNull { list ->
if (list.accounts.any { it is Account.Payment }) list.userWalletId else null
}
return walletIdsWithPayment.any { walletId ->
paymentAccountStatusSupplier
.getSyncOrNull(
params = PaymentAccountStatusProducer.Params(walletId),
timeMillis = PAYMENT_STATUS_SYNC_TIMEOUT_MS,
)
?.value
?.isActivePayment() == true
}
} }
private fun List<AccountStatus>.isModeEnabled(): Boolean { private fun AccountList.hasMultipleCryptoPortfolios(): Boolean =
var cryptoPortfolioCount = 0 accounts.filterIsInstance<Account.CryptoPortfolio>().size > 1
for (status in this) {
when {
status is AccountStatus.CryptoPortfolio && ++cryptoPortfolioCount > 1 -> return true
status is AccountStatus.Payment && status.value.isActivePayment() -> return true
}
}
return false
}
private fun PaymentAccountStatusValue.isActivePayment(): Boolean { private fun PaymentAccountStatusValue.isActivePayment(): Boolean {
return when (this) { return when (this) {
@ -60,4 +87,8 @@ class IsAccountsModeEnabledUseCase(
-> true -> true
} }
} }
private companion object {
const val PAYMENT_STATUS_SYNC_TIMEOUT_MS = 1_000L
}
} }

View file

@ -1,15 +1,19 @@
package com.tangem.domain.account.status.usecase package com.tangem.domain.account.status.usecase
import com.google.common.truth.Truth import com.google.common.truth.Truth
import com.tangem.domain.account.models.AccountStatusList import com.tangem.domain.account.models.AccountList
import com.tangem.domain.account.status.supplier.MultiAccountStatusListSupplier import com.tangem.domain.account.supplier.MultiAccountListSupplier
import com.tangem.domain.models.account.Account
import com.tangem.domain.models.account.AccountStatus import com.tangem.domain.models.account.AccountStatus
import com.tangem.domain.models.account.PaymentAccountStatusValue import com.tangem.domain.models.account.PaymentAccountStatusValue
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.pay.flow.PaymentAccountStatusProducer
import com.tangem.domain.pay.flow.PaymentAccountStatusSupplier
import io.mockk.clearMocks import io.mockk.clearMocks
import io.mockk.coEvery import io.mockk.coEvery
import io.mockk.every import io.mockk.every
import io.mockk.mockk import io.mockk.mockk
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.last
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.AfterEach
@ -20,13 +24,17 @@ import org.junit.jupiter.api.TestInstance
@TestInstance(TestInstance.Lifecycle.PER_CLASS) @TestInstance(TestInstance.Lifecycle.PER_CLASS)
class IsAccountsModeEnabledUseCaseTest { class IsAccountsModeEnabledUseCaseTest {
private val multiAccountStatusListSupplier: MultiAccountStatusListSupplier = mockk() private val multiAccountListSupplier: MultiAccountListSupplier = mockk()
private val paymentAccountStatusSupplier: PaymentAccountStatusSupplier = mockk()
private val useCase = IsAccountsModeEnabledUseCase(multiAccountStatusListSupplier = multiAccountStatusListSupplier) private val useCase = IsAccountsModeEnabledUseCase(
multiAccountListSupplier = multiAccountListSupplier,
paymentAccountStatusSupplier = paymentAccountStatusSupplier,
)
@AfterEach @AfterEach
fun tearDown() { fun tearDown() {
clearMocks(multiAccountStatusListSupplier) clearMocks(multiAccountListSupplier, paymentAccountStatusSupplier)
} }
@Nested @Nested
@ -35,145 +43,140 @@ class IsAccountsModeEnabledUseCaseTest {
@Test @Test
fun `returns false when supplier emits empty list`() = runTest { fun `returns false when supplier emits empty list`() = runTest {
every { multiAccountStatusListSupplier.invoke() } returns flowOf(emptyList()) every { multiAccountListSupplier.invoke() } returns flowOf(emptyList())
val actual = useCase.invoke().first() val actual = useCase.invoke().last()
Truth.assertThat(actual).isFalse() Truth.assertThat(actual).isFalse()
} }
@Test @Test
fun `returns false when single crypto portfolio account`() = runTest { fun `returns false when single crypto portfolio account`() = runTest {
val statusList = createAccountStatusList( val list = createAccountList(WALLET_ID_1, listOf(mockCryptoPortfolio()))
statuses = listOf(mockCryptoPortfolio()), every { multiAccountListSupplier.invoke() } returns flowOf(listOf(list))
)
every { multiAccountStatusListSupplier.invoke() } returns flowOf(listOf(statusList))
val actual = useCase.invoke().first() val actual = useCase.invoke().last()
Truth.assertThat(actual).isFalse() Truth.assertThat(actual).isFalse()
} }
@Test @Test
fun `returns true when two crypto portfolio accounts`() = runTest { fun `returns true when two crypto portfolio accounts`() = runTest {
val statusList = createAccountStatusList( val list = createAccountList(WALLET_ID_1, listOf(mockCryptoPortfolio(), mockCryptoPortfolio()))
statuses = listOf(mockCryptoPortfolio(), mockCryptoPortfolio()), every { multiAccountListSupplier.invoke() } returns flowOf(listOf(list))
)
every { multiAccountStatusListSupplier.invoke() } returns flowOf(listOf(statusList))
val actual = useCase.invoke().first() val actual = useCase.invoke().last()
Truth.assertThat(actual).isTrue() Truth.assertThat(actual).isTrue()
} }
@Test @Test
fun `returns true when payment account is Loaded`() = runTest { fun `returns true when payment account is Loaded`() = runTest {
val statusList = createAccountStatusList( val list = createAccountList(WALLET_ID_1, listOf(mockCryptoPortfolio(), mockPaymentAccount()))
statuses = listOf(mockCryptoPortfolio(), mockPayment(mockk<PaymentAccountStatusValue.Loaded>())), every { multiAccountListSupplier.invoke() } returns flowOf(listOf(list))
) mockPaymentStatus(WALLET_ID_1, mockk<PaymentAccountStatusValue.Loaded>())
every { multiAccountStatusListSupplier.invoke() } returns flowOf(listOf(statusList))
val actual = useCase.invoke().first() val actual = useCase.invoke().last()
Truth.assertThat(actual).isTrue() Truth.assertThat(actual).isTrue()
} }
@Test @Test
fun `returns true when payment account is Locked`() = runTest { fun `returns true when payment account is Locked`() = runTest {
val statusList = createAccountStatusList( val list = createAccountList(WALLET_ID_1, listOf(mockCryptoPortfolio(), mockPaymentAccount()))
statuses = listOf(mockCryptoPortfolio(), mockPayment(mockk<PaymentAccountStatusValue.Locked>())), every { multiAccountListSupplier.invoke() } returns flowOf(listOf(list))
) mockPaymentStatus(WALLET_ID_1, mockk<PaymentAccountStatusValue.Locked>())
every { multiAccountStatusListSupplier.invoke() } returns flowOf(listOf(statusList))
val actual = useCase.invoke().first() val actual = useCase.invoke().last()
Truth.assertThat(actual).isTrue() Truth.assertThat(actual).isTrue()
} }
@Test @Test
fun `returns false when payment account is NotCreated`() = runTest { fun `returns false when payment account is NotCreated`() = runTest {
val statusList = createAccountStatusList( val list = createAccountList(WALLET_ID_1, listOf(mockCryptoPortfolio(), mockPaymentAccount()))
statuses = listOf(mockCryptoPortfolio(), mockPayment(PaymentAccountStatusValue.NotCreated)), every { multiAccountListSupplier.invoke() } returns flowOf(listOf(list))
) mockPaymentStatus(WALLET_ID_1, PaymentAccountStatusValue.NotCreated)
every { multiAccountStatusListSupplier.invoke() } returns flowOf(listOf(statusList))
val actual = useCase.invoke().first() val actual = useCase.invoke().last()
Truth.assertThat(actual).isFalse() Truth.assertThat(actual).isFalse()
} }
@Test @Test
fun `returns false when payment account is Empty`() = runTest { fun `returns false when payment account is Empty`() = runTest {
val statusList = createAccountStatusList( val list = createAccountList(WALLET_ID_1, listOf(mockCryptoPortfolio(), mockPaymentAccount()))
statuses = listOf(mockCryptoPortfolio(), mockPayment(PaymentAccountStatusValue.Empty)), every { multiAccountListSupplier.invoke() } returns flowOf(listOf(list))
) mockPaymentStatus(WALLET_ID_1, PaymentAccountStatusValue.Empty)
every { multiAccountStatusListSupplier.invoke() } returns flowOf(listOf(statusList))
val actual = useCase.invoke().first() val actual = useCase.invoke().last()
Truth.assertThat(actual).isFalse() Truth.assertThat(actual).isFalse()
} }
@Test @Test
fun `returns true when payment account is UnderReview`() = runTest { fun `returns true when payment account is UnderReview`() = runTest {
val statusList = createAccountStatusList( val list = createAccountList(WALLET_ID_1, listOf(mockCryptoPortfolio(), mockPaymentAccount()))
statuses = listOf(mockCryptoPortfolio(), mockPayment(mockk<PaymentAccountStatusValue.UnderReview>())), every { multiAccountListSupplier.invoke() } returns flowOf(listOf(list))
) mockPaymentStatus(WALLET_ID_1, mockk<PaymentAccountStatusValue.UnderReview>())
every { multiAccountStatusListSupplier.invoke() } returns flowOf(listOf(statusList))
val actual = useCase.invoke().first() val actual = useCase.invoke().last()
Truth.assertThat(actual).isTrue() Truth.assertThat(actual).isTrue()
} }
@Test @Test
fun `returns true when payment account is IssuingCard`() = runTest { fun `returns true when payment account is IssuingCard`() = runTest {
val statusList = createAccountStatusList( val list = createAccountList(WALLET_ID_1, listOf(mockCryptoPortfolio(), mockPaymentAccount()))
statuses = listOf(mockCryptoPortfolio(), mockPayment(mockk<PaymentAccountStatusValue.IssuingCard>())), every { multiAccountListSupplier.invoke() } returns flowOf(listOf(list))
) mockPaymentStatus(WALLET_ID_1, mockk<PaymentAccountStatusValue.IssuingCard>())
every { multiAccountStatusListSupplier.invoke() } returns flowOf(listOf(statusList))
val actual = useCase.invoke().first() val actual = useCase.invoke().last()
Truth.assertThat(actual).isTrue() Truth.assertThat(actual).isTrue()
} }
@Test @Test
fun `returns true when payment account is Loading`() = runTest { fun `returns true when payment account is Loading`() = runTest {
val statusList = createAccountStatusList( val list = createAccountList(WALLET_ID_1, listOf(mockCryptoPortfolio(), mockPaymentAccount()))
statuses = listOf(mockCryptoPortfolio(), mockPayment(PaymentAccountStatusValue.Loading)), every { multiAccountListSupplier.invoke() } returns flowOf(listOf(list))
) mockPaymentStatus(WALLET_ID_1, PaymentAccountStatusValue.Loading)
every { multiAccountStatusListSupplier.invoke() } returns flowOf(listOf(statusList))
val actual = useCase.invoke().first() val actual = useCase.invoke().last()
Truth.assertThat(actual).isTrue() Truth.assertThat(actual).isTrue()
} }
@Test @Test
fun `GIVEN payment account is Deactivated WHEN invoke THEN returns true`() = runTest { fun `returns true when payment account is Deactivated`() = runTest {
// GIVEN val list = createAccountList(WALLET_ID_1, listOf(mockCryptoPortfolio(), mockPaymentAccount()))
val statusList = createAccountStatusList( every { multiAccountListSupplier.invoke() } returns flowOf(listOf(list))
statuses = listOf(mockCryptoPortfolio(), mockPayment(mockk<PaymentAccountStatusValue.Deactivated>())), mockPaymentStatus(WALLET_ID_1, mockk<PaymentAccountStatusValue.Deactivated>())
)
every { multiAccountStatusListSupplier.invoke() } returns flowOf(listOf(statusList))
// WHEN val actual = useCase.invoke().last()
val actual = useCase.invoke().first()
// THEN
Truth.assertThat(actual).isTrue() Truth.assertThat(actual).isTrue()
} }
@Test @Test
fun `returns true when multiple status lists and one has two crypto portfolios`() = runTest { fun `returns true when multiple wallets and one has two crypto portfolios`() = runTest {
val statusList1 = createAccountStatusList(statuses = listOf(mockCryptoPortfolio())) val list1 = createAccountList(WALLET_ID_1, listOf(mockCryptoPortfolio()))
val statusList2 = createAccountStatusList( val list2 = createAccountList(WALLET_ID_2, listOf(mockCryptoPortfolio(), mockCryptoPortfolio()))
statuses = listOf(mockCryptoPortfolio(), mockCryptoPortfolio()), every { multiAccountListSupplier.invoke() } returns flowOf(listOf(list1, list2))
)
every { multiAccountStatusListSupplier.invoke() } returns flowOf(listOf(statusList1, statusList2))
val actual = useCase.invoke().first() val actual = useCase.invoke().last()
Truth.assertThat(actual).isTrue()
}
@Test
fun `returns true when multiple wallets and one has active payment`() = runTest {
val list1 = createAccountList(WALLET_ID_1, listOf(mockCryptoPortfolio()))
val list2 = createAccountList(WALLET_ID_2, listOf(mockCryptoPortfolio(), mockPaymentAccount()))
every { multiAccountListSupplier.invoke() } returns flowOf(listOf(list1, list2))
mockPaymentStatus(WALLET_ID_2, mockk<PaymentAccountStatusValue.Loaded>())
val actual = useCase.invoke().last()
Truth.assertThat(actual).isTrue() Truth.assertThat(actual).isTrue()
} }
@ -185,7 +188,7 @@ class IsAccountsModeEnabledUseCaseTest {
@Test @Test
fun `returns false when getSyncOrNull returns null`() = runTest { fun `returns false when getSyncOrNull returns null`() = runTest {
coEvery { multiAccountStatusListSupplier.getSyncOrNull(Unit, any()) } returns null coEvery { multiAccountListSupplier.getSyncOrNull(Unit, any()) } returns null
val actual = useCase.invokeSync() val actual = useCase.invokeSync()
@ -194,7 +197,7 @@ class IsAccountsModeEnabledUseCaseTest {
@Test @Test
fun `returns false when getSyncOrNull returns empty list`() = runTest { fun `returns false when getSyncOrNull returns empty list`() = runTest {
coEvery { multiAccountStatusListSupplier.getSyncOrNull(Unit, any()) } returns emptyList() coEvery { multiAccountListSupplier.getSyncOrNull(Unit, any()) } returns emptyList()
val actual = useCase.invokeSync() val actual = useCase.invokeSync()
@ -203,10 +206,8 @@ class IsAccountsModeEnabledUseCaseTest {
@Test @Test
fun `returns false when single crypto portfolio account`() = runTest { fun `returns false when single crypto portfolio account`() = runTest {
val statusList = createAccountStatusList( val list = createAccountList(WALLET_ID_1, listOf(mockCryptoPortfolio()))
statuses = listOf(mockCryptoPortfolio()), coEvery { multiAccountListSupplier.getSyncOrNull(Unit, any()) } returns listOf(list)
)
coEvery { multiAccountStatusListSupplier.getSyncOrNull(Unit, any()) } returns listOf(statusList)
val actual = useCase.invokeSync() val actual = useCase.invokeSync()
@ -215,10 +216,8 @@ class IsAccountsModeEnabledUseCaseTest {
@Test @Test
fun `returns true when two crypto portfolio accounts`() = runTest { fun `returns true when two crypto portfolio accounts`() = runTest {
val statusList = createAccountStatusList( val list = createAccountList(WALLET_ID_1, listOf(mockCryptoPortfolio(), mockCryptoPortfolio()))
statuses = listOf(mockCryptoPortfolio(), mockCryptoPortfolio()), coEvery { multiAccountListSupplier.getSyncOrNull(Unit, any()) } returns listOf(list)
)
coEvery { multiAccountStatusListSupplier.getSyncOrNull(Unit, any()) } returns listOf(statusList)
val actual = useCase.invokeSync() val actual = useCase.invokeSync()
@ -227,10 +226,9 @@ class IsAccountsModeEnabledUseCaseTest {
@Test @Test
fun `returns true when payment account is Loaded`() = runTest { fun `returns true when payment account is Loaded`() = runTest {
val statusList = createAccountStatusList( val list = createAccountList(WALLET_ID_1, listOf(mockCryptoPortfolio(), mockPaymentAccount()))
statuses = listOf(mockCryptoPortfolio(), mockPayment(mockk<PaymentAccountStatusValue.Loaded>())), coEvery { multiAccountListSupplier.getSyncOrNull(Unit, any()) } returns listOf(list)
) mockPaymentStatusSync(WALLET_ID_1, mockk<PaymentAccountStatusValue.Loaded>())
coEvery { multiAccountStatusListSupplier.getSyncOrNull(Unit, any()) } returns listOf(statusList)
val actual = useCase.invokeSync() val actual = useCase.invokeSync()
@ -239,10 +237,9 @@ class IsAccountsModeEnabledUseCaseTest {
@Test @Test
fun `returns true when payment account is Locked`() = runTest { fun `returns true when payment account is Locked`() = runTest {
val statusList = createAccountStatusList( val list = createAccountList(WALLET_ID_1, listOf(mockCryptoPortfolio(), mockPaymentAccount()))
statuses = listOf(mockCryptoPortfolio(), mockPayment(mockk<PaymentAccountStatusValue.Locked>())), coEvery { multiAccountListSupplier.getSyncOrNull(Unit, any()) } returns listOf(list)
) mockPaymentStatusSync(WALLET_ID_1, mockk<PaymentAccountStatusValue.Locked>())
coEvery { multiAccountStatusListSupplier.getSyncOrNull(Unit, any()) } returns listOf(statusList)
val actual = useCase.invokeSync() val actual = useCase.invokeSync()
@ -251,10 +248,9 @@ class IsAccountsModeEnabledUseCaseTest {
@Test @Test
fun `returns false when payment account is NotCreated`() = runTest { fun `returns false when payment account is NotCreated`() = runTest {
val statusList = createAccountStatusList( val list = createAccountList(WALLET_ID_1, listOf(mockCryptoPortfolio(), mockPaymentAccount()))
statuses = listOf(mockCryptoPortfolio(), mockPayment(PaymentAccountStatusValue.NotCreated)), coEvery { multiAccountListSupplier.getSyncOrNull(Unit, any()) } returns listOf(list)
) mockPaymentStatusSync(WALLET_ID_1, PaymentAccountStatusValue.NotCreated)
coEvery { multiAccountStatusListSupplier.getSyncOrNull(Unit, any()) } returns listOf(statusList)
val actual = useCase.invokeSync() val actual = useCase.invokeSync()
@ -263,10 +259,9 @@ class IsAccountsModeEnabledUseCaseTest {
@Test @Test
fun `returns false when payment account is Empty`() = runTest { fun `returns false when payment account is Empty`() = runTest {
val statusList = createAccountStatusList( val list = createAccountList(WALLET_ID_1, listOf(mockCryptoPortfolio(), mockPaymentAccount()))
statuses = listOf(mockCryptoPortfolio(), mockPayment(PaymentAccountStatusValue.Empty)), coEvery { multiAccountListSupplier.getSyncOrNull(Unit, any()) } returns listOf(list)
) mockPaymentStatusSync(WALLET_ID_1, PaymentAccountStatusValue.Empty)
coEvery { multiAccountStatusListSupplier.getSyncOrNull(Unit, any()) } returns listOf(statusList)
val actual = useCase.invokeSync() val actual = useCase.invokeSync()
@ -275,10 +270,9 @@ class IsAccountsModeEnabledUseCaseTest {
@Test @Test
fun `returns true when payment account is UnderReview`() = runTest { fun `returns true when payment account is UnderReview`() = runTest {
val statusList = createAccountStatusList( val list = createAccountList(WALLET_ID_1, listOf(mockCryptoPortfolio(), mockPaymentAccount()))
statuses = listOf(mockCryptoPortfolio(), mockPayment(mockk<PaymentAccountStatusValue.UnderReview>())), coEvery { multiAccountListSupplier.getSyncOrNull(Unit, any()) } returns listOf(list)
) mockPaymentStatusSync(WALLET_ID_1, mockk<PaymentAccountStatusValue.UnderReview>())
coEvery { multiAccountStatusListSupplier.getSyncOrNull(Unit, any()) } returns listOf(statusList)
val actual = useCase.invokeSync() val actual = useCase.invokeSync()
@ -286,27 +280,22 @@ class IsAccountsModeEnabledUseCaseTest {
} }
@Test @Test
fun `GIVEN payment account is Deactivated WHEN invokeSync THEN returns true`() = runTest { fun `returns true when payment account is Deactivated`() = runTest {
// GIVEN val list = createAccountList(WALLET_ID_1, listOf(mockCryptoPortfolio(), mockPaymentAccount()))
val statusList = createAccountStatusList( coEvery { multiAccountListSupplier.getSyncOrNull(Unit, any()) } returns listOf(list)
statuses = listOf(mockCryptoPortfolio(), mockPayment(mockk<PaymentAccountStatusValue.Deactivated>())), mockPaymentStatusSync(WALLET_ID_1, mockk<PaymentAccountStatusValue.Deactivated>())
)
coEvery { multiAccountStatusListSupplier.getSyncOrNull(Unit, any()) } returns listOf(statusList)
// WHEN
val actual = useCase.invokeSync() val actual = useCase.invokeSync()
// THEN
Truth.assertThat(actual).isTrue() Truth.assertThat(actual).isTrue()
} }
@Test @Test
fun `returns true when multiple status lists and one has loaded payment`() = runTest { fun `returns true when multiple wallets and one has loaded payment`() = runTest {
val statusList1 = createAccountStatusList(statuses = listOf(mockCryptoPortfolio())) val list1 = createAccountList(WALLET_ID_1, listOf(mockCryptoPortfolio()))
val statusList2 = createAccountStatusList( val list2 = createAccountList(WALLET_ID_2, listOf(mockCryptoPortfolio(), mockPaymentAccount()))
statuses = listOf(mockCryptoPortfolio(), mockPayment(mockk<PaymentAccountStatusValue.Loaded>())), coEvery { multiAccountListSupplier.getSyncOrNull(Unit, any()) } returns listOf(list1, list2)
) mockPaymentStatusSync(WALLET_ID_2, mockk<PaymentAccountStatusValue.Loaded>())
coEvery { multiAccountStatusListSupplier.getSyncOrNull(Unit, any()) } returns listOf(statusList1, statusList2)
val actual = useCase.invokeSync() val actual = useCase.invokeSync()
@ -314,13 +303,29 @@ class IsAccountsModeEnabledUseCaseTest {
} }
} }
private fun mockCryptoPortfolio(): AccountStatus.CryptoPortfolio = mockk() private fun mockCryptoPortfolio(): Account.CryptoPortfolio = mockk()
private fun mockPayment(value: PaymentAccountStatusValue): AccountStatus.Payment = mockk { private fun mockPaymentAccount(): Account.Payment = mockk()
every { this@mockk.value } returns value
private fun mockPaymentStatus(walletId: UserWalletId, value: PaymentAccountStatusValue) {
val status = mockk<AccountStatus.Payment> { every { this@mockk.value } returns value }
every { paymentAccountStatusSupplier.invoke(walletId) } returns flowOf(status)
} }
private fun createAccountStatusList(statuses: List<AccountStatus>): AccountStatusList = mockk { private fun mockPaymentStatusSync(walletId: UserWalletId, value: PaymentAccountStatusValue) {
every { accountStatuses } returns statuses val status = mockk<AccountStatus.Payment> { every { this@mockk.value } returns value }
coEvery {
paymentAccountStatusSupplier.getSyncOrNull(PaymentAccountStatusProducer.Params(walletId), any())
} returns status
}
private fun createAccountList(walletId: UserWalletId, accounts: List<Account>): AccountList = mockk {
every { userWalletId } returns walletId
every { this@mockk.accounts } returns accounts
}
private companion object {
val WALLET_ID_1 = UserWalletId(stringValue = "011")
val WALLET_ID_2 = UserWalletId(stringValue = "022")
} }
} }