Updated on 2026-08-14
This commit is contained in:
parent
af8544e6d7
commit
fc6767346c
8 changed files with 693 additions and 10 deletions
|
|
@ -102,7 +102,7 @@ class InitializeWithCryptoCurrencyTransformerTest {
|
|||
assertThat(result.topAppBarUM.menuItems).isEqualTo(state.topAppBarUM.menuItems)
|
||||
assertThat(result.balanceBlockUM.actionButtons).isEqualTo(state.balanceBlockUM.actionButtons)
|
||||
assertThat(result.balanceBlockUM.tokenBalanceTypeUM).isEqualTo(state.balanceBlockUM.tokenBalanceTypeUM)
|
||||
assertThat(result.stakingBlocksState).isEqualTo(state.stakingBlocksState)
|
||||
assertThat(result.earnBlockState).isEqualTo(state.earnBlockState)
|
||||
assertThat(result.pullToRefreshConfig).isSameInstanceAs(state.pullToRefreshConfig)
|
||||
assertThat(result.isBalanceHidden).isEqualTo(state.isBalanceHidden)
|
||||
assertThat(result.isMarketPriceAvailable).isEqualTo(state.isMarketPriceAvailable)
|
||||
|
|
@ -120,8 +120,9 @@ class InitializeWithCryptoCurrencyTransformerTest {
|
|||
tokenBalanceTypeUM = TokenBalanceTypeUM.Single,
|
||||
currencyIconState = mockk(relaxed = true),
|
||||
),
|
||||
notifications = persistentListOf(),
|
||||
marketPriceBlockState = mockk<MarketPriceBlockState>(relaxed = true),
|
||||
stakingBlocksState = null,
|
||||
earnBlockState = null,
|
||||
pullToRefreshConfig = mockk<PullToRefreshConfig>(relaxed = true),
|
||||
isBalanceHidden = false,
|
||||
isMarketPriceAvailable = false,
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ class SetBalanceLoadingTransformerTest {
|
|||
// THEN
|
||||
assertThat(result.topAppBarUM).isSameInstanceAs(state.topAppBarUM)
|
||||
assertThat(result.marketPriceBlockState).isSameInstanceAs(state.marketPriceBlockState)
|
||||
assertThat(result.stakingBlocksState).isEqualTo(state.stakingBlocksState)
|
||||
assertThat(result.earnBlockState).isEqualTo(state.earnBlockState)
|
||||
assertThat(result.pullToRefreshConfig).isSameInstanceAs(state.pullToRefreshConfig)
|
||||
assertThat(result.isBalanceHidden).isEqualTo(state.isBalanceHidden)
|
||||
assertThat(result.isMarketPriceAvailable).isEqualTo(state.isMarketPriceAvailable)
|
||||
|
|
@ -134,8 +134,9 @@ class SetBalanceLoadingTransformerTest {
|
|||
tokenBalanceTypeUM = TokenBalanceTypeUM.Single,
|
||||
currencyIconState = CurrencyIconState.Loading,
|
||||
),
|
||||
notifications = persistentListOf(),
|
||||
marketPriceBlockState = mockk<MarketPriceBlockState>(relaxed = true),
|
||||
stakingBlocksState = null,
|
||||
earnBlockState = null,
|
||||
pullToRefreshConfig = mockk<PullToRefreshConfig>(relaxed = true),
|
||||
isBalanceHidden = false,
|
||||
isMarketPriceAvailable = false,
|
||||
|
|
|
|||
|
|
@ -390,7 +390,7 @@ class SetBalanceTransformerTest {
|
|||
// THEN
|
||||
assertThat(result.topAppBarUM).isSameInstanceAs(state.topAppBarUM)
|
||||
assertThat(result.marketPriceBlockState).isSameInstanceAs(state.marketPriceBlockState)
|
||||
assertThat(result.stakingBlocksState).isEqualTo(state.stakingBlocksState)
|
||||
assertThat(result.earnBlockState).isEqualTo(state.earnBlockState)
|
||||
assertThat(result.pullToRefreshConfig).isSameInstanceAs(state.pullToRefreshConfig)
|
||||
assertThat(result.isBalanceHidden).isEqualTo(state.isBalanceHidden)
|
||||
assertThat(result.isMarketPriceAvailable).isEqualTo(state.isMarketPriceAvailable)
|
||||
|
|
@ -472,8 +472,9 @@ class SetBalanceTransformerTest {
|
|||
tokenBalanceTypeUM = TokenBalanceTypeUM.Single,
|
||||
currencyIconState = CurrencyIconState.Loading,
|
||||
),
|
||||
notifications = persistentListOf(),
|
||||
marketPriceBlockState = mockk<MarketPriceBlockState>(relaxed = true),
|
||||
stakingBlocksState = null,
|
||||
earnBlockState = null,
|
||||
pullToRefreshConfig = mockk<PullToRefreshConfig>(relaxed = true),
|
||||
isBalanceHidden = false,
|
||||
isMarketPriceAvailable = false,
|
||||
|
|
|
|||
|
|
@ -195,8 +195,9 @@ class SetTopBarTitleTransformerTest {
|
|||
menuItems = persistentListOf(),
|
||||
),
|
||||
balanceBlockUM = mockk<TokenDetailsBalanceBlockUM>(relaxed = true),
|
||||
notifications = persistentListOf(),
|
||||
marketPriceBlockState = mockk<MarketPriceBlockState>(relaxed = true),
|
||||
stakingBlocksState = null,
|
||||
earnBlockState = null,
|
||||
pullToRefreshConfig = mockk<PullToRefreshConfig>(relaxed = true),
|
||||
isBalanceHidden = false,
|
||||
isMarketPriceAvailable = false,
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ class ToggleBalanceTypeTransformerTest {
|
|||
// THEN
|
||||
assertThat(result.topAppBarUM).isSameInstanceAs(state.topAppBarUM)
|
||||
assertThat(result.marketPriceBlockState).isSameInstanceAs(state.marketPriceBlockState)
|
||||
assertThat(result.stakingBlocksState).isEqualTo(state.stakingBlocksState)
|
||||
assertThat(result.earnBlockState).isEqualTo(state.earnBlockState)
|
||||
assertThat(result.pullToRefreshConfig).isSameInstanceAs(state.pullToRefreshConfig)
|
||||
assertThat(result.isBalanceHidden).isEqualTo(state.isBalanceHidden)
|
||||
assertThat(result.isMarketPriceAvailable).isEqualTo(state.isMarketPriceAvailable)
|
||||
|
|
@ -194,8 +194,9 @@ class ToggleBalanceTypeTransformerTest {
|
|||
tokenBalanceTypeUM = TokenBalanceTypeUM.Single,
|
||||
currencyIconState = CurrencyIconState.Loading,
|
||||
),
|
||||
notifications = persistentListOf(),
|
||||
marketPriceBlockState = mockk<MarketPriceBlockState>(relaxed = true),
|
||||
stakingBlocksState = null,
|
||||
earnBlockState = null,
|
||||
pullToRefreshConfig = mockk<PullToRefreshConfig>(relaxed = true),
|
||||
isBalanceHidden = false,
|
||||
isMarketPriceAvailable = false,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,540 @@
|
|||
package com.tangem.feature.tokendetails.presentation.tokendetails.state.transformer
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig
|
||||
import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
|
||||
import com.tangem.core.ui.ds.message.TangemMessageEffect
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning
|
||||
import com.tangem.domain.tokens.model.warnings.HederaWarnings
|
||||
import com.tangem.domain.tokens.model.warnings.KaspaWarnings
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsBalanceBlockUM
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsTopAppBarUM
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsTopAppBarUM.TitleState
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsUM
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.math.BigDecimal
|
||||
|
||||
class UpdateNotificationsTransformerTest {
|
||||
|
||||
private val clickIntents: TokenDetailsClickIntents = mockk(relaxed = true)
|
||||
|
||||
// region Mapping warnings to notifications
|
||||
|
||||
@Test
|
||||
fun `GIVEN empty warnings WHEN transform THEN notifications are empty`() {
|
||||
// GIVEN
|
||||
val transformer = createTransformer(warnings = emptySet())
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
|
||||
// THEN
|
||||
assertThat(result.notifications).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN SomeNetworksUnreachable WHEN transform THEN notification with id networks_unreachable is created`() {
|
||||
// GIVEN
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(CryptoCurrencyWarning.SomeNetworksUnreachable),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
|
||||
// THEN
|
||||
assertThat(result.notifications).hasSize(1)
|
||||
assertThat(result.notifications.first().id).isEqualTo("networks_unreachable")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN BalanceNotEnoughForFee WHEN transform THEN notification with id balance_not_enough_for_fee is created`() {
|
||||
// GIVEN
|
||||
val tokenCurrency: CryptoCurrency = mockk(relaxed = true)
|
||||
val coinCurrency: CryptoCurrency = mockk(relaxed = true) {
|
||||
io.mockk.every { network } returns mockk(relaxed = true) {
|
||||
io.mockk.every { name } returns "Ethereum"
|
||||
}
|
||||
io.mockk.every { name } returns "Ethereum"
|
||||
io.mockk.every { symbol } returns "ETH"
|
||||
}
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(
|
||||
CryptoCurrencyWarning.BalanceNotEnoughForFee(
|
||||
tokenCurrency = tokenCurrency,
|
||||
coinCurrency = coinCurrency,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
|
||||
// THEN
|
||||
assertThat(result.notifications).hasSize(1)
|
||||
assertThat(result.notifications.first().id).isEqualTo("balance_not_enough_for_fee")
|
||||
assertThat(result.notifications.first().buttonsUM).hasSize(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN CustomTokenNotEnoughForFee with null feeCurrency WHEN transform THEN notification has no buttons`() {
|
||||
// GIVEN
|
||||
val currency: CryptoCurrency = mockk(relaxed = true)
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(
|
||||
CryptoCurrencyWarning.CustomTokenNotEnoughForFee(
|
||||
currency = currency,
|
||||
feeCurrency = null,
|
||||
networkName = "Ethereum",
|
||||
feeCurrencyName = "Ethereum",
|
||||
feeCurrencySymbol = "ETH",
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
|
||||
// THEN
|
||||
assertThat(result.notifications).hasSize(1)
|
||||
assertThat(result.notifications.first().id).isEqualTo("custom_token_not_enough_for_fee")
|
||||
assertThat(result.notifications.first().buttonsUM).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN BeaconChainShutdown WHEN transform THEN notification with id beacon_chain_shutdown is created`() {
|
||||
// GIVEN
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(CryptoCurrencyWarning.BeaconChainShutdown),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
|
||||
// THEN
|
||||
assertThat(result.notifications).hasSize(1)
|
||||
assertThat(result.notifications.first().id).isEqualTo("beacon_chain_shutdown")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN MigrationMaticToPol WHEN transform THEN notification with id migration_matic_pol is created`() {
|
||||
// GIVEN
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(CryptoCurrencyWarning.MigrationMaticToPol),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
|
||||
// THEN
|
||||
assertThat(result.notifications).hasSize(1)
|
||||
assertThat(result.notifications.first().id).isEqualTo("migration_matic_pol")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN MigrationClore WHEN transform THEN notification has button and id migration_clore`() {
|
||||
// GIVEN
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(CryptoCurrencyWarning.MigrationClore),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
|
||||
// THEN
|
||||
assertThat(result.notifications).hasSize(1)
|
||||
assertThat(result.notifications.first().id).isEqualTo("migration_clore")
|
||||
assertThat(result.notifications.first().buttonsUM).hasSize(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN HederaAssociateWarning WHEN transform THEN notification with button is created`() {
|
||||
// GIVEN
|
||||
val currency: CryptoCurrency = mockk(relaxed = true)
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(HederaWarnings.AssociateWarning(currency = currency)),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
|
||||
// THEN
|
||||
assertThat(result.notifications).hasSize(1)
|
||||
assertThat(result.notifications.first().id).isEqualTo("hedera_associate")
|
||||
assertThat(result.notifications.first().buttonsUM).hasSize(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN HederaAssociateWarningWithFee WHEN transform THEN notification with button is created`() {
|
||||
// GIVEN
|
||||
val currency: CryptoCurrency = mockk(relaxed = true)
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(
|
||||
HederaWarnings.AssociateWarningWithFee(
|
||||
currency = currency,
|
||||
fee = BigDecimal("0.05"),
|
||||
feeCurrencySymbol = "HBAR",
|
||||
feeCurrencyDecimals = 8,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
|
||||
// THEN
|
||||
assertThat(result.notifications).hasSize(1)
|
||||
assertThat(result.notifications.first().id).isEqualTo("hedera_associate_fee")
|
||||
assertThat(result.notifications.first().buttonsUM).hasSize(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN RequiredTrustline WHEN transform THEN notification with button is created`() {
|
||||
// GIVEN
|
||||
val currency: CryptoCurrency = mockk(relaxed = true)
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(
|
||||
CryptoCurrencyWarning.RequiredTrustline(
|
||||
currency = currency,
|
||||
currencySymbol = "XLM",
|
||||
requiredAmount = BigDecimal("10"),
|
||||
currencyDecimals = 7,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
|
||||
// THEN
|
||||
assertThat(result.notifications).hasSize(1)
|
||||
assertThat(result.notifications.first().id).isEqualTo("required_trustline")
|
||||
assertThat(result.notifications.first().buttonsUM).hasSize(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN KaspaIncompleteTransaction WHEN transform THEN notification with button and close is created`() {
|
||||
// GIVEN
|
||||
val currency: CryptoCurrency = mockk(relaxed = true)
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(
|
||||
KaspaWarnings.IncompleteTransaction(
|
||||
currency = currency,
|
||||
amount = BigDecimal("100"),
|
||||
currencySymbol = "KAS",
|
||||
currencyDecimals = 8,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
|
||||
// THEN
|
||||
assertThat(result.notifications).hasSize(1)
|
||||
assertThat(result.notifications.first().id).isEqualTo("kaspa_incomplete")
|
||||
assertThat(result.notifications.first().buttonsUM).hasSize(1)
|
||||
assertThat(result.notifications.first().onCloseClick).isNotNull()
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Skipped warnings
|
||||
|
||||
@Test
|
||||
fun `GIVEN ExistentialDeposit WHEN transform THEN notification is skipped`() {
|
||||
// GIVEN
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(
|
||||
CryptoCurrencyWarning.ExistentialDeposit(
|
||||
currencyName = "Polkadot",
|
||||
edStringValueWithSymbol = "1 DOT",
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
|
||||
// THEN
|
||||
assertThat(result.notifications).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN Rent WHEN transform THEN notification is skipped`() {
|
||||
// GIVEN
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(
|
||||
CryptoCurrencyWarning.Rent(
|
||||
rent = BigDecimal("0.00001"),
|
||||
exemptionAmount = BigDecimal("0.01"),
|
||||
cryptoCurrency = mockk(relaxed = true),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
|
||||
// THEN
|
||||
assertThat(result.notifications).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN UsedOutdatedDataWarning WHEN transform THEN notification is skipped`() {
|
||||
// GIVEN
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(CryptoCurrencyWarning.UsedOutdatedDataWarning),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
|
||||
// THEN
|
||||
assertThat(result.notifications).isEmpty()
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Message effect
|
||||
|
||||
@Test
|
||||
fun `GIVEN any mapped warning WHEN transform THEN messageEffect is None`() {
|
||||
// GIVEN
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(CryptoCurrencyWarning.SomeNetworksUnreachable),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
|
||||
// THEN
|
||||
assertThat(result.notifications.first().messageEffect).isEqualTo(TangemMessageEffect.None)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Icon
|
||||
|
||||
@Test
|
||||
fun `GIVEN any mapped warning WHEN transform THEN iconUM is not null`() {
|
||||
// GIVEN
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(CryptoCurrencyWarning.BeaconChainShutdown),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
|
||||
// THEN
|
||||
assertThat(result.notifications.first().iconUM).isNotNull()
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Multiple warnings
|
||||
|
||||
@Test
|
||||
fun `GIVEN multiple warnings with some skipped WHEN transform THEN only mapped warnings are in notifications`() {
|
||||
// GIVEN
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(
|
||||
CryptoCurrencyWarning.SomeNetworksUnreachable,
|
||||
CryptoCurrencyWarning.BeaconChainShutdown,
|
||||
CryptoCurrencyWarning.UsedOutdatedDataWarning,
|
||||
CryptoCurrencyWarning.TopUpWithoutReserve,
|
||||
),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
|
||||
// THEN
|
||||
assertThat(result.notifications).hasSize(2)
|
||||
assertThat(result.notifications.map { it.id }).containsExactly(
|
||||
"networks_unreachable",
|
||||
"beacon_chain_shutdown",
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Click callbacks
|
||||
|
||||
@Test
|
||||
fun `GIVEN HederaAssociateWarning WHEN button clicked THEN onAssociateClick is called`() {
|
||||
// GIVEN
|
||||
val currency: CryptoCurrency = mockk(relaxed = true)
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(HederaWarnings.AssociateWarning(currency = currency)),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
result.notifications.first().buttonsUM.first().onClick()
|
||||
|
||||
// THEN
|
||||
verify(exactly = 1) { clickIntents.onAssociateClick() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN RequiredTrustline WHEN button clicked THEN onOpenTrustlineClick is called`() {
|
||||
// GIVEN
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(
|
||||
CryptoCurrencyWarning.RequiredTrustline(
|
||||
currency = mockk(relaxed = true),
|
||||
currencySymbol = "XLM",
|
||||
requiredAmount = BigDecimal("10"),
|
||||
currencyDecimals = 7,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
result.notifications.first().buttonsUM.first().onClick()
|
||||
|
||||
// THEN
|
||||
verify(exactly = 1) { clickIntents.onOpenTrustlineClick() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN KaspaIncompleteTransaction WHEN retry clicked THEN onRetryIncompleteTransactionClick is called`() {
|
||||
// GIVEN
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(
|
||||
KaspaWarnings.IncompleteTransaction(
|
||||
currency = mockk(relaxed = true),
|
||||
amount = BigDecimal("100"),
|
||||
currencySymbol = "KAS",
|
||||
currencyDecimals = 8,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
result.notifications.first().buttonsUM.first().onClick()
|
||||
|
||||
// THEN
|
||||
verify(exactly = 1) { clickIntents.onRetryIncompleteTransactionClick() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN KaspaIncompleteTransaction WHEN close clicked THEN onDismissIncompleteTransactionClick is called`() {
|
||||
// GIVEN
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(
|
||||
KaspaWarnings.IncompleteTransaction(
|
||||
currency = mockk(relaxed = true),
|
||||
amount = BigDecimal("100"),
|
||||
currencySymbol = "KAS",
|
||||
currencyDecimals = 8,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
result.notifications.first().onCloseClick!!.invoke()
|
||||
|
||||
// THEN
|
||||
verify(exactly = 1) { clickIntents.onDismissIncompleteTransactionClick() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN MigrationClore WHEN button clicked THEN onCloreMigrationClick is called`() {
|
||||
// GIVEN
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(CryptoCurrencyWarning.MigrationClore),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
result.notifications.first().buttonsUM.first().onClick()
|
||||
|
||||
// THEN
|
||||
verify(exactly = 1) { clickIntents.onCloreMigrationClick() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN BalanceNotEnoughForFee WHEN buy button clicked THEN onBuyCoinClick is called`() {
|
||||
// GIVEN
|
||||
val coinCurrency: CryptoCurrency = mockk(relaxed = true) {
|
||||
io.mockk.every { network } returns mockk(relaxed = true) {
|
||||
io.mockk.every { name } returns "Ethereum"
|
||||
}
|
||||
io.mockk.every { name } returns "Ethereum"
|
||||
io.mockk.every { symbol } returns "ETH"
|
||||
}
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(
|
||||
CryptoCurrencyWarning.BalanceNotEnoughForFee(
|
||||
tokenCurrency = mockk(relaxed = true),
|
||||
coinCurrency = coinCurrency,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(initialState())
|
||||
result.notifications.first().buttonsUM.first().onClick()
|
||||
|
||||
// THEN
|
||||
verify(exactly = 1) { clickIntents.onBuyCoinClick(coinCurrency) }
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region State preservation
|
||||
|
||||
@Test
|
||||
fun `GIVEN any warnings WHEN transform THEN unrelated state fields are preserved`() {
|
||||
// GIVEN
|
||||
val state = initialState()
|
||||
val transformer = createTransformer(
|
||||
warnings = setOf(CryptoCurrencyWarning.SomeNetworksUnreachable),
|
||||
)
|
||||
|
||||
// WHEN
|
||||
val result = transformer.transform(state)
|
||||
|
||||
// THEN
|
||||
assertThat(result.topAppBarUM).isSameInstanceAs(state.topAppBarUM)
|
||||
assertThat(result.balanceBlockUM).isSameInstanceAs(state.balanceBlockUM)
|
||||
assertThat(result.marketPriceBlockState).isSameInstanceAs(state.marketPriceBlockState)
|
||||
assertThat(result.pullToRefreshConfig).isSameInstanceAs(state.pullToRefreshConfig)
|
||||
assertThat(result.isBalanceHidden).isEqualTo(state.isBalanceHidden)
|
||||
assertThat(result.isMarketPriceAvailable).isEqualTo(state.isMarketPriceAvailable)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
private fun createTransformer(warnings: Set<CryptoCurrencyWarning>) = UpdateNotificationsTransformer(
|
||||
warnings = warnings,
|
||||
clickIntents = clickIntents,
|
||||
)
|
||||
|
||||
private fun initialState(): TokenDetailsUM = TokenDetailsUM(
|
||||
topAppBarUM = TokenDetailsTopAppBarUM(
|
||||
titleState = TitleState.Simple(tokenName = "Tether"),
|
||||
subtitle = stringReference("ERC-20 in Ethereum network"),
|
||||
onBackClick = {},
|
||||
menuItems = persistentListOf(),
|
||||
),
|
||||
balanceBlockUM = mockk<TokenDetailsBalanceBlockUM>(relaxed = true),
|
||||
notifications = persistentListOf(),
|
||||
marketPriceBlockState = mockk<MarketPriceBlockState>(relaxed = true),
|
||||
earnBlockState = null,
|
||||
pullToRefreshConfig = mockk<PullToRefreshConfig>(relaxed = true),
|
||||
isBalanceHidden = false,
|
||||
isMarketPriceAvailable = false,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
package com.tangem.feature.tokendetails.presentation.tokendetails.state.transformer
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.tangem.common.ui.earn.EarnBlockUM
|
||||
import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig
|
||||
import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
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.staking.StakingBalance
|
||||
import com.tangem.domain.staking.model.StakingAvailability
|
||||
import com.tangem.domain.staking.model.StakingEntryInfo
|
||||
import com.tangem.domain.staking.model.StakingOption
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsBalanceBlockUM
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsTopAppBarUM
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsTopAppBarUM.TitleState
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsUM
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.math.BigDecimal
|
||||
|
||||
class UpdateStakingNotificationTransformerTest {
|
||||
|
||||
private val clickIntents: TokenDetailsClickIntents = mockk(relaxed = true)
|
||||
|
||||
@Test
|
||||
fun `GIVEN Unavailable WHEN transform THEN earnBlockState is null`() {
|
||||
val transformer = createTransformer(
|
||||
availability = StakingAvailability.Unavailable,
|
||||
entryInfo = null,
|
||||
)
|
||||
|
||||
val result = transformer.transform(initialState())
|
||||
|
||||
assertThat(result.earnBlockState).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN TemporaryUnavailable WHEN transform THEN TemporaryUnavailable`() {
|
||||
val transformer = createTransformer(
|
||||
availability = StakingAvailability.TemporaryUnavailable,
|
||||
entryInfo = null,
|
||||
)
|
||||
|
||||
val result = transformer.transform(initialState())
|
||||
|
||||
assertThat(result.earnBlockState).isInstanceOf(EarnBlockUM.Content::class.java)
|
||||
val content = result.earnBlockState as EarnBlockUM.Content
|
||||
assertThat(content.iconUM).isInstanceOf(EarnBlockUM.IconUM.Plain::class.java)
|
||||
assertThat(content.trailingUM).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN Available without entryInfo AND no staked WHEN transform THEN null`() {
|
||||
val transformer = createTransformer(
|
||||
availability = availableOption(BigDecimal("4.2")),
|
||||
entryInfo = null,
|
||||
)
|
||||
|
||||
val result = transformer.transform(initialState())
|
||||
|
||||
assertThat(result.earnBlockState).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN Available with entryInfo AND no staked WHEN transform THEN Available`() {
|
||||
val transformer = createTransformer(
|
||||
availability = availableOption(BigDecimal("4.2")),
|
||||
entryInfo = StakingEntryInfo(tokenSymbol = "SOL"),
|
||||
)
|
||||
|
||||
val result = transformer.transform(initialState())
|
||||
|
||||
assertThat(result.earnBlockState).isInstanceOf(EarnBlockUM.Content::class.java)
|
||||
val content = result.earnBlockState as EarnBlockUM.Content
|
||||
assertThat(content.trailingUM).isInstanceOf(EarnBlockUM.TrailingUM.Button::class.java)
|
||||
}
|
||||
|
||||
private fun createTransformer(
|
||||
availability: StakingAvailability,
|
||||
entryInfo: StakingEntryInfo?,
|
||||
) = UpdateStakingNotificationTransformer(
|
||||
cryptoCurrencyStatus = buildStatus(),
|
||||
stakingAvailability = availability,
|
||||
stakingEntryInfo = entryInfo,
|
||||
appCurrency = AppCurrency.Default,
|
||||
clickIntents = clickIntents,
|
||||
)
|
||||
|
||||
private fun buildStatus(): CryptoCurrencyStatus {
|
||||
val network = mockk<Network>(relaxed = true) {
|
||||
every { rawId } returns "solana"
|
||||
every { isTestnet } returns false
|
||||
}
|
||||
val currency = mockk<CryptoCurrency.Coin>(relaxed = true) {
|
||||
every { symbol } returns "SOL"
|
||||
every { decimals } returns 9
|
||||
every { this@mockk.network } returns network
|
||||
every { id.isCoin } returns true
|
||||
}
|
||||
val stakingBalance = mockk<StakingBalance>(relaxed = true)
|
||||
val value = mockk<CryptoCurrencyStatus.Value>(relaxed = true) {
|
||||
every { this@mockk.stakingBalance } returns stakingBalance
|
||||
every { fiatRate } returns BigDecimal.ONE
|
||||
every { yieldSupplyStatus } returns null
|
||||
}
|
||||
return CryptoCurrencyStatus(currency = currency, value = value)
|
||||
}
|
||||
|
||||
private fun availableOption(apy: BigDecimal): StakingAvailability.Available {
|
||||
val option = mockk<StakingOption>(relaxed = true) {
|
||||
every { this@mockk.apy } returns apy
|
||||
}
|
||||
return StakingAvailability.Available(option = option)
|
||||
}
|
||||
|
||||
private fun initialState(): TokenDetailsUM = TokenDetailsUM(
|
||||
topAppBarUM = TokenDetailsTopAppBarUM(
|
||||
titleState = TitleState.Simple(tokenName = "Solana"),
|
||||
subtitle = stringReference("Solana network"),
|
||||
onBackClick = {},
|
||||
menuItems = persistentListOf(),
|
||||
),
|
||||
balanceBlockUM = mockk<TokenDetailsBalanceBlockUM>(relaxed = true),
|
||||
notifications = persistentListOf(),
|
||||
earnBlockState = null,
|
||||
marketPriceBlockState = mockk<MarketPriceBlockState>(relaxed = true),
|
||||
pullToRefreshConfig = mockk<PullToRefreshConfig>(relaxed = true),
|
||||
isBalanceHidden = false,
|
||||
isMarketPriceAvailable = false,
|
||||
)
|
||||
}
|
||||
|
|
@ -205,8 +205,9 @@ class UpdateTopBarMenuTransformerTest {
|
|||
menuItems = persistentListOf(),
|
||||
),
|
||||
balanceBlockUM = mockk<TokenDetailsBalanceBlockUM>(relaxed = true),
|
||||
notifications = persistentListOf(),
|
||||
marketPriceBlockState = mockk<MarketPriceBlockState>(relaxed = true),
|
||||
stakingBlocksState = null,
|
||||
earnBlockState = null,
|
||||
pullToRefreshConfig = mockk<PullToRefreshConfig>(relaxed = true),
|
||||
isBalanceHidden = false,
|
||||
isMarketPriceAvailable = false,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue