Updated on 2026-08-14
This commit is contained in:
parent
84f35ac892
commit
e7edce0cd8
5 changed files with 205 additions and 0 deletions
|
|
@ -0,0 +1,14 @@
|
|||
package com.tangem.feature.wallet.child.managetokens.analytics
|
||||
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
|
||||
internal sealed class PortfolioAnalyticsEvent(
|
||||
event: String,
|
||||
) : AnalyticsEvent(category = "Portfolio", event = event) {
|
||||
|
||||
class ButtonAddManage : PortfolioAnalyticsEvent(event = "Button - Add Manage")
|
||||
|
||||
class ButtonAddTokens : PortfolioAnalyticsEvent(event = "Button - Add tokens")
|
||||
|
||||
class ButtonOrganizeTokens : PortfolioAnalyticsEvent(event = "Button - Organize Tokens")
|
||||
}
|
||||
|
|
@ -3,11 +3,13 @@ package com.tangem.feature.wallet.child.managetokens.model
|
|||
import com.arkivanov.decompose.router.slot.SlotNavigation
|
||||
import com.arkivanov.decompose.router.slot.activate
|
||||
import com.arkivanov.decompose.router.slot.dismiss
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.feature.wallet.child.managetokens.AddAndManageBottomSheetComponent
|
||||
import com.tangem.feature.wallet.child.managetokens.analytics.PortfolioAnalyticsEvent
|
||||
import com.tangem.features.commonfeatures.api.portfolioselector.PortfolioFetcher
|
||||
import com.tangem.features.commonfeatures.api.portfolioselector.PortfolioSelectorComponent
|
||||
import com.tangem.features.commonfeatures.api.portfolioselector.PortfolioSelectorController
|
||||
|
|
@ -21,6 +23,7 @@ internal class AddAndManageModel @Inject constructor(
|
|||
paramsContainer: ParamsContainer,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val portfolioFetcherFactory: PortfolioFetcher.Factory,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
val portfolioSelectorController: PortfolioSelectorController,
|
||||
) : Model() {
|
||||
|
||||
|
|
@ -45,6 +48,7 @@ internal class AddAndManageModel @Inject constructor(
|
|||
}
|
||||
|
||||
fun onAddTokensClick() {
|
||||
analyticsEventHandler.send(PortfolioAnalyticsEvent.ButtonAddTokens())
|
||||
modelScope.launch {
|
||||
val data = portfolioFetcher.data.first()
|
||||
val isSingleAccount = data.isSingleChoice(params.userWalletId)
|
||||
|
|
@ -65,6 +69,7 @@ internal class AddAndManageModel @Inject constructor(
|
|||
}
|
||||
|
||||
fun onOrganizeTokensClick() {
|
||||
analyticsEventHandler.send(PortfolioAnalyticsEvent.ButtonOrganizeTokens())
|
||||
params.onDismiss()
|
||||
params.onOrganizeTokensClick()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import com.tangem.domain.tokens.GetCryptoCurrencyActionsUseCase
|
|||
import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplySetShouldShowMainPromoUseCase
|
||||
import com.tangem.feature.wallet.child.managetokens.analytics.PortfolioAnalyticsEvent
|
||||
import com.tangem.feature.wallet.presentation.account.AccountDependencies
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.OnrampStatusFactory
|
||||
|
|
@ -123,6 +124,7 @@ internal class WalletContentClickIntentsImplementor @Inject constructor(
|
|||
override fun onOrganizeTokensClick() {
|
||||
val userWalletId = stateHolder.getSelectedWalletId()
|
||||
if (walletFeatureToggles.isAddAndManageTokensEnabled) {
|
||||
analyticsEventHandler.send(PortfolioAnalyticsEvent.ButtonAddManage())
|
||||
router.openAddAndManageBottomSheet(userWalletId = userWalletId)
|
||||
} else {
|
||||
router.openOrganizeTokensScreen(userWalletId = userWalletId)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,101 @@
|
|||
package com.tangem.feature.wallet.child.managetokens.model
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.decompose.model.MutableParamsContainer
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.feature.wallet.child.managetokens.AddAndManageBottomSheetComponent
|
||||
import com.tangem.features.commonfeatures.api.portfolioselector.PortfolioFetcher
|
||||
import com.tangem.features.commonfeatures.api.portfolioselector.PortfolioSelectorController
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.slot
|
||||
import io.mockk.verify
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
internal class AddAndManageModelTest {
|
||||
|
||||
private val analyticsEventHandler: AnalyticsEventHandler = mockk(relaxed = true)
|
||||
private val portfolioFetcher: PortfolioFetcher = mockk(relaxed = true) {
|
||||
every { data } returns flowOf(
|
||||
PortfolioFetcher.Data(
|
||||
appCurrency = mockk(relaxed = true),
|
||||
isBalanceHidden = false,
|
||||
balances = emptyMap(),
|
||||
),
|
||||
)
|
||||
}
|
||||
private val portfolioFetcherFactory: PortfolioFetcher.Factory = mockk(relaxed = true) {
|
||||
every { create(any(), any()) } returns portfolioFetcher
|
||||
}
|
||||
private val portfolioSelectorController: PortfolioSelectorController = mockk(relaxed = true) {
|
||||
every { selectedAccount } returns flowOf(null)
|
||||
}
|
||||
|
||||
private val onDismiss: () -> Unit = mockk(relaxed = true)
|
||||
private val onOrganizeTokensClick: () -> Unit = mockk(relaxed = true)
|
||||
private val onManageTokensClick: (AccountId) -> Unit = mockk(relaxed = true)
|
||||
|
||||
private val userWalletId = UserWalletId(stringValue = "0123456789ABCDEF")
|
||||
|
||||
private val params = AddAndManageBottomSheetComponent.Params(
|
||||
userWalletId = userWalletId,
|
||||
onDismiss = onDismiss,
|
||||
onOrganizeTokensClick = onOrganizeTokensClick,
|
||||
onManageTokensClick = onManageTokensClick,
|
||||
)
|
||||
|
||||
private fun createModel(): AddAndManageModel = AddAndManageModel(
|
||||
paramsContainer = MutableParamsContainer(params),
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
portfolioFetcherFactory = portfolioFetcherFactory,
|
||||
analyticsEventHandler = analyticsEventHandler,
|
||||
portfolioSelectorController = portfolioSelectorController,
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `GIVEN bottom sheet model WHEN onAddTokensClick THEN sends ButtonAddTokens event with correct payload`() =
|
||||
runTest {
|
||||
val model = createModel()
|
||||
val captured = slot<AnalyticsEvent>()
|
||||
|
||||
model.onAddTokensClick()
|
||||
|
||||
verify(exactly = 1) { analyticsEventHandler.send(capture(captured)) }
|
||||
assertThat(captured.captured.category).isEqualTo("Portfolio")
|
||||
assertThat(captured.captured.event).isEqualTo("Button - Add tokens")
|
||||
assertThat(captured.captured.params).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN bottom sheet model WHEN onOrganizeTokensClick THEN sends ButtonOrganizeTokens event with correct payload`() =
|
||||
runTest {
|
||||
val model = createModel()
|
||||
val captured = slot<AnalyticsEvent>()
|
||||
|
||||
model.onOrganizeTokensClick()
|
||||
|
||||
verify(exactly = 1) { analyticsEventHandler.send(capture(captured)) }
|
||||
assertThat(captured.captured.category).isEqualTo("Portfolio")
|
||||
assertThat(captured.captured.event).isEqualTo("Button - Organize Tokens")
|
||||
assertThat(captured.captured.params).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN bottom sheet model WHEN onOrganizeTokensClick THEN dismisses bottom sheet and forwards to params callback`() =
|
||||
runTest {
|
||||
val model = createModel()
|
||||
|
||||
model.onOrganizeTokensClick()
|
||||
|
||||
verify(exactly = 1) { onDismiss() }
|
||||
verify(exactly = 1) { onOrganizeTokensClick() }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
package com.tangem.feature.wallet.child.wallet.model.intents
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
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
|
||||
import io.mockk.verify
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
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")
|
||||
|
||||
private fun createImplementor(): WalletContentClickIntentsImplementor {
|
||||
every { stateHolder.getSelectedWalletId() } returns userWalletId
|
||||
|
||||
val implementor = WalletContentClickIntentsImplementor(
|
||||
stateHolder = stateHolder,
|
||||
currencyActionsClickIntents = mockk(relaxed = true),
|
||||
onrampStatusFactory = mockk(relaxed = true),
|
||||
getUserWalletUseCase = mockk(relaxed = true),
|
||||
singleAccountStatusListSupplier = mockk(relaxed = true),
|
||||
getCryptoCurrencyActionsUseCase = mockk(relaxed = true),
|
||||
getExplorerTransactionUrlUseCase = mockk(relaxed = true),
|
||||
shouldShowMarketsTooltipUseCase = mockk(relaxed = true),
|
||||
dispatchers = mockk(relaxed = true),
|
||||
walletEventSender = mockk(relaxed = true),
|
||||
analyticsEventHandler = analyticsEventHandler,
|
||||
accountDependencies = mockk(relaxed = true),
|
||||
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`() =
|
||||
runTest {
|
||||
every { walletFeatureToggles.isAddAndManageTokensEnabled } returns true
|
||||
val implementor = createImplementor()
|
||||
val captured = slot<AnalyticsEvent>()
|
||||
|
||||
implementor.onOrganizeTokensClick()
|
||||
|
||||
verify(exactly = 1) { analyticsEventHandler.send(capture(captured)) }
|
||||
assertThat(captured.captured.category).isEqualTo("Portfolio")
|
||||
assertThat(captured.captured.event).isEqualTo("Button - Add Manage")
|
||||
assertThat(captured.captured.params).isEmpty()
|
||||
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()) }
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue