Updated on 2026-08-14

This commit is contained in:
Tangem 2025-08-07 18:58:42 +04:00
parent 0a8e78877d
commit 06263e1193
11 changed files with 360 additions and 436 deletions

View file

@ -10,12 +10,8 @@ import com.tangem.domain.account.models.AccountList
import com.tangem.domain.account.repository.AccountsCRUDRepository
import com.tangem.domain.models.TokensGroupType
import com.tangem.domain.models.TokensSortType
import com.tangem.domain.models.account.Account
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.*
import com.tangem.domain.models.wallet.UserWalletId
import java.util.UUID
/**
* Use case for adding a new crypto portfolio account
@ -42,7 +38,7 @@ class AddCryptoPortfolioUseCase(
userWalletId: UserWalletId,
accountName: AccountName,
icon: CryptoPortfolioIcon,
derivationIndex: Int,
derivationIndex: DerivationIndex,
): Either<Error, Account.CryptoPortfolio> = either {
val newAccount = createAccount(userWalletId, accountName, icon, derivationIndex)
@ -62,11 +58,10 @@ class AddCryptoPortfolioUseCase(
userWalletId: UserWalletId,
accountName: AccountName,
icon: CryptoPortfolioIcon,
derivationIndex: Int,
derivationIndex: DerivationIndex,
): Account.CryptoPortfolio {
// TODO: [REDACTED_JIRA]
return Account.CryptoPortfolio(
accountId = AccountId(userWalletId = userWalletId, value = UUID.randomUUID().toString()),
accountId = AccountId.forCryptoPortfolio(userWalletId = userWalletId, derivationIndex = derivationIndex),
accountName = accountName,
accountIcon = icon,
derivationIndex = derivationIndex,
@ -77,7 +72,6 @@ class AddCryptoPortfolioUseCase(
groupType = TokensGroupType.NONE,
),
)
.getOrElse { raise(Error.AccountCreation(it)) }
}
private suspend fun Raise<Error>.getAccountList(userWalletId: UserWalletId): Option<AccountList> {
@ -108,13 +102,6 @@ class AddCryptoPortfolioUseCase(
*/
sealed interface Error {
/**
* Error indicating that the account creation failed
*
* @property cause the underlying cause of the failure
*/
data class AccountCreation(val cause: Account.CryptoPortfolio.Error) : Error
/**
* Error indicating that the account list requirements were not met.
*

View file

@ -3,14 +3,13 @@ package com.tangem.domain.account.models
import arrow.core.Either
import arrow.core.left
import com.google.common.truth.Truth
import com.tangem.domain.account.utils.randomAccountId
import com.tangem.domain.models.TokensGroupType
import com.tangem.domain.models.TokensSortType
import com.tangem.domain.account.utils.createAccount
import com.tangem.domain.account.utils.createAccounts
import com.tangem.domain.models.account.Account
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.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import io.mockk.clearMocks
import io.mockk.mockk
import org.junit.jupiter.api.BeforeEach
@ -19,7 +18,6 @@ import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.MethodSource
import kotlin.random.Random
/**
[REDACTED_AUTHOR]
@ -30,7 +28,7 @@ class AccountListTest {
@Test
fun mainAccount() {
// Arrange
val mainAccount = createAccount(isMain = true)
val mainAccount = Account.CryptoPortfolio.createMainAccount(userWalletId = userWalletId)
val accountList = AccountList(
userWallet = mockk(),
@ -52,13 +50,13 @@ class AccountListTest {
// Arrange
val accountList = AccountList(
userWallet = mockk(),
accounts = createAccounts(count = 2),
accounts = createAccounts(userWalletId = userWalletId, count = 2),
totalAccounts = 2,
).getOrNull()!!
val fullAccountList = AccountList(
userWallet = mockk(),
accounts = createAccounts(20),
accounts = createAccounts(userWalletId = userWalletId, count = 20),
totalAccounts = 20,
).getOrNull()!!
@ -116,50 +114,41 @@ class AccountListTest {
expected = AccountList.Error.EmptyAccountsList.left(),
),
CreateTestModel(
accounts = setOf(createAccount(isMain = false)),
accounts = setOf(
createAccount(userWalletId = userWalletId, derivationIndex = 1),
),
expected = AccountList.Error.MainAccountNotFound.left(),
),
CreateTestModel(
accounts = setOf(
createAccount(isMain = true),
createAccount(isMain = true),
Account.CryptoPortfolio.createMainAccount(userWalletId),
Account.CryptoPortfolio.createMainAccount(userWalletId).copy(
accountIcon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
),
),
expected = AccountList.Error.ExceedsMaxMainAccountsCount.left(),
),
createAccount(isMain = true).let {
CreateTestModel(
accounts = setOf(it),
expected = AccountList(
userWallet = userWallet,
accounts = setOf(it),
totalAccounts = 1,
),
)
},
createAccounts(count = 20).let {
createAccounts(userWalletId = userWalletId, count = 1).let {
CreateTestModel(
accounts = it,
expected = AccountList(
userWallet = userWallet,
accounts = it,
totalAccounts = 20,
),
expected = AccountList(userWallet = userWallet, accounts = it, totalAccounts = 1),
)
},
createAccounts(userWalletId = userWalletId, count = 20).let {
CreateTestModel(
accounts = it,
expected = AccountList(userWallet = userWallet, accounts = it, totalAccounts = 20),
)
},
CreateTestModel(
accounts = createAccounts(21),
accounts = createAccounts(userWalletId = userWalletId, count = 21),
expected = AccountList.Error.ExceedsMaxAccountsCount.left(),
),
CreateTestModel(
accounts = setOf(
createAccount(
accountId = AccountId(value = "1", userWalletId = mockk()),
isMain = true,
),
createAccount(
accountId = AccountId(value = "1", userWalletId = mockk()),
isMain = false,
),
createAccount(userWalletId = userWalletId, derivationIndex = 0),
createAccount(userWalletId = userWalletId, derivationIndex = 1),
createAccount(userWalletId = userWalletId, derivationIndex = 1),
),
expected = AccountList.Error.DuplicateAccountIds.left(),
),
@ -190,12 +179,8 @@ class AccountListTest {
private fun provideTestModels() = listOf(
// region Add new account
run {
val mainAccount = createAccount(
accountId = AccountId(value = "1", userWalletId = mockk()),
isMain = true,
)
val newAccount = createAccount(isMain = false)
val mainAccount = Account.CryptoPortfolio.createMainAccount(userWalletId)
val newAccount = createAccount(userWalletId = userWalletId, derivationIndex = 1)
PlusTestModel(
initial = AccountList(
@ -214,11 +199,7 @@ class AccountListTest {
// endregion
// region Replace existing account
run {
val mainAccount = createAccount(
accountId = AccountId(value = "1", userWalletId = mockk()),
isMain = true,
)
val mainAccount = Account.CryptoPortfolio.createMainAccount(userWalletId)
val newAccount = mainAccount.copy(accountName = AccountName("New Name").getOrNull()!!)
PlusTestModel(
@ -239,33 +220,12 @@ class AccountListTest {
PlusTestModel(
initial = AccountList(
userWallet = userWallet,
accounts = createAccounts(20),
accounts = createAccounts(userWalletId = userWalletId, count = 20),
totalAccounts = 20,
).getOrNull()!!,
toAdd = createAccount(isMain = false),
toAdd = createAccount(userWalletId = userWalletId, derivationIndex = 21),
expected = AccountList.Error.ExceedsMaxAccountsCount.left(),
),
PlusTestModel(
initial = AccountList(
userWallet = userWallet,
accounts = setOf(createAccount(isMain = true)),
totalAccounts = 1,
).getOrNull()!!,
toAdd = createAccount(isMain = true),
expected = AccountList.Error.ExceedsMaxMainAccountsCount.left(),
),
PlusTestModel(
initial = AccountList(
userWallet = userWallet,
accounts = setOf(
createAccount(isMain = true),
createAccount(isMain = false),
),
totalAccounts = 2,
).getOrNull()!!,
toAdd = createAccount(isMain = true),
expected = AccountList.Error.ExceedsMaxMainAccountsCount.left(),
),
)
}
@ -294,15 +254,8 @@ class AccountListTest {
private fun provideTestModels() = listOf(
// region Remove existing account
run {
val mainAccount = createAccount(
accountId = AccountId(value = "1", userWalletId = mockk()),
isMain = true,
)
val secondaryAccount = createAccount(
accountId = AccountId(value = "2", userWalletId = mockk()),
isMain = false,
)
val mainAccount = Account.CryptoPortfolio.createMainAccount(userWalletId)
val secondaryAccount = createAccount(userWalletId = userWalletId, derivationIndex = 2)
MinusTestModel(
initial = AccountList(
@ -321,14 +274,9 @@ class AccountListTest {
// endregion
// region Remove unexisting account
run {
val mainAccount = createAccount(
accountId = AccountId(value = "1", userWalletId = mockk()),
isMain = true,
)
val notInList = createAccount(
accountId = AccountId(value = "3", userWalletId = mockk()),
isMain = false,
)
val mainAccount = Account.CryptoPortfolio.createMainAccount(userWalletId)
val notInList = createAccount(userWalletId = userWalletId, derivationIndex = 3)
MinusTestModel(
initial = AccountList(
userWallet = userWallet,
@ -346,7 +294,7 @@ class AccountListTest {
// endregion
// region EmptyAccountsList
run {
val mainAccount = createAccount(isMain = true)
val mainAccount = Account.CryptoPortfolio.createMainAccount(userWalletId)
MinusTestModel(
initial = AccountList(
@ -361,14 +309,9 @@ class AccountListTest {
// endregion
// region MainAccountNotFound
run {
val mainAccount = createAccount(
accountId = AccountId(value = "1", userWalletId = mockk()),
isMain = true,
)
val secondaryAccount = createAccount(
accountId = AccountId(value = "2", userWalletId = mockk()),
isMain = false,
)
val mainAccount = Account.CryptoPortfolio.createMainAccount(userWalletId)
val secondaryAccount = createAccount(userWalletId = userWalletId, derivationIndex = 2)
MinusTestModel(
initial = AccountList(
userWallet = userWallet,
@ -389,32 +332,8 @@ class AccountListTest {
val expected: Either<AccountList.Error, AccountList>,
)
private fun createAccounts(count: Int): Set<Account.CryptoPortfolio> {
return buildSet {
add(createAccount(isMain = true))
repeat(count - 1) {
add(createAccount(isMain = false))
}
}
}
private companion object {
private fun createAccount(
accountId: AccountId = AccountId(value = randomAccountId(length = 5), userWalletId = mockk()),
accountIcon: CryptoPortfolioIcon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
isMain: Boolean,
): Account.CryptoPortfolio {
return Account.CryptoPortfolio(
accountId = accountId,
name = "Test Account",
accountIcon = accountIcon,
derivationIndex = if (isMain) 0 else Random.nextInt(1, 21),
isArchived = false,
cryptoCurrencyList = Account.CryptoPortfolio.CryptoCurrencyList(
currencies = emptySet(),
sortType = TokensSortType.NONE,
groupType = TokensGroupType.NONE,
),
)
.getOrNull()!!
val userWalletId = UserWalletId("011")
}
}

View file

@ -7,11 +7,9 @@ import arrow.core.toOption
import com.google.common.truth.Truth
import com.tangem.domain.account.models.AccountList
import com.tangem.domain.account.repository.AccountsCRUDRepository
import com.tangem.domain.models.TokensGroupType
import com.tangem.domain.models.TokensSortType
import com.tangem.domain.account.utils.createAccount
import com.tangem.domain.account.utils.createAccounts
import com.tangem.domain.models.account.Account
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.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
@ -20,8 +18,6 @@ import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import java.util.UUID
import kotlin.random.Random
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class AddCryptoPortfolioUseCaseTest {
@ -29,47 +25,21 @@ class AddCryptoPortfolioUseCaseTest {
private val crudRepository: AccountsCRUDRepository = mockk(relaxUnitFun = true)
private val useCase = AddCryptoPortfolioUseCase(crudRepository)
private val userWalletId = UserWalletId("011")
private val userWallet = mockk<UserWallet>()
@BeforeEach
fun resetMocks() {
clearMocks(crudRepository, userWallet)
every { userWallet.walletId } returns userWalletId
}
@Test
fun `invoke should add new crypto portfolio account to existing list`() = runTest {
// Arrange
val existingAccount = createAccount(
name = "Main Account",
derivationIndex = 0,
icon = CryptoPortfolioIcon.ofMainAccount(userWalletId = userWalletId),
)
val accountList = AccountList(
userWallet = userWallet,
accounts = setOf(existingAccount),
totalAccounts = 1,
).getOrNull()!!
val fakeUUID = UUID.randomUUID()
mockkStatic(UUID::class)
every { UUID.randomUUID() } returns fakeUUID
val newAccount = createAccount(
accountId = AccountId(value = fakeUUID.toString(), userWalletId = userWalletId),
name = "New Account",
icon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
derivationIndex = 1,
)
val newAccount = createNewAccount()
val accountList = AccountList.createEmpty(userWallet)
val updatedAccountList = (accountList + newAccount).getOrNull()!!
coEvery { crudRepository.getAccounts(userWalletId) } returns accountList.toOption()
coEvery { crudRepository.saveAccounts(updatedAccountList) } just Runs
// Act
val actual = useCase(
@ -89,30 +59,16 @@ class AddCryptoPortfolioUseCaseTest {
}
coVerify(inverse = true) { crudRepository.getUserWallet(userWalletId) }
unmockkStatic(UUID::class)
}
@Test
fun `invoke should create new account list if none exists`() = runTest {
// Arrange
val fakeUUID = UUID.randomUUID()
mockkStatic(UUID::class)
every { UUID.randomUUID() } returns fakeUUID
val newAccount = createAccount(
accountId = AccountId(value = fakeUUID.toString(), userWalletId = userWalletId),
name = "New Account",
icon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
derivationIndex = 1,
)
val newAccount = createNewAccount()
val newAccountList = (AccountList.createEmpty(userWallet) + newAccount).getOrNull()!!
coEvery { crudRepository.getAccounts(userWalletId) } returns None
coEvery { crudRepository.getUserWallet(userWalletId) } returns userWallet
coEvery { crudRepository.saveAccounts(newAccountList) } just Runs
// Act
val actual = useCase(
@ -131,32 +87,6 @@ class AddCryptoPortfolioUseCaseTest {
crudRepository.getUserWallet(userWalletId)
crudRepository.saveAccounts(newAccountList)
}
unmockkStatic(UUID::class)
}
@Test
fun `invoke should return error if account creation fails`() = runTest {
// Act
val actual = useCase(
userWalletId = userWalletId,
accountName = AccountName.Main,
icon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
derivationIndex = -1,
)
// Assert
val expected = AddCryptoPortfolioUseCase.Error.AccountCreation(
cause = Account.CryptoPortfolio.Error.NegativeDerivationIndex,
).left()
Truth.assertThat(actual).isEqualTo(expected)
coVerify(inverse = true) {
crudRepository.getAccounts(any())
crudRepository.getUserWallet(any())
crudRepository.saveAccounts(any())
}
}
@Test
@ -164,15 +94,11 @@ class AddCryptoPortfolioUseCaseTest {
// Arrange
val accountList = AccountList(
userWallet = userWallet,
accounts = createAccounts(count = 20),
accounts = createAccounts(userWalletId = userWalletId, count = 20),
totalAccounts = 20,
).getOrNull()!!
val newAccount = createAccount(
name = "New Account",
icon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
derivationIndex = 1,
)
val newAccount = createNewAccount(derivationIndex = 21)
coEvery { crudRepository.getAccounts(userWalletId) } returns accountList.toOption()
@ -202,12 +128,7 @@ class AddCryptoPortfolioUseCaseTest {
@Test
fun `invoke should return error if getAccounts throws exception`() = runTest {
// Arrange
val newAccount = createAccount(
name = "New Account",
icon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
derivationIndex = 1,
)
val newAccount = createNewAccount()
val exception = IllegalStateException("Test error")
coEvery { crudRepository.getAccounts(userWalletId) } throws exception
@ -235,30 +156,8 @@ class AddCryptoPortfolioUseCaseTest {
@Test
fun `invoke should return error if saveAccounts throws exception`() = runTest {
// Arrange
val existingAccount = createAccount(
name = "Main Account",
derivationIndex = 0,
icon = CryptoPortfolioIcon.ofMainAccount(userWalletId = userWalletId),
)
val accountList = AccountList(
userWallet = userWallet,
accounts = setOf(existingAccount),
totalAccounts = 1,
).getOrNull()!!
val fakeUUID = UUID.randomUUID()
mockkStatic(UUID::class)
every { UUID.randomUUID() } returns fakeUUID
val newAccount = createAccount(
accountId = AccountId(value = fakeUUID.toString(), userWalletId = userWalletId),
name = "New Account",
icon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
derivationIndex = 1,
)
val newAccount = createNewAccount()
val accountList = AccountList.createEmpty(userWallet)
val updatedAccountList = (accountList + newAccount).getOrNull()!!
val exception = IllegalStateException("Test error")
@ -267,7 +166,7 @@ class AddCryptoPortfolioUseCaseTest {
coEvery { crudRepository.saveAccounts(updatedAccountList) } throws exception
// Act
useCase(
val actual = useCase(
userWalletId = userWalletId,
accountName = newAccount.name,
icon = newAccount.icon,
@ -275,8 +174,8 @@ class AddCryptoPortfolioUseCaseTest {
)
// Assert
// val expected = AddCryptoPortfolioUseCase.Error.DataOperationFailed(cause = exception).left()
// Truth.assertThat(actual).isEqualTo(expected)
val expected = AddCryptoPortfolioUseCase.Error.DataOperationFailed(cause = exception).left()
Truth.assertThat(actual).isEqualTo(expected)
coVerifyOrder {
crudRepository.getAccounts(userWalletId)
@ -286,32 +185,17 @@ class AddCryptoPortfolioUseCaseTest {
coVerify(inverse = true) { crudRepository.getUserWallet(userWalletId) }
}
private fun createAccounts(count: Int): Set<Account.CryptoPortfolio> {
return buildSet {
add(createAccount(derivationIndex = 0))
repeat(count - 1) {
add(createAccount())
}
private companion object {
val userWalletId = UserWalletId("011")
fun createNewAccount(derivationIndex: Int = 1): Account.CryptoPortfolio {
return createAccount(
userWalletId = userWalletId,
name = "New Account",
icon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
derivationIndex = derivationIndex,
)
}
}
private fun createAccount(
accountId: AccountId? = null,
name: String = "Test Account",
icon: CryptoPortfolioIcon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
derivationIndex: Int = Random.nextInt(1, 21),
): Account.CryptoPortfolio {
return Account.CryptoPortfolio(
accountId = accountId ?: AccountId(value = UUID.randomUUID().toString(), userWalletId = userWalletId),
accountName = AccountName(name).getOrNull()!!,
accountIcon = icon,
derivationIndex = derivationIndex,
isArchived = false,
cryptoCurrencyList = Account.CryptoPortfolio.CryptoCurrencyList(
currencies = emptySet(),
sortType = TokensSortType.NONE,
groupType = TokensGroupType.NONE,
),
).getOrNull()!!
}
}

View file

@ -8,19 +8,17 @@ import com.google.common.truth.Truth
import com.tangem.domain.account.models.AccountList
import com.tangem.domain.account.repository.AccountsCRUDRepository
import com.tangem.domain.account.usecase.UpdateCryptoPortfolioUseCase.Error
import com.tangem.domain.account.utils.randomAccountId
import com.tangem.domain.models.TokensGroupType
import com.tangem.domain.models.TokensSortType
import com.tangem.domain.models.account.Account
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 io.mockk.*
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import kotlin.random.Random
/**
[REDACTED_AUTHOR]
@ -31,25 +29,24 @@ class UpdateCryptoPortfolioUseCaseTest {
private val crudRepository: AccountsCRUDRepository = mockk(relaxUnitFun = true)
private val useCase = UpdateCryptoPortfolioUseCase(crudRepository = crudRepository)
private val userWallet = mockk<UserWallet>()
@BeforeEach
fun resetMocks() {
clearMocks(crudRepository)
clearMocks(crudRepository, userWallet)
every { userWallet.walletId } returns userWalletId
}
@Test
fun `invoke should update crypto portfolio account with new name`() = runTest {
// Arrange
val accountId = AccountId(value = "test-account-id", userWalletId = mockk())
val userWalletId = accountId.userWalletId
val account = createAccount(accountId = accountId, isMain = true)
val accountList = AccountList(
userWallet = mockk(),
accounts = setOf(account),
totalAccounts = 1,
)
.getOrNull()!!
val accountList = AccountList.createEmpty(userWallet = userWallet)
val accountId = accountList.mainAccount.accountId
val newAccountName = AccountName("New name").getOrNull()!!
val updatedAccount = accountList.mainAccount.copy(accountName = newAccountName)
val updatedAccountList = (accountList + updatedAccount).getOrNull()!!
coEvery { crudRepository.getAccounts(userWalletId = userWalletId) } returns accountList.toOption()
@ -57,11 +54,9 @@ class UpdateCryptoPortfolioUseCaseTest {
val actual = useCase(accountId = accountId, accountName = newAccountName)
// Assert
val updatedAccount = account.copy(accountName = newAccountName)
val expected = updatedAccount.right()
Truth.assertThat(actual).isEqualTo(expected)
val updatedAccountList = (accountList + updatedAccount).getOrNull()!!
coVerifyOrder {
crudRepository.getAccounts(userWalletId = userWalletId)
crudRepository.saveAccounts(accountList = updatedAccountList)
@ -71,20 +66,15 @@ class UpdateCryptoPortfolioUseCaseTest {
@Test
fun `invoke should update crypto portfolio account with new icon`() = runTest {
// Arrange
val accountId = AccountId(value = "test-account-id", userWalletId = mockk())
val userWalletId = accountId.userWalletId
val account = createAccount(accountId = accountId, isMain = true)
val accountList = AccountList(
userWallet = mockk(),
accounts = setOf(account),
totalAccounts = 1,
)
.getOrNull()!!
val accountList = AccountList.createEmpty(userWallet = userWallet)
val accountId = accountList.mainAccount.accountId
val newAccountIcon = CryptoPortfolioIcon.ofCustomAccount(
value = CryptoPortfolioIcon.Icon.Star,
color = CryptoPortfolioIcon.Color.CaribbeanBlue,
)
val updatedAccount = accountList.mainAccount.copy(accountIcon = newAccountIcon)
val updatedAccountList = (accountList + updatedAccount).getOrNull()!!
coEvery { crudRepository.getAccounts(userWalletId = userWalletId) } returns accountList.toOption()
@ -92,11 +82,9 @@ class UpdateCryptoPortfolioUseCaseTest {
val actual = useCase(accountId = accountId, icon = newAccountIcon)
// Assert
val updatedAccount = account.copy(accountIcon = newAccountIcon)
val expected = updatedAccount.right()
Truth.assertThat(actual).isEqualTo(expected)
val updatedAccountList = (accountList + updatedAccount).getOrNull()!!
coVerifyOrder {
crudRepository.getAccounts(userWalletId = userWalletId)
crudRepository.saveAccounts(accountList = updatedAccountList)
@ -106,21 +94,16 @@ class UpdateCryptoPortfolioUseCaseTest {
@Test
fun `invoke should update crypto portfolio account with new name and icon`() = runTest {
// Arrange
val accountId = AccountId(value = "test-account-id", userWalletId = mockk())
val userWalletId = accountId.userWalletId
val account = createAccount(accountId = accountId, isMain = true)
val accountList = AccountList(
userWallet = mockk(),
accounts = setOf(account),
totalAccounts = 1,
)
.getOrNull()!!
val accountList = AccountList.createEmpty(userWallet = userWallet)
val accountId = accountList.mainAccount.accountId
val newAccountName = AccountName("New name").getOrNull()!!
val newAccountIcon = CryptoPortfolioIcon.ofCustomAccount(
value = CryptoPortfolioIcon.Icon.Star,
color = CryptoPortfolioIcon.Color.CaribbeanBlue,
)
val updatedAccount = accountList.mainAccount.copy(accountName = newAccountName, accountIcon = newAccountIcon)
val updatedAccountList = (accountList + updatedAccount).getOrNull()!!
coEvery { crudRepository.getAccounts(userWalletId = userWalletId) } returns accountList.toOption()
@ -128,11 +111,9 @@ class UpdateCryptoPortfolioUseCaseTest {
val actual = useCase(accountId = accountId, accountName = newAccountName, icon = newAccountIcon)
// Assert
val updatedAccount = account.copy(accountName = newAccountName, accountIcon = newAccountIcon)
val expected = updatedAccount.right()
Truth.assertThat(actual).isEqualTo(expected)
val updatedAccountList = (accountList + updatedAccount).getOrNull()!!
coVerifyOrder {
crudRepository.getAccounts(userWalletId = userWalletId)
crudRepository.saveAccounts(accountList = updatedAccountList)
@ -142,15 +123,8 @@ class UpdateCryptoPortfolioUseCaseTest {
@Test
fun `invoke if name and icon are null`() = runTest {
// Arrange
val accountId = AccountId(value = "test-account-id", userWalletId = mockk())
val userWalletId = accountId.userWalletId
val account = createAccount(accountId = accountId, isMain = true)
val accountList = AccountList(
userWallet = mockk(),
accounts = setOf(account),
totalAccounts = 1,
)
.getOrNull()!!
val accountList = AccountList.createEmpty(userWallet = userWallet)
val accountId = accountList.mainAccount.accountId
coEvery { crudRepository.getAccounts(userWalletId = userWalletId) } returns accountList.toOption()
@ -170,10 +144,11 @@ class UpdateCryptoPortfolioUseCaseTest {
@Test
fun `invoke if getAccounts throws exception`() = runTest {
// Arrange
val accountId = AccountId(value = "test-account-id", userWalletId = mockk())
val userWalletId = accountId.userWalletId
val accountList = AccountList.createEmpty(userWallet = userWallet)
val accountId = accountList.mainAccount.accountId
val newAccountName = AccountName("New name").getOrNull()!!
val exception = IllegalStateException("Test exception")
coEvery { crudRepository.getAccounts(userWalletId = userWalletId) } throws exception
@ -192,8 +167,10 @@ class UpdateCryptoPortfolioUseCaseTest {
@Test
fun `invoke if getAccounts returns None`() = runTest {
// Arrange
val accountId = AccountId(value = "test-account-id", userWalletId = mockk())
val userWalletId = accountId.userWalletId
val accountId = AccountId.forCryptoPortfolio(
userWalletId = userWalletId,
derivationIndex = DerivationIndex.Main,
)
val accountList = None
val newAccountName = AccountName("New name").getOrNull()!!
@ -214,18 +191,11 @@ class UpdateCryptoPortfolioUseCaseTest {
@Test
fun `invoke if getAccounts does not contain accountId`() = runTest {
// Arrange
val accountId = AccountId(value = "test-account-id", userWalletId = mockk())
val userWalletId = accountId.userWalletId
val account = createAccount(
accountId = AccountId(value = "another-account-id", userWalletId = mockk()),
isMain = true,
val accountList = AccountList.createEmpty(userWallet = userWallet)
val accountId = AccountId.forCryptoPortfolio(
userWalletId = userWalletId,
derivationIndex = DerivationIndex(1).getOrNull()!!,
)
val accountList = AccountList(
userWallet = mockk(),
accounts = setOf(account),
totalAccounts = 1,
)
.getOrNull()!!
val newAccountName = AccountName("New name").getOrNull()!!
@ -245,17 +215,11 @@ class UpdateCryptoPortfolioUseCaseTest {
@Test
fun `invoke if saveAccounts throws exception`() = runTest {
// Arrange
val accountId = AccountId(value = "test-account-id", userWalletId = mockk())
val userWalletId = accountId.userWalletId
val account = createAccount(accountId = accountId, isMain = true)
val accountList = AccountList(
userWallet = mockk(),
accounts = setOf(account),
totalAccounts = 1,
).getOrNull()!!
val accountList = AccountList.createEmpty(userWallet = userWallet)
val accountId = accountList.mainAccount.accountId
val newAccountName = AccountName("New name").getOrNull()!!
val updatedAccount = account.copy(accountName = newAccountName)
val updatedAccount = accountList.mainAccount.copy(accountName = newAccountName)
val updatedAccountList = (accountList + updatedAccount).getOrNull()!!
val exception = IllegalStateException("Save failed")
@ -276,23 +240,8 @@ class UpdateCryptoPortfolioUseCaseTest {
}
}
private fun createAccount(
accountId: AccountId = AccountId(value = randomAccountId(length = 5), userWalletId = mockk()),
accountIcon: CryptoPortfolioIcon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
isMain: Boolean,
): Account.CryptoPortfolio {
return Account.CryptoPortfolio(
accountId = accountId,
name = "Test Account",
accountIcon = accountIcon,
derivationIndex = if (isMain) 0 else Random.nextInt(1, 21),
isArchived = false,
cryptoCurrencyList = Account.CryptoPortfolio.CryptoCurrencyList(
currencies = emptySet(),
sortType = TokensSortType.NONE,
groupType = TokensGroupType.NONE,
),
)
.getOrNull()!!
private companion object {
val userWalletId = UserWalletId("011")
}
}

View file

@ -1,8 +1,41 @@
package com.tangem.domain.account.utils
fun randomAccountId(length: Int): String {
val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
return (1..length)
.map { chars.random() }
.joinToString("")
import com.tangem.domain.models.TokensGroupType
import com.tangem.domain.models.TokensSortType
import com.tangem.domain.models.account.*
import com.tangem.domain.models.wallet.UserWalletId
import kotlin.random.Random
fun createAccounts(userWalletId: UserWalletId, count: Int): Set<Account.CryptoPortfolio> {
return buildSet {
add(Account.CryptoPortfolio.createMainAccount(userWalletId))
repeat(count - 1) {
val account = createAccount(userWalletId = userWalletId, derivationIndex = it + 1)
add(account)
}
}
}
fun createAccount(
userWalletId: UserWalletId,
name: String = "Test Account",
icon: CryptoPortfolioIcon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
derivationIndex: Int = Random.nextInt(1, 21),
): Account.CryptoPortfolio {
val derivationIndex = DerivationIndex(derivationIndex).getOrNull()!!
return Account.CryptoPortfolio(
accountId = AccountId.forCryptoPortfolio(userWalletId = userWalletId, derivationIndex = derivationIndex),
accountName = AccountName(name).getOrNull()!!,
accountIcon = icon,
derivationIndex = derivationIndex,
isArchived = false,
cryptoCurrencyList = Account.CryptoPortfolio.CryptoCurrencyList(
currencies = emptySet(),
sortType = TokensSortType.NONE,
groupType = TokensGroupType.NONE,
),
)
}