Updated on 2026-08-14

This commit is contained in:
Tangem 2026-07-14 14:50:24 +03:00
commit 50fe9e603d
1919 changed files with 94940 additions and 15178 deletions

View file

@ -74,7 +74,6 @@ class SetTokenListTransformerTest {
shouldShowMainPromo = false,
isAccountsModeEnabled = false,
isRedesignEnabled = true,
isAddAndManageTokensEnabled = false,
isMultipleCardsEnabled = false,
)
}

View file

@ -6,7 +6,6 @@ import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
import io.mockk.every
import io.mockk.mockk
import io.mockk.slot
@ -21,7 +20,6 @@ internal class WalletContentClickIntentsAnalyticsTest {
private val stateHolder: WalletStateController = mockk(relaxed = true)
private val analyticsEventHandler: AnalyticsEventHandler = mockk(relaxed = true)
private val walletFeatureToggles: WalletFeatureToggles = mockk(relaxed = true)
private val router: InnerWalletRouter = mockk(relaxed = true)
private val userWalletId = UserWalletId(stringValue = "0123456789ABCDEF")
@ -45,16 +43,14 @@ internal class WalletContentClickIntentsAnalyticsTest {
yieldSupplySetShouldShowMainPromoUseCase = mockk(relaxed = true),
tokenListAnalyticsSender = mockk(relaxed = true),
uiMessageSender = mockk(relaxed = true),
walletFeatureToggles = walletFeatureToggles,
)
implementor.initialize(router = router, coroutineScope = TestScope())
return implementor
}
@Test
fun `GIVEN add and manage toggle enabled WHEN onOrganizeTokensClick THEN sends ButtonAddManage event and opens bottom sheet`() =
fun `WHEN onOrganizeTokensClick THEN sends ButtonAddManage event and opens bottom sheet`() =
runTest {
every { walletFeatureToggles.isAddAndManageTokensEnabled } returns true
val implementor = createImplementor()
val captured = slot<AnalyticsEvent>()
@ -67,17 +63,4 @@ internal class WalletContentClickIntentsAnalyticsTest {
verify(exactly = 1) { router.openAddAndManageBottomSheet(userWalletId = userWalletId) }
verify(exactly = 0) { router.openOrganizeTokensScreen(any()) }
}
@Test
fun `GIVEN add and manage toggle disabled WHEN onOrganizeTokensClick THEN does not send analytics and opens organize screen`() =
runTest {
every { walletFeatureToggles.isAddAndManageTokensEnabled } returns false
val implementor = createImplementor()
implementor.onOrganizeTokensClick()
verify(exactly = 0) { analyticsEventHandler.send(any<AnalyticsEvent>()) }
verify(exactly = 1) { router.openOrganizeTokensScreen(userWalletId = userWalletId) }
verify(exactly = 0) { router.openAddAndManageBottomSheet(any()) }
}
}

View file

@ -24,8 +24,8 @@ import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.networks.multi.MultiNetworkStatusSupplier
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
import com.tangem.domain.wallets.PromoCodeActivationResult
import com.tangem.domain.wallets.models.GetUserWalletError
import com.tangem.domain.wallets.models.errors.ActivatePromoCodeError
import com.tangem.domain.wallets.models.errors.GetUserWalletError
import com.tangem.domain.wallets.usecase.ActivateBitcoinPromocodeUseCase
import com.tangem.domain.wallets.usecase.BindRefcodeWithWalletUseCase
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
@ -82,7 +82,6 @@ class DefaultPromoDeeplinkHandlerTest {
every { analyticsEventHandler.send(any()) } returns Unit
messages = mutableListOf()
every { uiMessageSender.send(capture(messages)) } just runs
}
@Test
@ -499,13 +498,21 @@ class DefaultPromoDeeplinkHandlerTest {
)
coEvery { multiNetworkStatusSupplier.invoke(any()) } returns flowOf(setOf(btcStatusCard, btcStatusCustom))
val btcCoinCustom = buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCustom)
val btcCoinCard = buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCard)
val btcCoinCustom =
buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCustom)
val btcCoinCard =
buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCard)
coEvery { multiWalletCryptoCurrenciesSupplier.getSyncOrNull(any()) } returns setOf(
btcCoinCustom,
btcCoinCard,
)
coEvery { activateBitcoinPromocodeUseCase.invoke(any(), "bc1qcustom", promoCode) } returns Either.Right("ok")
coEvery {
activateBitcoinPromocodeUseCase.invoke(
any(),
"bc1qcustom",
promoCode
)
} returns Either.Right("ok")
val dispatcherProvider = testDispatcherProvider(testScheduler)
@ -556,7 +563,8 @@ class DefaultPromoDeeplinkHandlerTest {
)
coEvery { multiNetworkStatusSupplier.invoke(any()) } returns flowOf(setOf(btcStatusCard, btcStatusCustom))
val btcCoinCard = buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCard)
val btcCoinCard =
buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCard)
coEvery { multiWalletCryptoCurrenciesSupplier.getSyncOrNull(any()) } returns setOf(btcCoinCard)
coEvery { activateBitcoinPromocodeUseCase.invoke(any(), "bc1qcard", promoCode) } returns Either.Right("ok")
@ -643,7 +651,7 @@ class DefaultPromoDeeplinkHandlerTest {
Truth.assertThat(sent.title).isEqualTo(resourceReference(R.string.bitcoin_promo_no_address_title))
Truth.assertThat(sent.message).isEqualTo(resourceReference(R.string.bitcoin_promo_no_address))
coVerify(exactly = 0) { activateBitcoinPromocodeUseCase.invoke(any(),any(), any()) }
coVerify(exactly = 0) { activateBitcoinPromocodeUseCase.invoke(any(), any(), any()) }
verify(
exactly = 1,
@ -673,8 +681,10 @@ class DefaultPromoDeeplinkHandlerTest {
)
coEvery { multiNetworkStatusSupplier.invoke(any()) } returns flowOf(setOf(btcStatusCard))
val btcCoinCustom = buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCustom)
val btcCoinCard = buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCard)
val btcCoinCustom =
buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCustom)
val btcCoinCard =
buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCard)
coEvery { multiWalletCryptoCurrenciesSupplier.getSyncOrNull(any()) } returns setOf(
btcCoinCustom,
btcCoinCard,
@ -732,7 +742,8 @@ class DefaultPromoDeeplinkHandlerTest {
)
coEvery { multiNetworkStatusSupplier.invoke(any()) } returns flowOf(setOf(btcStatusCustom))
val btcCoinCard = buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCard)
val btcCoinCard =
buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCard)
coEvery { multiWalletCryptoCurrenciesSupplier.getSyncOrNull(any()) } returns setOf(btcCoinCard)
val dispatcherProvider = testDispatcherProvider(testScheduler)
@ -787,7 +798,8 @@ class DefaultPromoDeeplinkHandlerTest {
)
coEvery { multiNetworkStatusSupplier.invoke(any()) } returns flowOf(setOf(btcStatusCard))
val btcCoinCustom = buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCustom)
val btcCoinCustom =
buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCustom)
coEvery { multiWalletCryptoCurrenciesSupplier.getSyncOrNull(any()) } returns setOf(btcCoinCustom)
val dispatcherProvider = testDispatcherProvider(testScheduler)

View file

@ -21,7 +21,6 @@ import com.tangem.domain.yield.supply.promo.usecase.ShouldShowYieldBoostMainBann
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetShouldShowMainPromoUseCase
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotificationUM
import com.tangem.features.yield.supply.api.YieldSupplyFeatureToggles
import io.mockk.clearMocks
import io.mockk.coEvery
import io.mockk.every
@ -48,7 +47,6 @@ internal class GetWalletNotificationsCarouselFactoryTest {
private val notificationsRepository: NotificationsRepository = mockk()
private val shouldShowYieldBoostMainBannerUseCase: ShouldShowYieldBoostMainBannerUseCase = mockk()
private val yieldSupplyGetShouldShowMainPromoUseCase: YieldSupplyGetShouldShowMainPromoUseCase = mockk()
private val yieldSupplyFeatureToggles: YieldSupplyFeatureToggles = mockk()
private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier = mockk(relaxed = true)
private val clickIntents: WalletClickIntents = mockk(relaxed = true)
private val userWallet: UserWallet.Hot = mockk(relaxed = true)
@ -59,7 +57,6 @@ internal class GetWalletNotificationsCarouselFactoryTest {
notificationsRepository = notificationsRepository,
shouldShowYieldBoostMainBannerUseCase = shouldShowYieldBoostMainBannerUseCase,
yieldSupplyGetShouldShowMainPromoUseCase = yieldSupplyGetShouldShowMainPromoUseCase,
yieldSupplyFeatureToggles = yieldSupplyFeatureToggles,
singleAccountStatusListSupplier = singleAccountStatusListSupplier,
)
@ -71,7 +68,6 @@ internal class GetWalletNotificationsCarouselFactoryTest {
notificationsRepository,
shouldShowYieldBoostMainBannerUseCase,
yieldSupplyGetShouldShowMainPromoUseCase,
yieldSupplyFeatureToggles,
singleAccountStatusListSupplier,
clickIntents,
userWallet,
@ -83,7 +79,6 @@ internal class GetWalletNotificationsCarouselFactoryTest {
every { isReadyToShowRateAppUseCase() } returns flowOf(false)
every { getWalletsUseCase() } returns flowOf(emptyList())
every { yieldSupplyGetShouldShowMainPromoUseCase() } returns flowOf(true)
every { yieldSupplyFeatureToggles.isYieldPromoEnabled } returns true
coEvery { shouldShowYieldBoostMainBannerUseCase(any()) } returns Either.Right(true)
// Balance is loaded by default, so banners gated on balance are not suppressed.
every {
@ -100,7 +95,6 @@ internal class GetWalletNotificationsCarouselFactoryTest {
@MethodSource("provideTestModels")
fun `GIVEN gating conditions WHEN create THEN yield boost banner visibility matches`(model: Model) = runTest {
// Arrange
every { yieldSupplyFeatureToggles.isYieldPromoEnabled } returns model.toggleEnabled
every { yieldSupplyGetShouldShowMainPromoUseCase() } returns flowOf(model.shouldShowLocal)
coEvery { shouldShowYieldBoostMainBannerUseCase(WALLET_ID) } returns model.mainBanner
@ -206,19 +200,16 @@ internal class GetWalletNotificationsCarouselFactoryTest {
)
internal data class Model(
val toggleEnabled: Boolean,
val shouldShowLocal: Boolean,
val mainBanner: Either<Throwable, Boolean>,
val expectedShown: Boolean,
)
private fun provideTestModels() = listOf(
Model(toggleEnabled = true, shouldShowLocal = true, mainBanner = Either.Right(true), expectedShown = true),
Model(toggleEnabled = false, shouldShowLocal = true, mainBanner = Either.Right(true), expectedShown = false),
Model(toggleEnabled = true, shouldShowLocal = false, mainBanner = Either.Right(true), expectedShown = false),
Model(toggleEnabled = true, shouldShowLocal = true, mainBanner = Either.Right(false), expectedShown = false),
Model(shouldShowLocal = true, mainBanner = Either.Right(true), expectedShown = true),
Model(shouldShowLocal = false, mainBanner = Either.Right(true), expectedShown = false),
Model(shouldShowLocal = true, mainBanner = Either.Right(false), expectedShown = false),
Model(
toggleEnabled = true,
shouldShowLocal = true,
mainBanner = Either.Left(RuntimeException("boom")),
expectedShown = false,

View file

@ -67,7 +67,6 @@ internal class WalletTokensListUMConverterTest {
isAccountsModeEnabled = false,
expandedAccounts = emptySet(),
stakingAvailabilityMap = emptyMap(),
isAddAndManageTokensEnabled = true,
shouldShowMainPromo = false,
)