Updated on 2026-08-14
This commit is contained in:
parent
49aede77dc
commit
238e955fdd
3 changed files with 180 additions and 2 deletions
|
|
@ -24,7 +24,7 @@ import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
|||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TokensListItemUM2
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTokensListUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.isSingleWalletWithToken
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.isSingleCurrency
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -171,7 +171,7 @@ internal class WalletTokensListUMConverter(
|
|||
} else {
|
||||
R.drawable.ic_filter_24
|
||||
}
|
||||
return if (accountList.flattenCurrencies().isNotEmpty() && !selectedWallet.isSingleWalletWithToken()) {
|
||||
return if (accountList.flattenCurrencies().isNotEmpty() && !selectedWallet.isSingleCurrency()) {
|
||||
TangemButtonUM(
|
||||
text = resourceReference(textRes),
|
||||
isEnabled = accountList.totalFiatBalance !is TotalFiatBalance.Loading,
|
||||
|
|
|
|||
|
|
@ -25,4 +25,8 @@ internal fun UserWallet.isSingleWallet(): Boolean {
|
|||
|
||||
internal fun UserWallet.isSingleWalletWithToken(): Boolean {
|
||||
return this is UserWallet.Cold && scanResponse.cardTypesResolver.isSingleWalletWithToken()
|
||||
}
|
||||
|
||||
internal fun UserWallet.isSingleCurrency(): Boolean {
|
||||
return this is UserWallet.Cold && scanResponse.cardTypesResolver.isSingleCurrency()
|
||||
}
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.transformers.converter
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.tangem.domain.account.models.AccountStatusList
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.card.CardTypesResolver
|
||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||
import com.tangem.domain.core.utils.lceError
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.TokensGroupType
|
||||
import com.tangem.domain.models.TokensSortType
|
||||
import com.tangem.domain.models.TotalFiatBalance
|
||||
import com.tangem.domain.models.account.Account.CryptoPortfolio.Companion.createMainAccount
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.network.NetworkAddress
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.models.tokenlist.TokenList
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTokensListUM
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.unmockkStatic
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.params.ParameterizedTest
|
||||
import org.junit.jupiter.params.provider.MethodSource
|
||||
import java.math.BigDecimal
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
internal class WalletTokensListUMConverterTest {
|
||||
|
||||
private val userWalletId = UserWalletId("00")
|
||||
|
||||
@AfterEach
|
||||
fun tearDown() {
|
||||
unmockkStatic(ScanResponse::cardTypesResolver)
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideOrganizeButtonModels")
|
||||
fun `GIVEN wallet type WHEN convert THEN Add and Manage button visibility matches`(model: OrganizeButtonModel) {
|
||||
// Arrange
|
||||
val converter = createConverter(
|
||||
selectedWallet = mockColdWallet(
|
||||
isSingleCurrency = model.isSingleCurrency,
|
||||
isSingleWalletWithToken = model.isSingleWalletWithToken,
|
||||
),
|
||||
)
|
||||
|
||||
// Act
|
||||
val result = converter.convert(value = nonEmptyAccountList()) as WalletTokensListUM.Content
|
||||
|
||||
// Assert
|
||||
assertThat(result.organizeButtonUM != null).isEqualTo(model.expectedButtonShown)
|
||||
}
|
||||
|
||||
private fun createConverter(selectedWallet: UserWallet): WalletTokensListUMConverter = WalletTokensListUMConverter(
|
||||
appCurrency = AppCurrency.Default,
|
||||
selectedWallet = selectedWallet,
|
||||
clickIntents = mockk(relaxed = true),
|
||||
yieldModuleApyMap = emptyMap(),
|
||||
isAccountsModeEnabled = false,
|
||||
expandedAccounts = emptySet(),
|
||||
stakingAvailabilityMap = emptyMap(),
|
||||
isAddAndManageTokensEnabled = true,
|
||||
shouldShowMainPromo = false,
|
||||
)
|
||||
|
||||
private fun mockColdWallet(isSingleCurrency: Boolean, isSingleWalletWithToken: Boolean): UserWallet.Cold {
|
||||
mockkStatic(ScanResponse::cardTypesResolver)
|
||||
val resolver = mockk<CardTypesResolver>(relaxed = true) {
|
||||
every { isSingleCurrency() } returns isSingleCurrency
|
||||
every { isSingleWalletWithToken() } returns isSingleWalletWithToken
|
||||
}
|
||||
val scanResponse = mockk<ScanResponse>()
|
||||
every { scanResponse.cardTypesResolver } returns resolver
|
||||
return mockk<UserWallet.Cold>(relaxed = true) {
|
||||
every { this@mockk.scanResponse } returns scanResponse
|
||||
}
|
||||
}
|
||||
|
||||
private fun nonEmptyAccountList(): AccountStatusList {
|
||||
val tokenList = TokenList.Ungrouped(
|
||||
currencies = listOf(createLoadedStatus(createToken())),
|
||||
totalFiatBalance = TotalFiatBalance.Loaded(BigDecimal.ZERO, StatusSource.ACTUAL),
|
||||
sortedBy = TokensSortType.NONE,
|
||||
)
|
||||
return AccountStatusList(
|
||||
userWalletId = userWalletId,
|
||||
accountStatuses = listOf(
|
||||
AccountStatus.CryptoPortfolio(
|
||||
account = createMainAccount(userWalletId),
|
||||
tokenList = tokenList,
|
||||
priceChangeLce = Unit.lceError(),
|
||||
),
|
||||
),
|
||||
totalAccounts = 1,
|
||||
totalArchivedAccounts = 0,
|
||||
totalFiatBalance = TotalFiatBalance.Loaded(BigDecimal.ZERO, StatusSource.ACTUAL),
|
||||
sortType = TokensSortType.NONE,
|
||||
groupType = TokensGroupType.NONE,
|
||||
)
|
||||
}
|
||||
|
||||
private fun createToken(): CryptoCurrency.Token {
|
||||
val network = Network(
|
||||
id = Network.ID(value = "ethereum", derivationPath = Network.DerivationPath.None),
|
||||
name = "ethereum",
|
||||
currencySymbol = "ETH",
|
||||
derivationPath = Network.DerivationPath.None,
|
||||
isTestnet = false,
|
||||
standardType = Network.StandardType.ERC20,
|
||||
hasFiatFeeRate = false,
|
||||
canHandleTokens = true,
|
||||
transactionExtrasType = Network.TransactionExtrasType.NONE,
|
||||
nameResolvingType = Network.NameResolvingType.NONE,
|
||||
)
|
||||
return CryptoCurrency.Token(
|
||||
id = CryptoCurrency.ID(
|
||||
prefix = CryptoCurrency.ID.Prefix.TOKEN_PREFIX,
|
||||
body = CryptoCurrency.ID.Body.NetworkId(rawId = "ethereum"),
|
||||
suffix = CryptoCurrency.ID.Suffix.ContractAddress(contractAddress = "0xABCDEF"),
|
||||
),
|
||||
network = network,
|
||||
name = "Token",
|
||||
symbol = "TKN",
|
||||
decimals = 18,
|
||||
iconUrl = null,
|
||||
isCustom = false,
|
||||
contractAddress = "0xABCDEF",
|
||||
)
|
||||
}
|
||||
|
||||
private fun createLoadedStatus(token: CryptoCurrency.Token): CryptoCurrencyStatus {
|
||||
val value = CryptoCurrencyStatus.Loaded(
|
||||
amount = BigDecimal.ONE,
|
||||
fiatAmount = BigDecimal.ZERO,
|
||||
fiatRate = BigDecimal.ONE,
|
||||
priceChange = BigDecimal.ZERO,
|
||||
stakingBalance = null,
|
||||
yieldSupplyStatus = null,
|
||||
hasCurrentNetworkTransactions = false,
|
||||
pendingTransactions = emptySet(),
|
||||
networkAddress = NetworkAddress.Single(
|
||||
defaultAddress = NetworkAddress.Address(
|
||||
value = "addr",
|
||||
type = NetworkAddress.Address.Type.Primary,
|
||||
),
|
||||
),
|
||||
sources = CryptoCurrencyStatus.Sources(),
|
||||
)
|
||||
return CryptoCurrencyStatus(currency = token, value = value)
|
||||
}
|
||||
|
||||
internal data class OrganizeButtonModel(
|
||||
val isSingleCurrency: Boolean,
|
||||
val isSingleWalletWithToken: Boolean,
|
||||
val expectedButtonShown: Boolean,
|
||||
)
|
||||
|
||||
private fun provideOrganizeButtonModels() = listOf(
|
||||
// Multi-currency wallet (Wallet / Wallet2) — Add & Manage is shown.
|
||||
OrganizeButtonModel(isSingleCurrency = false, isSingleWalletWithToken = false, expectedButtonShown = true),
|
||||
// Single-currency wallet without token (e.g. S2C) — Add & Manage must be hidden ([REDACTED_TASK_KEY]).
|
||||
OrganizeButtonModel(isSingleCurrency = true, isSingleWalletWithToken = false, expectedButtonShown = false),
|
||||
// Single-currency wallet with token (e.g. NODL) — Add & Manage stays hidden.
|
||||
OrganizeButtonModel(isSingleCurrency = true, isSingleWalletWithToken = true, expectedButtonShown = false),
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue