Updated on 2026-08-14

This commit is contained in:
Tangem 2026-04-21 09:28:48 +01:00
parent 0bedc513a7
commit c846d8c276
15 changed files with 862 additions and 3 deletions

View file

@ -11,10 +11,15 @@ android {
namespace = "com.tangem.features.createwalletstart.impl"
}
tasks.withType<Test>().configureEach {
useJUnitPlatform()
}
dependencies {
/** Api */
implementation(projects.features.createWalletStart.api)
implementation(projects.features.hotWallet.api)
implementation(projects.features.onboardingV2.api)
/** Project - Domain */
implementation(projects.domain.card)
@ -71,4 +76,11 @@ dependencies {
/** DI */
implementation(deps.hilt.android)
kapt(deps.hilt.kapt)
/** Test */
testImplementation(deps.test.junit5)
testRuntimeOnly(deps.test.junit5.engine)
testImplementation(deps.test.mockk)
testImplementation(deps.test.truth)
testImplementation(deps.test.coroutine)
}

View file

@ -33,14 +33,15 @@ import com.tangem.domain.wallets.builder.ColdUserWalletBuilder
import com.tangem.domain.wallets.usecase.GenerateBuyTangemCardLinkUseCase
import com.tangem.domain.wallets.usecase.SaveWalletUseCase
import com.tangem.features.createwalletstart.entity.CreateWalletStartUM
import com.tangem.features.onboarding.v2.OnboardingV2FeatureToggles
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.logging.TangemLogger
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import com.tangem.utils.logging.TangemLogger
import javax.inject.Inject
private const val HIDE_PROGRESS_DELAY = 400L
@ -65,6 +66,7 @@ internal class CreateWalletStartModel @Inject constructor(
private val trackingContextProxy: TrackingContextProxy,
private val analyticsEventHandler: AnalyticsEventHandler,
private val appsFlyerStore: AppsFlyerStore,
private val onboardingV2FeatureToggles: OnboardingV2FeatureToggles,
) : Model() {
private val params = paramsContainer.require<CreateWalletStartComponent.Params>()
@ -234,7 +236,12 @@ internal class CreateWalletStartModel @Inject constructor(
},
ifRight = {
setLoading(false)
appRouter.replaceAll(AppRoute.Wallet)
val route = if (onboardingV2FeatureToggles.isAddressSyncEnabled) {
AppRoute.AddressSync
} else {
AppRoute.Wallet
}
appRouter.replaceAll(route)
},
)
}

View file

@ -0,0 +1,651 @@
package com.tangem.features.createwalletstart
import arrow.core.left
import arrow.core.right
import com.tangem.common.core.TangemError
import com.tangem.common.core.TangemSdkError
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.AppRouter
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.Basic
import com.tangem.core.analytics.models.event.OnboardingAnalyticsEvent
import com.tangem.core.analytics.utils.TrackingContextProxy
import com.tangem.core.decompose.model.MutableParamsContainer
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.decompose.navigation.Router
import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.core.navigation.url.UrlOpener
import com.tangem.core.ui.R
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.message.DialogMessage
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
import com.tangem.domain.card.ScanCardProcessor
import com.tangem.domain.card.analytics.IntroductionProcess
import com.tangem.domain.card.repository.CardSdkConfigRepository
import com.tangem.domain.common.wallets.UserWalletsListRepository
import com.tangem.domain.common.wallets.error.SaveWalletError
import com.tangem.domain.hotwallet.IsHotWalletCreationSupported
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.settings.repositories.SettingsRepository
import com.tangem.domain.wallets.builder.ColdUserWalletBuilder
import com.tangem.domain.wallets.models.AppsFlyerConversionData
import com.tangem.domain.wallets.usecase.GenerateBuyTangemCardLinkUseCase
import com.tangem.domain.wallets.usecase.SaveWalletUseCase
import com.tangem.features.createwalletstart.entity.CreateWalletStartUM
import com.tangem.features.onboarding.v2.OnboardingV2FeatureToggles
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
import io.mockk.*
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
@OptIn(ExperimentalCoroutinesApi::class)
internal class CreateWalletStartModelTest {
private val router: Router = mockk(relaxed = true)
private val appRouter: AppRouter = mockk(relaxed = true)
private val scanCardProcessor: ScanCardProcessor = mockk()
private val cardSdkConfigRepository: CardSdkConfigRepository = mockk(relaxed = true)
private val settingsRepository: SettingsRepository = mockk()
private val coldUserWalletBuilderFactory: ColdUserWalletBuilder.Factory = mockk()
private val coldUserWalletBuilder: ColdUserWalletBuilder = mockk()
private val saveWalletUseCase: SaveWalletUseCase = mockk()
private val isHotWalletCreationSupported: IsHotWalletCreationSupported = mockk()
private val userWalletsListRepository: UserWalletsListRepository = mockk()
private val uiMessageSender: UiMessageSender = mockk(relaxed = true)
private val generateBuyTangemCardLinkUseCase: GenerateBuyTangemCardLinkUseCase = mockk()
private val urlOpener: UrlOpener = mockk(relaxed = true)
private val trackingContextProxy: TrackingContextProxy = mockk(relaxed = true)
private val analyticsEventHandler: AnalyticsEventHandler = mockk(relaxed = true)
private val appsFlyerStore: AppsFlyerStore = mockk()
private val onboardingV2FeatureToggles: OnboardingV2FeatureToggles = mockk()
private val testUserWalletId = UserWalletId("1234567890ABCDEF")
private val testScanResponse: ScanResponse = mockk(relaxed = true)
private val testColdWallet: UserWallet.Cold = mockk(relaxed = true) {
every { walletId } returns testUserWalletId
}
@BeforeEach
fun setUp() {
coEvery { appsFlyerStore.get() } returns null
coEvery { settingsRepository.shouldSaveAccessCodes() } returns false
every { coldUserWalletBuilderFactory.create(any()) } returns coldUserWalletBuilder
every { coldUserWalletBuilder.build() } returns testColdWallet
every { onboardingV2FeatureToggles.isAddressSyncEnabled } returns false
coEvery {
scanCardProcessor.scan(
analyticsSource = any(),
shouldCheckIsAlreadyActivated = any(),
cardId = any(),
onProgressStateChange = any(),
onWalletNotCreated = any(),
disclaimerWillShow = any(),
onCancel = any(),
onFailure = any(),
onSuccess = any()
)
} just Runs
}
@Test
fun `GIVEN ColdWallet mode WHEN onScanClick THEN ButtonScanCard event sent AND scan called`() = runTest {
val model = createModel(testScope = this, mode = CreateWalletStartComponent.Mode.ColdWallet)
advanceUntilIdle()
model.uiState.value.onScanClick.invoke()
advanceUntilIdle()
verify {
analyticsEventHandler.send(
match<IntroductionProcess.ButtonScanCard> {
it.source == AnalyticsParam.ScreensSources.CreateWalletIntro
},
)
}
coVerify {
scanCardProcessor.scan(
analyticsSource = AnalyticsParam.ScreensSources.Intro,
shouldCheckIsAlreadyActivated = true,
cardId = null,
onProgressStateChange = any(),
onWalletNotCreated = any(),
disclaimerWillShow = any(),
onCancel = any(),
onFailure = any(),
onSuccess = any()
)
}
}
@Test
fun `GIVEN HotWallet mode WHEN onScanClick THEN ButtonScanCard event sent AND scan called`() = runTest {
val model = createModel(testScope = this, mode = CreateWalletStartComponent.Mode.HotWallet)
advanceUntilIdle()
model.uiState.value.onScanClick.invoke()
advanceUntilIdle()
verify {
analyticsEventHandler.send(
match<IntroductionProcess.ButtonScanCard> {
it.source == AnalyticsParam.ScreensSources.CreateWalletIntro
},
)
}
coVerify {
scanCardProcessor.scan(
analyticsSource = AnalyticsParam.ScreensSources.Intro,
shouldCheckIsAlreadyActivated = true,
cardId = null,
onProgressStateChange = any(),
onWalletNotCreated = any(),
disclaimerWillShow = any(),
onCancel = any(),
onFailure = any(),
onSuccess = any()
)
}
}
@Test
fun `GIVEN ColdWallet AND hot wallet not supported WHEN otherMethodClick THEN dialog sent`() = runTest {
every { isHotWalletCreationSupported() } returns false
every { isHotWalletCreationSupported.getLeastVersionName() } returns "13"
val model = createModel(testScope = this, mode = CreateWalletStartComponent.Mode.ColdWallet)
advanceUntilIdle()
model.uiState.value.otherMethodClick.invoke()
advanceUntilIdle()
verify { trackingContextProxy.addHotWalletContext() }
verify {
analyticsEventHandler.send(
match<OnboardingAnalyticsEvent.Onboarding.ButtonMobileWallet> { true },
)
}
verify { uiMessageSender.send(match<DialogMessage> { true }) }
verify(exactly = 0) { router.push(any(), any()) }
}
@Test
fun `GIVEN HotWallet AND hot wallet supported WHEN onPrimaryButtonClick THEN CreateMobileWallet pushed`() =
runTest {
every { isHotWalletCreationSupported() } returns true
val model = createModel(testScope = this, mode = CreateWalletStartComponent.Mode.HotWallet)
advanceUntilIdle()
model.uiState.value.onPrimaryButtonClick.invoke()
advanceUntilIdle()
verify { trackingContextProxy.addHotWalletContext() }
verify {
analyticsEventHandler.send(
match<OnboardingAnalyticsEvent.Onboarding.ButtonMobileWallet> { true },
)
}
verify {
router.push(
route = AppRoute.CreateMobileWallet(
source = AnalyticsParam.ScreensSources.CreateWalletIntro.value,
),
onComplete = any(),
)
}
verify(exactly = 0) { uiMessageSender.send(any()) }
}
@Test
fun `GIVEN ColdWallet mode WHEN onPrimaryButtonClick THEN buy link opened`() = runTest {
val testUrl = "https://buy.tangem.com"
coEvery {
generateBuyTangemCardLinkUseCase.invoke(GenerateBuyTangemCardLinkUseCase.Source.Creation)
} returns testUrl
val model = createModel(testScope = this, mode = CreateWalletStartComponent.Mode.ColdWallet)
advanceUntilIdle()
model.uiState.value.onPrimaryButtonClick.invoke()
advanceUntilIdle()
verify {
analyticsEventHandler.send(
match<Basic.ButtonBuy> { true },
)
}
coVerify { generateBuyTangemCardLinkUseCase.invoke(GenerateBuyTangemCardLinkUseCase.Source.Creation) }
verify { urlOpener.openUrl(testUrl) }
}
@Test
fun `GIVEN HotWallet mode WHEN onBuyClick THEN buy link opened`() = runTest {
val testUrl = "https://buy.tangem.com"
coEvery {
generateBuyTangemCardLinkUseCase.invoke(GenerateBuyTangemCardLinkUseCase.Source.Creation)
} returns testUrl
val model = createModel(testScope = this, mode = CreateWalletStartComponent.Mode.HotWallet)
advanceUntilIdle()
model.uiState.value.otherMethodClick.invoke()
advanceUntilIdle()
verify {
analyticsEventHandler.send(
match<Basic.ButtonBuy> { true },
)
}
coVerify { generateBuyTangemCardLinkUseCase.invoke(GenerateBuyTangemCardLinkUseCase.Source.Creation) }
verify { urlOpener.openUrl(testUrl) }
}
@Test
fun `WHEN scanCard THEN access code policy set AND scanProcessor called`() = runTest {
coEvery { settingsRepository.shouldSaveAccessCodes() } returns true
val model = createModel(testScope = this, mode = CreateWalletStartComponent.Mode.ColdWallet)
advanceUntilIdle()
model.uiState.value.onScanClick.invoke()
advanceUntilIdle()
verify { cardSdkConfigRepository.setAccessCodeRequestPolicy(isBiometricsRequestPolicy = true) }
coVerify {
scanCardProcessor.scan(
analyticsSource = AnalyticsParam.ScreensSources.Intro,
shouldCheckIsAlreadyActivated = true,
cardId = null,
onProgressStateChange = any(),
onWalletNotCreated = any(),
disclaimerWillShow = any(),
onCancel = any(),
onFailure = any(),
onSuccess = any()
)
}
}
@Test
fun `GIVEN NfcFeatureIsUnavailable WHEN handleScanError THEN nfcFeatureUnavailable dialog sent`() = runTest {
val error = TangemSdkError.NfcFeatureIsUnavailable()
coEvery {
scanCardProcessor.scan(
analyticsSource = any(),
shouldCheckIsAlreadyActivated = any(),
cardId = any(),
onProgressStateChange = any(),
onWalletNotCreated = any(),
disclaimerWillShow = any(),
onCancel = any(),
onFailure = any(),
onSuccess = any()
)
} coAnswers {
val onFailure = arg<suspend (TangemError) -> Unit>(7)
onFailure.invoke(error)
}
val model = createModel(testScope = this, mode = CreateWalletStartComponent.Mode.ColdWallet)
advanceUntilIdle()
model.uiState.value.onScanClick.invoke()
advanceUntilIdle()
verify { uiMessageSender.send(match<DialogMessage> { true }) }
}
@Test
fun `GIVEN generic TangemSdkError WHEN handleScanError THEN no dialog sent`() = runTest {
val error: TangemSdkError = mockk(relaxed = true)
coEvery {
scanCardProcessor.scan(
analyticsSource = any(),
shouldCheckIsAlreadyActivated = any(),
cardId = any(),
onProgressStateChange = any(),
onWalletNotCreated = any(),
disclaimerWillShow = any(),
onCancel = any(),
onFailure = any(),
onSuccess = any()
)
} coAnswers {
val onFailure = arg<suspend (TangemError) -> Unit>(7)
onFailure.invoke(error)
}
val model = createModel(testScope = this, mode = CreateWalletStartComponent.Mode.ColdWallet)
advanceUntilIdle()
model.uiState.value.onScanClick.invoke()
advanceUntilIdle()
verify(exactly = 0) { uiMessageSender.send(any()) }
}
@Test
fun `GIVEN non-sdk TangemError WHEN handleScanError THEN no dialog sent`() = runTest {
val error: TangemError = mockk(relaxed = true)
coEvery {
scanCardProcessor.scan(
analyticsSource = any(),
shouldCheckIsAlreadyActivated = any(),
cardId = any(),
onProgressStateChange = any(),
onWalletNotCreated = any(),
disclaimerWillShow = any(),
onCancel = any(),
onFailure = any(),
onSuccess = any()
)
} coAnswers {
val onFailure = arg<suspend (TangemError) -> Unit>(7)
onFailure.invoke(error)
}
val model = createModel(testScope = this, mode = CreateWalletStartComponent.Mode.ColdWallet)
advanceUntilIdle()
model.uiState.value.onScanClick.invoke()
advanceUntilIdle()
verify(exactly = 0) { uiMessageSender.send(any()) }
}
@Test
fun `GIVEN builder returns null WHEN proceedWithScanResponse THEN saveWalletUseCase not called`() = runTest {
every { coldUserWalletBuilder.build() } returns null
coEvery {
scanCardProcessor.scan(
analyticsSource = any(),
shouldCheckIsAlreadyActivated = any(),
cardId = any(),
onProgressStateChange = any(),
onWalletNotCreated = any(),
disclaimerWillShow = any(),
onCancel = any(),
onFailure = any(),
onSuccess = any()
)
} coAnswers {
val onSuccess = arg<suspend (ScanResponse) -> Unit>(8)
onSuccess.invoke(testScanResponse)
}
val model = createModel(testScope = this, mode = CreateWalletStartComponent.Mode.ColdWallet)
advanceUntilIdle()
model.uiState.value.onScanClick.invoke()
advanceUntilIdle()
verify { coldUserWalletBuilderFactory.create(scanResponse = testScanResponse) }
coVerify(exactly = 0) { saveWalletUseCase(userWallet = any(), canOverride = any(), analyticsSource = any()) }
verify(exactly = 0) { appRouter.replaceAll(routes = anyVararg(), onComplete = any()) }
}
@Test
fun `GIVEN save returns WalletAlreadySaved WHEN proceedWithScanResponse THEN unlock called AND Wallet replaced`() =
runTest {
coEvery {
saveWalletUseCase(userWallet = any(), canOverride = any(), analyticsSource = any())
} returns SaveWalletError.WalletAlreadySaved(messageId = 0).left()
coEvery {
userWalletsListRepository.unlock(
userWalletId = testUserWalletId,
unlockMethod = any(),
)
} returns Unit.right()
coEvery {
scanCardProcessor.scan(
analyticsSource = any(),
shouldCheckIsAlreadyActivated = any(),
cardId = any(),
onProgressStateChange = any(),
onWalletNotCreated = any(),
disclaimerWillShow = any(),
onCancel = any(),
onFailure = any(),
onSuccess = any()
)
} coAnswers {
val onSuccess = arg<suspend (ScanResponse) -> Unit>(8)
onSuccess.invoke(testScanResponse)
}
val model = createModel(testScope = this, mode = CreateWalletStartComponent.Mode.ColdWallet)
advanceUntilIdle()
model.uiState.value.onScanClick.invoke()
advanceUntilIdle()
coVerify {
userWalletsListRepository.unlock(
userWalletId = testUserWalletId,
unlockMethod = UserWalletsListRepository.UnlockMethod.Scan(testScanResponse),
)
}
verify { appRouter.replaceAll(routes = arrayOf(AppRoute.Wallet), onComplete = any()) }
}
@Test
fun `GIVEN save returns DataError WHEN proceedWithScanResponse THEN no unlock AND no replace`() = runTest {
coEvery {
saveWalletUseCase(userWallet = any(), canOverride = any(), analyticsSource = any())
} returns SaveWalletError.DataError(messageId = 0).left()
coEvery {
scanCardProcessor.scan(
analyticsSource = any(),
shouldCheckIsAlreadyActivated = any(),
cardId = any(),
onProgressStateChange = any(),
onWalletNotCreated = any(),
disclaimerWillShow = any(),
onCancel = any(),
onFailure = any(),
onSuccess = any()
)
} coAnswers {
val onSuccess = arg<suspend (ScanResponse) -> Unit>(8)
onSuccess.invoke(testScanResponse)
}
val model = createModel(testScope = this, mode = CreateWalletStartComponent.Mode.ColdWallet)
advanceUntilIdle()
model.uiState.value.onScanClick.invoke()
advanceUntilIdle()
coVerify(exactly = 0) { userWalletsListRepository.unlock(any(), any()) }
verify(exactly = 0) { appRouter.replaceAll(routes = anyVararg(), onComplete = any()) }
}
@Test
fun `GIVEN save success AND isAddressSyncEnabled disabled WHEN proceedWithScanResponse THEN Wallet replaced`() =
runTest {
every { onboardingV2FeatureToggles.isAddressSyncEnabled } returns false
coEvery {
saveWalletUseCase(userWallet = any(), canOverride = any(), analyticsSource = any())
} returns Unit.right()
coEvery {
scanCardProcessor.scan(
analyticsSource = any(),
shouldCheckIsAlreadyActivated = any(),
cardId = any(),
onProgressStateChange = any(),
onWalletNotCreated = any(),
disclaimerWillShow = any(),
onCancel = any(),
onFailure = any(),
onSuccess = any()
)
} coAnswers {
val onSuccess = arg<suspend (ScanResponse) -> Unit>(8)
onSuccess.invoke(testScanResponse)
}
val model = createModel(testScope = this, mode = CreateWalletStartComponent.Mode.ColdWallet)
advanceUntilIdle()
model.uiState.value.onScanClick.invoke()
advanceUntilIdle()
verify { appRouter.replaceAll(routes = arrayOf(AppRoute.Wallet), onComplete = any()) }
}
@Test
fun `GIVEN save success AND isAddressSyncEnabled WHEN proceedWithScanResponse THEN AddressSync replaced`() =
runTest {
every { onboardingV2FeatureToggles.isAddressSyncEnabled } returns true
coEvery {
saveWalletUseCase(userWallet = any(), canOverride = any(), analyticsSource = any())
} returns Unit.right()
coEvery {
scanCardProcessor.scan(
analyticsSource = any(),
shouldCheckIsAlreadyActivated = any(),
cardId = any(),
onProgressStateChange = any(),
onWalletNotCreated = any(),
disclaimerWillShow = any(),
onCancel = any(),
onFailure = any(),
onSuccess = any()
)
} coAnswers {
val onSuccess = arg<suspend (ScanResponse) -> Unit>(8)
onSuccess.invoke(testScanResponse)
}
val model = createModel(testScope = this, mode = CreateWalletStartComponent.Mode.ColdWallet)
advanceUntilIdle()
model.uiState.value.onScanClick.invoke()
advanceUntilIdle()
verify { appRouter.replaceAll(routes = arrayOf(AppRoute.AddressSync), onComplete = any()) }
}
@Test
fun `WHEN model initialized THEN CreateWalletIntroScreenOpened event sent with referral id`() = runTest {
val refcode = "referralCode"
coEvery { appsFlyerStore.get() } returns AppsFlyerConversionData(refcode = refcode, campaign = null)
createModel(testScope = this, mode = CreateWalletStartComponent.Mode.ColdWallet)
advanceUntilIdle()
verify {
analyticsEventHandler.send(
match<IntroductionProcess.CreateWalletIntroScreenOpened> { true },
)
}
}
@Test
fun `WHEN ColdWallet WHEN get model THEN correct resources`() = runTest {
val model = createModel(testScope = this, mode = CreateWalletStartComponent.Mode.ColdWallet)
val state = model.uiState.value
assert(state.title == resourceReference(R.string.common_tangem_wallet))
assert(state.description == resourceReference(R.string.welcome_create_wallet_hardware_description))
assert(
state.featureItems == persistentListOf(
CreateWalletStartUM.FeatureItem(
iconResId = R.drawable.ic_shield_check_16,
text = resourceReference(R.string.welcome_create_wallet_feature_class),
),
CreateWalletStartUM.FeatureItem(
iconResId = R.drawable.ic_flash_16,
text = resourceReference(R.string.welcome_create_wallet_feature_delivery),
),
CreateWalletStartUM.FeatureItem(
iconResId = R.drawable.ic_sparkles_16,
text = resourceReference(R.string.welcome_create_wallet_feature_use),
)
)
)
assert(state.imageResId == R.drawable.img_hardware_wallet)
assert(state.shouldShowScanSecondaryButton)
assert(state.primaryButtonText == resourceReference(R.string.details_buy_wallet),)
assert(state.otherMethodTitle == resourceReference(R.string.welcome_create_wallet_mobile_title),)
assert(state.otherMethodDescription == null,)
assert(state.isScanInProgress.not())
}
@Test
fun `WHEN HotWallet WHEN get model THEN correct resources`() = runTest {
val model = createModel(testScope = this, mode = CreateWalletStartComponent.Mode.HotWallet)
val state = model.uiState.value
assert(state.title == resourceReference(R.string.hw_mobile_wallet))
assert(state.description == resourceReference(R.string.welcome_create_wallet_mobile_description_full))
assert(
state.featureItems == persistentListOf(
CreateWalletStartUM.FeatureItem(
iconResId = R.drawable.ic_shield_check_16,
text = resourceReference(R.string.welcome_create_wallet_feature_seamless),
),
CreateWalletStartUM.FeatureItem(
iconResId = R.drawable.ic_flash_16,
text = resourceReference(R.string.welcome_create_wallet_feature_one_tap),
),
CreateWalletStartUM.FeatureItem(
iconResId = R.drawable.ic_stack_fill_new_16,
text = resourceReference(R.string.welcome_create_wallet_feature_assets),
),
)
)
assert(state.imageResId == R.drawable.img_mobile_wallet)
assert(state.shouldShowScanSecondaryButton.not())
assert(state.primaryButtonText == resourceReference(R.string.welcome_create_wallet_mobile_title))
assert(state.otherMethodTitle == resourceReference(R.string.welcome_create_wallet_use_hardware_title))
assert(state.otherMethodDescription == resourceReference(R.string.welcome_create_wallet_use_hardware_description))
assert(state.isScanInProgress.not())
}
private fun createModel(
testScope: TestScope,
mode: CreateWalletStartComponent.Mode,
paramsContainer: ParamsContainer = MutableParamsContainer(
value = CreateWalletStartComponent.Params(mode = mode)
),
): CreateWalletStartModel {
return CreateWalletStartModel(
paramsContainer = paramsContainer,
dispatchers = testScope.createTestingCoroutineDispatcherProvider(),
router = router,
scanCardProcessor = scanCardProcessor,
cardSdkConfigRepository = cardSdkConfigRepository,
settingsRepository = settingsRepository,
appRouter = appRouter,
coldUserWalletBuilderFactory = coldUserWalletBuilderFactory,
saveWalletUseCase = saveWalletUseCase,
isHotWalletCreationSupported = isHotWalletCreationSupported,
userWalletsListRepository = userWalletsListRepository,
uiMessageSender = uiMessageSender,
generateBuyTangemCardLinkUseCase = generateBuyTangemCardLinkUseCase,
urlOpener = urlOpener,
trackingContextProxy = trackingContextProxy,
analyticsEventHandler = analyticsEventHandler,
appsFlyerStore = appsFlyerStore,
onboardingV2FeatureToggles = onboardingV2FeatureToggles,
)
}
private fun TestScope.createTestingCoroutineDispatcherProvider(): TestingCoroutineDispatcherProvider {
val testDispatcher = StandardTestDispatcher(testScheduler)
return TestingCoroutineDispatcherProvider(
main = testDispatcher,
mainImmediate = testDispatcher,
io = testDispatcher,
default = testDispatcher,
single = testDispatcher,
)
}
}