Updated on 2026-08-14

This commit is contained in:
Tangem 2025-11-19 14:54:40 +04:00
parent f9ae6c2519
commit 96154e6983
11 changed files with 262 additions and 165 deletions

View file

@ -18,6 +18,9 @@ dependencies {
implementation(deps.kotlin.coroutines) implementation(deps.kotlin.coroutines)
implementation(deps.kotlin.serialization) implementation(deps.kotlin.serialization)
// region Test libraries
testImplementation(projects.test.core) testImplementation(projects.test.core)
testImplementation(projects.test.mock)
testRuntimeOnly(deps.test.junit5.engine) testRuntimeOnly(deps.test.junit5.engine)
// endregion
} }

View file

@ -13,11 +13,11 @@ import com.tangem.utils.extensions.addOrReplace
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
/** /**
* Represents a list of accounts associated with a user wallet * Represents a list of accounts associated with a user wallet ID.
* *
* @property userWalletId the user wallet id associated with the account list * @property userWalletId the user wallet id associated with the account list
* @property accounts a list of accounts belonging to the user wallet * @property accounts a list of accounts belonging to the user wallet
* @property totalAccounts the total number of accounts * @property totalAccounts the total number of accounts (including archived ones)
* @property sortType the sorting type applied to the accounts * @property sortType the sorting type applied to the accounts
* @property groupType the grouping type applied to the accounts * @property groupType the grouping type applied to the accounts
* *
@ -142,6 +142,11 @@ data class AccountList private constructor(
data object DuplicateAccountNames : Error { data object DuplicateAccountNames : Error {
override fun toString(): String = "$tag: Account list contains duplicate account names" override fun toString(): String = "$tag: Account list contains duplicate account names"
} }
@Serializable
data object TotalAccountsLessThanActive : Error {
override fun toString(): String = "$tag: Total accounts cannot be less than active accounts"
}
} }
companion object { companion object {
@ -180,13 +185,17 @@ data class AccountList private constructor(
val uniqueAccountIdsCount = accounts.map { it.accountId.value }.distinct().size val uniqueAccountIdsCount = accounts.map { it.accountId.value }.distinct().size
ensure(accounts.size == uniqueAccountIdsCount) { Error.DuplicateAccountIds } ensure(accounts.size == uniqueAccountIdsCount) { Error.DuplicateAccountIds }
val customNames = accounts.mapNotNull { (it.accountName as? AccountName.Custom)?.value } val customNames = accounts.map { (it.accountName as? AccountName.Custom)?.value }
val uniqueCustomNameCount = customNames.distinct().size val uniqueCustomNameCount = customNames.distinct().size
ensure(customNames.size == uniqueCustomNameCount) { ensure(customNames.size == uniqueCustomNameCount) {
Error.DuplicateAccountNames Error.DuplicateAccountNames
} }
ensure(totalAccounts >= accounts.size) {
Error.TotalAccountsLessThanActive
}
AccountList( AccountList(
userWalletId = userWalletId, userWalletId = userWalletId,
accounts = accounts, accounts = accounts,

View file

@ -2,14 +2,20 @@ package com.tangem.domain.account.models
import arrow.core.Either import arrow.core.Either
import arrow.core.left import arrow.core.left
import arrow.core.right
import com.google.common.truth.Truth import com.google.common.truth.Truth
import com.tangem.domain.account.utils.createAccount import com.tangem.domain.models.TokensGroupType
import com.tangem.domain.account.utils.createAccounts import com.tangem.domain.models.TokensSortType
import com.tangem.domain.models.account.Account import com.tangem.domain.models.account.Account
import com.tangem.domain.models.account.AccountName import com.tangem.domain.models.account.AccountName
import com.tangem.domain.models.account.CryptoPortfolioIcon import com.tangem.domain.models.account.CryptoPortfolioIcon
import com.tangem.domain.models.account.DerivationIndex
import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.test.core.ProvideTestModels import com.tangem.test.core.ProvideTestModels
import com.tangem.test.mock.MockAccounts
import com.tangem.test.mock.MockAccounts.createAccount
import com.tangem.test.mock.MockAccounts.createAccountList
import com.tangem.test.mock.MockAccounts.createAccounts
import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.TestInstance
@ -19,60 +25,49 @@ import org.junit.jupiter.params.ParameterizedTest
[REDACTED_AUTHOR] [REDACTED_AUTHOR]
*/ */
@TestInstance(TestInstance.Lifecycle.PER_CLASS) @TestInstance(TestInstance.Lifecycle.PER_CLASS)
class AccountListTest { internal class AccountListTest {
@Test @Test
fun mainAccount() { fun mainAccount() {
// Arrange
val mainAccount = Account.CryptoPortfolio.createMainAccount(userWalletId = userWalletId)
val accountList = AccountList(
userWalletId = userWalletId,
accounts = listOf(mainAccount),
totalAccounts = 1,
)
.getOrNull()!!
// Act // Act
val actual = accountList.mainAccount val actual = MockAccounts.onlyMainAccount.mainAccount
// Assert // Assert
val expected = mainAccount val expected = Account.CryptoPortfolio.createMainAccount(userWalletId = userWalletId)
Truth.assertThat(actual).isEqualTo(expected) Truth.assertThat(actual).isEqualTo(expected)
} }
@Test @Test
fun canAddMoreAccounts() { fun canAddMoreAccounts() {
// Arrange // Arrange
val accountList = AccountList( val accountList = createAccountList(activeAccounts = 2)
userWalletId = userWalletId,
accounts = createAccounts(userWalletId = userWalletId, count = 2),
totalAccounts = 2,
).getOrNull()!!
val fullAccountList = AccountList( val fullAccountList = MockAccounts.fullAccountList
userWalletId = userWalletId,
accounts = createAccounts(userWalletId = userWalletId, count = 20),
totalAccounts = 20,
).getOrNull()!!
// Act & Assert // Act & Assert
Truth.assertThat(accountList.canAddMoreAccounts).isTrue() Truth.assertThat(accountList.canAddMoreAccounts).isTrue()
Truth.assertThat(fullAccountList.canAddMoreAccounts).isFalse() Truth.assertThat(fullAccountList.canAddMoreAccounts).isFalse()
} }
@Test
fun activeAccounts() {
// Arrange
val accountList = createAccountList(activeAccounts = 5, totalAccounts = 10)
// Act & Assert
val expected = 5
Truth.assertThat(accountList.activeAccounts).isEqualTo(expected)
}
@Test @Test
fun empty() { fun empty() {
// Act // Act
val actual = AccountList.empty(userWalletId) val actual = AccountList.empty(userWalletId)
// Assert // Assert
val expected = AccountList( val expected = MockAccounts.onlyMainAccount
userWalletId = userWalletId,
accounts = listOf(Account.CryptoPortfolio.createMainAccount(userWalletId = userWalletId)),
totalAccounts = 1,
).getOrNull()!!
// Assert
Truth.assertThat(actual).isEqualTo(expected) Truth.assertThat(actual).isEqualTo(expected)
} }
@ -80,6 +75,33 @@ class AccountListTest {
@TestInstance(TestInstance.Lifecycle.PER_CLASS) @TestInstance(TestInstance.Lifecycle.PER_CLASS)
inner class Create { inner class Create {
@Test
fun `invoke with non default sort and group types`() {
// Arrange
val accounts = createAccounts(count = 5)
val sortType = TokensSortType.BALANCE
val groupType = TokensGroupType.NETWORK
// Act
val actual = AccountList(
userWalletId = userWalletId,
accounts = accounts,
totalAccounts = accounts.size,
sortType = sortType,
groupType = groupType,
)
// Assert
val expected = AccountList(
userWalletId = userWalletId,
accounts = accounts,
totalAccounts = accounts.size,
sortType = sortType,
groupType = groupType,
)
Truth.assertThat(actual).isEqualTo(expected)
}
@ParameterizedTest @ParameterizedTest
@ProvideTestModels @ProvideTestModels
fun invoke(model: CreateTestModel) { fun invoke(model: CreateTestModel) {
@ -87,7 +109,7 @@ class AccountListTest {
val actual = AccountList( val actual = AccountList(
userWalletId = userWalletId, userWalletId = userWalletId,
accounts = model.accounts, accounts = model.accounts,
totalAccounts = model.accounts.size, totalAccounts = model.totalAccounts,
) )
// Assert // Assert
@ -99,9 +121,13 @@ class AccountListTest {
accounts = emptyList(), accounts = emptyList(),
expected = AccountList.Error.EmptyAccountsList.left(), expected = AccountList.Error.EmptyAccountsList.left(),
), ),
CreateTestModel(
accounts = createAccounts(count = 21),
expected = AccountList.Error.ExceedsMaxAccountsCount.left(),
),
CreateTestModel( CreateTestModel(
accounts = listOf( accounts = listOf(
createAccount(userWalletId = userWalletId, derivationIndex = 1), createAccount(derivationIndex = 1),
), ),
expected = AccountList.Error.MainAccountNotFound.left(), expected = AccountList.Error.MainAccountNotFound.left(),
), ),
@ -114,42 +140,44 @@ class AccountListTest {
), ),
expected = AccountList.Error.ExceedsMaxMainAccountsCount.left(), expected = AccountList.Error.ExceedsMaxMainAccountsCount.left(),
), ),
createAccounts(userWalletId = userWalletId, count = 1).let {
CreateTestModel(
accounts = it,
expected = AccountList(userWalletId = userWalletId, accounts = it, totalAccounts = 1),
)
},
createAccounts(userWalletId = userWalletId, count = 20).let {
CreateTestModel(
accounts = it,
expected = AccountList(userWalletId = userWalletId, accounts = it, totalAccounts = 20),
)
},
CreateTestModel(
accounts = createAccounts(userWalletId = userWalletId, count = 21),
expected = AccountList.Error.ExceedsMaxAccountsCount.left(),
),
CreateTestModel( CreateTestModel(
accounts = listOf( accounts = listOf(
createAccount(userWalletId = userWalletId, derivationIndex = 0), createAccount(derivationIndex = 0),
createAccount(userWalletId = userWalletId, derivationIndex = 1), createAccount(derivationIndex = 1),
createAccount(userWalletId = userWalletId, derivationIndex = 1), createAccount(derivationIndex = 1),
), ),
expected = AccountList.Error.DuplicateAccountIds.left(), expected = AccountList.Error.DuplicateAccountIds.left(),
), ),
CreateTestModel( CreateTestModel(
accounts = listOf( accounts = listOf(
createAccount(userWalletId = userWalletId, name = "Name", derivationIndex = 0), createAccount(name = "Name", derivationIndex = 0),
createAccount(userWalletId = userWalletId, name = "Name", derivationIndex = 1), createAccount(name = "Name", derivationIndex = 1),
), ),
expected = AccountList.Error.DuplicateAccountNames.left(), expected = AccountList.Error.DuplicateAccountNames.left(),
), ),
CreateTestModel(
accounts = createAccounts(count = 2),
totalAccounts = 1,
expected = AccountList.Error.TotalAccountsLessThanActive.left(),
),
createAccountList(activeAccounts = 1).let {
CreateTestModel(
accounts = it.accounts,
expected = it.right(),
)
},
createAccountList(activeAccounts = 20).let {
CreateTestModel(
accounts = it.accounts,
expected = it.right(),
)
},
) )
} }
data class CreateTestModel( data class CreateTestModel(
val accounts: List<Account>, val accounts: List<Account>,
val totalAccounts: Int = accounts.size,
val expected: Either<AccountList.Error, AccountList>, val expected: Either<AccountList.Error, AccountList>,
) )
@ -171,7 +199,7 @@ class AccountListTest {
// region Add new account // region Add new account
run { run {
val mainAccount = Account.CryptoPortfolio.createMainAccount(userWalletId) val mainAccount = Account.CryptoPortfolio.createMainAccount(userWalletId)
val newAccount = createAccount(userWalletId = userWalletId, derivationIndex = 1) val newAccount = createAccount(derivationIndex = 1)
PlusTestModel( PlusTestModel(
initial = AccountList( initial = AccountList(
@ -208,15 +236,71 @@ class AccountListTest {
) )
}, },
// endregion // endregion
// region MainAccountNotFound
run {
val mainAccount = Account.CryptoPortfolio.createMainAccount(userWalletId)
val newAccount = Account.CryptoPortfolio(
accountId = mainAccount.accountId,
accountName = mainAccount.accountName,
derivationIndex = DerivationIndex(1).getOrNull()!!,
icon = mainAccount.icon,
cryptoCurrencies = mainAccount.cryptoCurrencies,
)
PlusTestModel(
initial = AccountList(
userWalletId = userWalletId,
accounts = listOf(mainAccount),
totalAccounts = 1,
).getOrNull()!!,
toAdd = newAccount,
expected = AccountList.Error.MainAccountNotFound.left(),
)
},
// endregion
// region ExceedsMaxMainAccountsCount
run {
val mainAccount = Account.CryptoPortfolio.createMainAccount(userWalletId)
val newAccount = Account.CryptoPortfolio.createMainAccount(UserWalletId("012"))
PlusTestModel(
initial = AccountList(
userWalletId = userWalletId,
accounts = listOf(mainAccount),
totalAccounts = 1,
).getOrNull()!!,
toAdd = newAccount,
expected = AccountList.Error.ExceedsMaxMainAccountsCount.left(),
)
},
// endregion
// region DuplicateAccountNames
run {
val mainAccount = Account.CryptoPortfolio.createMainAccount(userWalletId)
val newAccount = createAccount(derivationIndex = 1).copy(accountName = mainAccount.accountName)
PlusTestModel(
initial = AccountList(
userWalletId = userWalletId,
accounts = listOf(mainAccount),
totalAccounts = 1,
).getOrNull()!!,
toAdd = newAccount,
expected = AccountList.Error.DuplicateAccountNames.left(),
)
},
// endregion
// region ExceedsMaxAccountsCount
PlusTestModel( PlusTestModel(
initial = AccountList( initial = AccountList(
userWalletId = userWalletId, userWalletId = userWalletId,
accounts = createAccounts(userWalletId = userWalletId, count = 20), accounts = createAccounts(count = 20),
totalAccounts = 20, totalAccounts = 20,
).getOrNull()!!, ).getOrNull()!!,
toAdd = createAccount(userWalletId = userWalletId, derivationIndex = 21), toAdd = createAccount(derivationIndex = 21),
expected = AccountList.Error.ExceedsMaxAccountsCount.left(), expected = AccountList.Error.ExceedsMaxAccountsCount.left(),
), ),
// endregion
) )
} }
@ -244,7 +328,7 @@ class AccountListTest {
// region Remove existing account // region Remove existing account
run { run {
val mainAccount = Account.CryptoPortfolio.createMainAccount(userWalletId) val mainAccount = Account.CryptoPortfolio.createMainAccount(userWalletId)
val secondaryAccount = createAccount(userWalletId = userWalletId, derivationIndex = 2) val secondaryAccount = createAccount(derivationIndex = 2)
MinusTestModel( MinusTestModel(
initial = AccountList( initial = AccountList(
@ -264,20 +348,18 @@ class AccountListTest {
// region Remove unexisting account // region Remove unexisting account
run { run {
val mainAccount = Account.CryptoPortfolio.createMainAccount(userWalletId) val mainAccount = Account.CryptoPortfolio.createMainAccount(userWalletId)
val notInList = createAccount(userWalletId = userWalletId, derivationIndex = 3) val notInList = createAccount(derivationIndex = 3)
val accountList = AccountList(
userWalletId = userWalletId,
accounts = listOf(mainAccount),
totalAccounts = 1,
)
MinusTestModel( MinusTestModel(
initial = AccountList( initial = accountList.getOrNull()!!,
userWalletId = userWalletId,
accounts = listOf(mainAccount),
totalAccounts = 1,
).getOrNull()!!,
toRemove = notInList, toRemove = notInList,
expected = AccountList( expected = accountList,
userWalletId = userWalletId,
accounts = listOf(mainAccount),
totalAccounts = 1,
),
) )
}, },
// endregion // endregion
@ -299,7 +381,7 @@ class AccountListTest {
// region MainAccountNotFound // region MainAccountNotFound
run { run {
val mainAccount = Account.CryptoPortfolio.createMainAccount(userWalletId) val mainAccount = Account.CryptoPortfolio.createMainAccount(userWalletId)
val secondaryAccount = createAccount(userWalletId = userWalletId, derivationIndex = 2) val secondaryAccount = createAccount(derivationIndex = 2)
MinusTestModel( MinusTestModel(
initial = AccountList( initial = AccountList(
@ -323,6 +405,6 @@ class AccountListTest {
private companion object { private companion object {
val userWalletId = UserWalletId("011") val userWalletId = MockAccounts.userWalletId
} }
} }

View file

@ -10,11 +10,8 @@ import com.tangem.domain.account.models.AccountList
import com.tangem.domain.account.repository.AccountsCRUDRepository import com.tangem.domain.account.repository.AccountsCRUDRepository
import com.tangem.domain.account.tokens.MainAccountTokensMigration import com.tangem.domain.account.tokens.MainAccountTokensMigration
import com.tangem.domain.account.usecase.AddCryptoPortfolioUseCase.Error import com.tangem.domain.account.usecase.AddCryptoPortfolioUseCase.Error
import com.tangem.domain.account.utils.createAccount import com.tangem.test.mock.MockAccounts
import com.tangem.domain.account.utils.createAccounts import com.tangem.test.mock.MockAccounts.createAccount
import com.tangem.domain.models.account.Account
import com.tangem.domain.models.account.CryptoPortfolioIcon
import com.tangem.domain.models.wallet.UserWalletId
import io.mockk.* import io.mockk.*
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.BeforeEach
@ -42,7 +39,7 @@ class AddCryptoPortfolioUseCaseTest {
@Test @Test
fun `invoke should add new crypto portfolio account to existing list`() = runTest { fun `invoke should add new crypto portfolio account to existing list`() = runTest {
// Arrange // Arrange
val newAccount = createNewAccount() val newAccount = createAccount(derivationIndex = 1)
val accountList = AccountList.empty(userWalletId) val accountList = AccountList.empty(userWalletId)
val updatedAccountList = (accountList + newAccount).getOrNull()!! val updatedAccountList = (accountList + newAccount).getOrNull()!!
@ -78,7 +75,7 @@ class AddCryptoPortfolioUseCaseTest {
@Test @Test
fun `invoke should return error if fetch is failed`() = runTest { fun `invoke should return error if fetch is failed`() = runTest {
// Arrange // Arrange
val newAccount = createNewAccount() val newAccount = createAccount(derivationIndex = 1)
val exception = Exception("Fetch error") val exception = Exception("Fetch error")
coEvery { coEvery {
@ -113,7 +110,7 @@ class AddCryptoPortfolioUseCaseTest {
@Test @Test
fun `invoke should return error if account list none exists`() = runTest { fun `invoke should return error if account list none exists`() = runTest {
// Arrange // Arrange
val newAccount = createNewAccount() val newAccount = createAccount(derivationIndex = 1)
coEvery { coEvery {
singleAccountListFetcher(SingleAccountListFetcher.Params(userWalletId)) singleAccountListFetcher(SingleAccountListFetcher.Params(userWalletId))
@ -147,13 +144,8 @@ class AddCryptoPortfolioUseCaseTest {
@Test @Test
fun `invoke should return error if account list requirements not met`() = runTest { fun `invoke should return error if account list requirements not met`() = runTest {
// Arrange // Arrange
val accountList = AccountList( val accountList = MockAccounts.fullAccountList
userWalletId = userWalletId, val newAccount = createAccount(derivationIndex = 21)
accounts = createAccounts(userWalletId = userWalletId, count = 20),
totalAccounts = 20,
).getOrNull()!!
val newAccount = createNewAccount(derivationIndex = 21)
coEvery { coEvery {
singleAccountListFetcher(SingleAccountListFetcher.Params(userWalletId)) singleAccountListFetcher(SingleAccountListFetcher.Params(userWalletId))
@ -190,7 +182,7 @@ class AddCryptoPortfolioUseCaseTest {
@Test @Test
fun `invoke should return error if getAccounts throws exception`() = runTest { fun `invoke should return error if getAccounts throws exception`() = runTest {
// Arrange // Arrange
val newAccount = createNewAccount() val newAccount = createAccount(derivationIndex = 1)
val exception = IllegalStateException("Test error") val exception = IllegalStateException("Test error")
coEvery { coEvery {
@ -224,7 +216,7 @@ class AddCryptoPortfolioUseCaseTest {
@Test @Test
fun `invoke should return error if saveAccounts throws exception`() = runTest { fun `invoke should return error if saveAccounts throws exception`() = runTest {
// Arrange // Arrange
val newAccount = createNewAccount() val newAccount = createAccount(derivationIndex = 1)
val accountList = AccountList.empty(userWalletId) val accountList = AccountList.empty(userWalletId)
val updatedAccountList = (accountList + newAccount).getOrNull()!! val updatedAccountList = (accountList + newAccount).getOrNull()!!
@ -263,7 +255,7 @@ class AddCryptoPortfolioUseCaseTest {
@Test @Test
fun `invoke should return new account if migrate returns error`() = runTest { fun `invoke should return new account if migrate returns error`() = runTest {
// Arrange // Arrange
val newAccount = createNewAccount() val newAccount = createAccount(derivationIndex = 1)
val accountList = AccountList.empty(userWalletId) val accountList = AccountList.empty(userWalletId)
val updatedAccountList = (accountList + newAccount).getOrNull()!! val updatedAccountList = (accountList + newAccount).getOrNull()!!
@ -299,15 +291,6 @@ class AddCryptoPortfolioUseCaseTest {
private companion object { private companion object {
val userWalletId = UserWalletId("011") val userWalletId = MockAccounts.userWalletId
fun createNewAccount(derivationIndex: Int = 1): Account.CryptoPortfolio {
return createAccount(
userWalletId = userWalletId,
name = "New Account",
icon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
derivationIndex = derivationIndex,
)
}
} }
} }

View file

@ -7,11 +7,9 @@ import com.google.common.truth.Truth
import com.tangem.domain.account.models.AccountList import com.tangem.domain.account.models.AccountList
import com.tangem.domain.account.repository.AccountsCRUDRepository import com.tangem.domain.account.repository.AccountsCRUDRepository
import com.tangem.domain.account.usecase.ApplyAccountListSortingUseCase.Error import com.tangem.domain.account.usecase.ApplyAccountListSortingUseCase.Error
import com.tangem.domain.models.account.Account
import com.tangem.domain.models.account.AccountId import com.tangem.domain.models.account.AccountId
import com.tangem.domain.models.account.CryptoPortfolioIcon
import com.tangem.domain.models.account.DerivationIndex
import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.test.mock.MockAccounts
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
import io.mockk.* import io.mockk.*
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
@ -71,8 +69,7 @@ class ApplyAccountListSortingUseCaseTest {
@Test @Test
fun `invoke returns DataOperationFailed when getAccountList returns error`() = runTest { fun `invoke returns DataOperationFailed when getAccountList returns error`() = runTest {
// Arrange // Arrange
val accountList = createAccountList() val accountIds = defaultAccountList.toAccountIds()
val accountIds = accountList.toAccountIds()
val exception = Exception("Test error") val exception = Exception("Test error")
coEvery { accountsCRUDRepository.getAccountListSync(userWalletId) } throws exception coEvery { accountsCRUDRepository.getAccountListSync(userWalletId) } throws exception
@ -91,7 +88,7 @@ class ApplyAccountListSortingUseCaseTest {
@Test @Test
fun `invoke returns UnableToSortSingleAccount when saved accountList contain one account`() = runTest { fun `invoke returns UnableToSortSingleAccount when saved accountList contain one account`() = runTest {
// Arrange // Arrange
val accountIds = createAccountList().toAccountIds() val accountIds = defaultAccountList.toAccountIds()
coEvery { coEvery {
accountsCRUDRepository.getAccountListSync(userWalletId) accountsCRUDRepository.getAccountListSync(userWalletId)
@ -115,7 +112,7 @@ class ApplyAccountListSortingUseCaseTest {
userWalletId = UserWalletId("012"), userWalletId = UserWalletId("012"),
) )
val accountList = createAccountList() val accountList = defaultAccountList
val accountIds = listOf(accountList.mainAccount.accountId, unknownAccountId) val accountIds = listOf(accountList.mainAccount.accountId, unknownAccountId)
coEvery { accountsCRUDRepository.getAccountListSync(userWalletId) } returns accountList.some() coEvery { accountsCRUDRepository.getAccountListSync(userWalletId) } returns accountList.some()
@ -134,7 +131,7 @@ class ApplyAccountListSortingUseCaseTest {
@Test @Test
fun `invoke returns Right without accounts saving when nothing to change`() = runTest { fun `invoke returns Right without accounts saving when nothing to change`() = runTest {
// Arrange // Arrange
val accountList = createAccountList() val accountList = defaultAccountList
val accountIds = accountList.toAccountIds() val accountIds = accountList.toAccountIds()
coEvery { accountsCRUDRepository.getAccountListSync(userWalletId) } returns accountList.some() coEvery { accountsCRUDRepository.getAccountListSync(userWalletId) } returns accountList.some()
@ -153,7 +150,7 @@ class ApplyAccountListSortingUseCaseTest {
@Test @Test
fun `invoke returns Right`() = runTest { fun `invoke returns Right`() = runTest {
// Arrange // Arrange
val accountList = createAccountList() val accountList = defaultAccountList
val accountIds = accountList.toAccountIds().reversed() val accountIds = accountList.toAccountIds().reversed()
val updatedAccountList = AccountList( val updatedAccountList = AccountList(
@ -179,21 +176,12 @@ class ApplyAccountListSortingUseCaseTest {
} }
} }
private fun createAccountList(): AccountList {
val accountList = AccountList.empty(userWalletId)
val account1 = Account.CryptoPortfolio(
accountId = AccountId.forCryptoPortfolio(userWalletId, DerivationIndex(1).getOrNull()!!),
name = "Account 1",
icon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
derivationIndex = 1,
)
.getOrNull()!!
return (accountList + account1).getOrNull()!!
}
private fun AccountList.toAccountIds(): List<AccountId> { private fun AccountList.toAccountIds(): List<AccountId> {
return this.accounts.map { it.accountId } return this.accounts.map { it.accountId }
} }
private companion object {
val defaultAccountList = MockAccounts.createAccountList(activeAccounts = 2)
}
} }

View file

@ -8,10 +8,10 @@ import com.google.common.truth.Truth
import com.tangem.domain.account.models.AccountList import com.tangem.domain.account.models.AccountList
import com.tangem.domain.account.repository.AccountsCRUDRepository import com.tangem.domain.account.repository.AccountsCRUDRepository
import com.tangem.domain.account.usecase.ArchiveCryptoPortfolioUseCase.Error import com.tangem.domain.account.usecase.ArchiveCryptoPortfolioUseCase.Error
import com.tangem.domain.account.utils.createAccount
import com.tangem.domain.models.account.AccountId import com.tangem.domain.models.account.AccountId
import com.tangem.domain.models.account.DerivationIndex import com.tangem.domain.models.account.DerivationIndex
import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.test.mock.MockAccounts.createAccount
import io.mockk.* import io.mockk.*
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.BeforeEach
@ -32,7 +32,7 @@ class ArchiveCryptoPortfolioUseCaseTest {
@Test @Test
fun `invoke should archive existing crypto portfolio account`() = runTest { fun `invoke should archive existing crypto portfolio account`() = runTest {
// Arrange // Arrange
val account = createAccount(userWalletId) val account = createAccount(derivationIndex = 1)
val accountList = (AccountList.empty(userWalletId) + account).getOrNull()!! val accountList = (AccountList.empty(userWalletId) + account).getOrNull()!!
val accountId = account.accountId val accountId = account.accountId
@ -122,7 +122,7 @@ class ArchiveCryptoPortfolioUseCaseTest {
@Test @Test
fun `invoke should return error if saveAccounts throws exception`() = runTest { fun `invoke should return error if saveAccounts throws exception`() = runTest {
// Arrange // Arrange
val account = createAccount(userWalletId) val account = createAccount(derivationIndex = 1)
val accountList = (AccountList.empty(userWalletId) + account).getOrNull()!! val accountList = (AccountList.empty(userWalletId) + account).getOrNull()!!
val accountId = account.accountId val accountId = account.accountId

View file

@ -1,38 +0,0 @@
package com.tangem.domain.account.utils
import com.tangem.domain.models.account.*
import com.tangem.domain.models.wallet.UserWalletId
import kotlin.random.Random
fun createAccounts(userWalletId: UserWalletId, count: Int): List<Account.CryptoPortfolio> {
return buildList {
add(Account.CryptoPortfolio.createMainAccount(userWalletId))
repeat(count - 1) {
val account = createAccount(
userWalletId = userWalletId,
name = "Test Account ${it + 1}",
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()!!,
icon = icon,
derivationIndex = derivationIndex,
cryptoCurrencies = emptySet(),
)
}

View file

@ -150,6 +150,7 @@ include(":app")
include(":plugins:detekt-rules") include(":plugins:detekt-rules")
include(":test:core") include(":test:core")
include(":test:mock")
// region Core modules // region Core modules
include(":core:analytics") include(":core:analytics")

1
test/mock/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/build

View file

@ -0,0 +1,8 @@
plugins {
alias(deps.plugins.kotlin.jvm)
id("configuration")
}
dependencies {
implementation(projects.domain.account)
}

View file

@ -0,0 +1,60 @@
package com.tangem.test.mock
import com.tangem.domain.account.models.AccountList
import com.tangem.domain.models.account.*
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWalletId
/**
[REDACTED_AUTHOR]
*/
object MockAccounts {
val userWalletId = UserWalletId("011")
val onlyMainAccount = createAccountList(activeAccounts = 1)
val fullAccountList = createAccountList(activeAccounts = 20)
fun createAccountList(
activeAccounts: Int,
totalAccounts: Int = activeAccounts,
userWalletId: UserWalletId = this.userWalletId,
): AccountList {
return AccountList(
userWalletId = userWalletId,
accounts = createAccounts(count = activeAccounts, userWalletId = userWalletId),
totalAccounts = totalAccounts,
).getOrNull()!!
}
fun createAccounts(count: Int, userWalletId: UserWalletId = this.userWalletId): List<Account.CryptoPortfolio> {
return buildList {
add(Account.CryptoPortfolio.createMainAccount(userWalletId))
repeat(count - 1) {
val account = createAccount(derivationIndex = it + 1, userWalletId = userWalletId)
add(account)
}
}
}
fun createAccount(
derivationIndex: Int,
name: String = "Account #$derivationIndex",
icon: CryptoPortfolioIcon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
cryptoCurrencies: Set<CryptoCurrency> = emptySet(),
userWalletId: UserWalletId = this.userWalletId,
): Account.CryptoPortfolio {
val derivationIndex = DerivationIndex(derivationIndex).getOrNull()!!
return Account.CryptoPortfolio(
accountId = AccountId.forCryptoPortfolio(userWalletId = userWalletId, derivationIndex = derivationIndex),
accountName = AccountName(name).getOrNull()!!,
icon = icon,
derivationIndex = derivationIndex,
cryptoCurrencies = cryptoCurrencies,
)
}
}