Updated on 2026-08-14
This commit is contained in:
parent
92bf1fa521
commit
0adc20d9aa
3 changed files with 154 additions and 8 deletions
|
|
@ -61,4 +61,15 @@ dependencies {
|
|||
|
||||
/** Other */
|
||||
implementation(deps.kotlin.immutable.collections)
|
||||
|
||||
/** Test */
|
||||
testRuntimeOnly(deps.test.junit5.engine)
|
||||
testImplementation(deps.test.junit5)
|
||||
testImplementation(deps.test.mockk)
|
||||
testImplementation(deps.test.truth)
|
||||
testImplementation(deps.test.coroutine)
|
||||
}
|
||||
|
||||
tasks.withType<Test>().configureEach {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
|
@ -112,6 +112,7 @@ internal class TangemPayCardLimitSetupModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun onAmountChange(newValue: String) {
|
||||
if (newValue.toBigDecimalOrNull() == null) return
|
||||
uiState.update { state ->
|
||||
state.copy(
|
||||
amountFieldModel = state.amountFieldModel.copy(value = newValue),
|
||||
|
|
@ -121,9 +122,7 @@ internal class TangemPayCardLimitSetupModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun onPresetClick(preset: BigDecimal) {
|
||||
val amount = uiState.value.amountFieldModel.value.toBigDecimalOrNull() ?: return
|
||||
val newAmount = if (preset == BigDecimal.ZERO) BigDecimal.ZERO else amount + preset
|
||||
onAmountChange(newAmount.stripTrailingZeros().toPlainString())
|
||||
onAmountChange(preset.stripTrailingZeros().toPlainString())
|
||||
}
|
||||
|
||||
private fun onSubmitClick() {
|
||||
|
|
@ -154,7 +153,7 @@ internal class TangemPayCardLimitSetupModel @Inject constructor(
|
|||
|
||||
private fun isValid(value: String): Boolean {
|
||||
val amount = value.toBigDecimalOrNull() ?: return false
|
||||
return amount >= BigDecimal.ZERO
|
||||
return amount >= MIN_LIMIT
|
||||
}
|
||||
|
||||
private fun buildSubtitle(maxLimit: BigDecimal?, currency: Currency): TextReference {
|
||||
|
|
@ -163,7 +162,7 @@ internal class TangemPayCardLimitSetupModel @Inject constructor(
|
|||
id = R.string.tangempay_card_limit_setup_amount_subtitle,
|
||||
formatArgs = WrappedList(
|
||||
listOf(
|
||||
BigDecimal.ZERO.format { fiat(currency.currencyCode, currency.symbol).anyDecimals(0) },
|
||||
MIN_LIMIT.format { fiat(currency.currencyCode, currency.symbol).anyDecimals(0) },
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
@ -172,7 +171,7 @@ internal class TangemPayCardLimitSetupModel @Inject constructor(
|
|||
id = R.string.tangempay_daily_limit_hint,
|
||||
formatArgs = WrappedList(
|
||||
listOf(
|
||||
BigDecimal.ZERO.format { fiat(currency.currencyCode, currency.symbol).anyDecimals(0) },
|
||||
MIN_LIMIT.format { fiat(currency.currencyCode, currency.symbol).anyDecimals(0) },
|
||||
maxLimit.format { fiat(currency.currencyCode, currency.symbol).anyDecimals(0) },
|
||||
),
|
||||
),
|
||||
|
|
@ -181,15 +180,19 @@ internal class TangemPayCardLimitSetupModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun buildPresets(currency: Currency) = listOf(
|
||||
BigDecimal.ZERO,
|
||||
MIN_LIMIT,
|
||||
BigDecimal("5000"),
|
||||
BigDecimal("10000"),
|
||||
BigDecimal("25000"),
|
||||
).map { preset ->
|
||||
val label = preset.format { fiat(currency.currencyCode, currency.symbol).anyDecimals(0) }
|
||||
TangemPayCardLimitSetupUM.LimitPresetUM(
|
||||
label = if (preset == BigDecimal.ZERO) "0" else "+$label",
|
||||
label = label,
|
||||
onClick = { onPresetClick(preset) },
|
||||
)
|
||||
}.toPersistentList()
|
||||
|
||||
companion object {
|
||||
private val MIN_LIMIT = BigDecimal.ONE
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
package com.tangem.features.tangempay.limit.setup
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.tangem.core.decompose.model.MutableParamsContainer
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.account.PaymentAccountStatusValue
|
||||
import com.tangem.domain.models.pay.TangemPayCard
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.pay.TangemPayDetailsConfig
|
||||
import com.tangem.domain.pay.flow.PaymentAccountStatusSupplier
|
||||
import com.tangem.domain.pay.usecase.SetTangemPayCardLimitUseCase
|
||||
import com.tangem.domain.visa.model.TangemPayCardFrozenState
|
||||
import com.tangem.features.tangempay.components.TangemPayDetailsContainerComponent
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import org.junit.jupiter.api.Nested
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.params.ParameterizedTest
|
||||
import org.junit.jupiter.params.provider.Arguments
|
||||
import org.junit.jupiter.params.provider.MethodSource
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
internal class TangemPayCardLimitSetupModelTest {
|
||||
|
||||
private val cardId = "test_card_id"
|
||||
private val userWalletId = UserWalletId("123")
|
||||
|
||||
private val router: Router = mockk(relaxed = true)
|
||||
private val uiMessageSender: UiMessageSender = mockk(relaxed = true)
|
||||
private val setLimitUseCase: SetTangemPayCardLimitUseCase = mockk(relaxed = true)
|
||||
private val paymentAccountStatusSupplier: PaymentAccountStatusSupplier = mockk()
|
||||
|
||||
private val params = TangemPayDetailsContainerComponent.Params(
|
||||
userWalletId = userWalletId,
|
||||
config = TangemPayDetailsConfig(
|
||||
customerId = "customer1",
|
||||
cardId = cardId,
|
||||
isPinSet = false,
|
||||
cardFrozenState = TangemPayCardFrozenState.Unfrozen,
|
||||
cardNumberEnd = "1234",
|
||||
chainId = 1,
|
||||
isTangemPayDeactivated = false,
|
||||
displayName = null,
|
||||
),
|
||||
)
|
||||
|
||||
private val testCard = TangemPayCard(
|
||||
id = cardId,
|
||||
hasPinCode = false,
|
||||
displayName = null,
|
||||
limit = null,
|
||||
isFrozen = false,
|
||||
lastDigits = "1234",
|
||||
)
|
||||
|
||||
private val loadedStatus: PaymentAccountStatusValue.Loaded = mockk(relaxed = true) {
|
||||
every { source } returns StatusSource.ACTUAL
|
||||
every { cards } returns listOf(testCard)
|
||||
every { currencyCode } returns "USD"
|
||||
}
|
||||
|
||||
private val paymentStatus: AccountStatus.Payment = mockk(relaxed = true) {
|
||||
every { value } returns loadedStatus
|
||||
}
|
||||
|
||||
private fun createModel(): TangemPayCardLimitSetupModel {
|
||||
every { paymentAccountStatusSupplier.invoke(userWalletId) } returns flowOf(paymentStatus)
|
||||
return TangemPayCardLimitSetupModel(
|
||||
paramsContainer = MutableParamsContainer(params),
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
router = router,
|
||||
paymentAccountStatusSupplier = paymentAccountStatusSupplier,
|
||||
setTangemPayCardLimitUseCase = setLimitUseCase,
|
||||
uiMessageSender = uiMessageSender,
|
||||
)
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCases")
|
||||
fun `GIVEN amount WHEN changed THEN submit button reflects validity`(
|
||||
amount: String,
|
||||
expectedEnabled: Boolean,
|
||||
) {
|
||||
val model = createModel()
|
||||
|
||||
model.uiState.value.amountFieldModel.onValueChange(amount)
|
||||
|
||||
assertThat(model.uiState.value.isSubmitButtonEnabled).isEqualTo(expectedEnabled)
|
||||
model.onDestroy()
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
inner class Presets {
|
||||
|
||||
@Test
|
||||
fun `WHEN first preset clicked THEN amount set to MIN_LIMIT`() {
|
||||
val model = createModel()
|
||||
|
||||
model.uiState.value.presets.first().onClick()
|
||||
|
||||
assertThat(model.uiState.value.amountFieldModel.value).isEqualTo("1")
|
||||
model.onDestroy()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN last preset clicked THEN amount set to 5000`() {
|
||||
val model = createModel()
|
||||
|
||||
model.uiState.value.presets.last().onClick()
|
||||
|
||||
assertThat(model.uiState.value.amountFieldModel.value).isEqualTo("25000")
|
||||
model.onDestroy()
|
||||
}
|
||||
}
|
||||
|
||||
private fun provideTestCases() = listOf(
|
||||
Arguments.of("0", false),
|
||||
Arguments.of("0.99", false),
|
||||
Arguments.of("1", true),
|
||||
Arguments.of("100", true),
|
||||
Arguments.of("-1", false),
|
||||
Arguments.of("", false),
|
||||
Arguments.of("abc", false),
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue