Updated on 2026-08-14

This commit is contained in:
Tangem 2026-07-09 08:02:24 -07:00
parent e1c58bed0e
commit 8d37a2bc1f
20 changed files with 470 additions and 54 deletions

View file

@ -8,4 +8,11 @@ import com.tangem.domain.visa.error.VisaApiError
interface TangemPayTariffPlanTransitionsRepository {
suspend fun getTransitions(userWalletId: UserWalletId): Either<VisaApiError, List<TangemPayTariffPlanTransition>>
suspend fun setPendingTransition(
userWalletId: UserWalletId,
pendingTariffPlanId: String,
): Either<VisaApiError, Unit>
suspend fun cancelPendingTransition(userWalletId: UserWalletId): Either<VisaApiError, Unit>
}

View file

@ -0,0 +1,19 @@
package com.tangem.domain.pay.usecase
import arrow.core.Either
import arrow.core.raise.either
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.pay.flow.PaymentAccountStatusFetcher
import com.tangem.domain.pay.repository.TangemPayTariffPlanTransitionsRepository
import com.tangem.domain.visa.error.VisaApiError
class CancelTariffPlanPendingTransitionUseCase(
private val repository: TangemPayTariffPlanTransitionsRepository,
private val paymentAccountStatusFetcher: PaymentAccountStatusFetcher,
) {
suspend operator fun invoke(userWalletId: UserWalletId): Either<VisaApiError, Unit> = either {
repository.cancelPendingTransition(userWalletId).bind()
paymentAccountStatusFetcher.invoke(userWalletId)
}
}

View file

@ -0,0 +1,20 @@
package com.tangem.domain.pay.usecase
import arrow.core.Either
import arrow.core.raise.either
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.pay.flow.PaymentAccountStatusFetcher
import com.tangem.domain.pay.repository.TangemPayTariffPlanTransitionsRepository
import com.tangem.domain.visa.error.VisaApiError
class SetTariffPlanPendingTransitionUseCase(
private val repository: TangemPayTariffPlanTransitionsRepository,
private val paymentAccountStatusFetcher: PaymentAccountStatusFetcher,
) {
suspend operator fun invoke(userWalletId: UserWalletId, pendingTariffPlanId: String): Either<VisaApiError, Unit> =
either {
repository.setPendingTransition(userWalletId, pendingTariffPlanId).bind()
paymentAccountStatusFetcher.invoke(userWalletId)
}
}

View file

@ -0,0 +1,56 @@
package com.tangem.domain.pay.usecase
import arrow.core.left
import arrow.core.right
import com.google.common.truth.Truth.assertThat
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.pay.flow.PaymentAccountStatusFetcher
import com.tangem.domain.pay.repository.TangemPayTariffPlanTransitionsRepository
import com.tangem.domain.visa.error.VisaApiError
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.mockk
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
internal class CancelTariffPlanPendingTransitionUseCaseTest {
private val repository: TangemPayTariffPlanTransitionsRepository = mockk()
private val paymentAccountStatusFetcher: PaymentAccountStatusFetcher = mockk()
private val useCase = CancelTariffPlanPendingTransitionUseCase(
repository = repository,
paymentAccountStatusFetcher = paymentAccountStatusFetcher,
)
@Test
fun `GIVEN cancelPendingTransition fails WHEN invoke THEN returns Left and skips fetch`() = runTest {
// GIVEN
coEvery { repository.cancelPendingTransition(USER_WALLET_ID) } returns VisaApiError.Unspecified.left()
// WHEN
val result = useCase(USER_WALLET_ID)
// THEN
assertThat(result.leftOrNull()).isEqualTo(VisaApiError.Unspecified)
coVerify(exactly = 0) { paymentAccountStatusFetcher.invoke(any<UserWalletId>()) }
}
@Test
fun `GIVEN cancelPendingTransition succeeds WHEN invoke THEN refreshes account status`() = runTest {
// GIVEN
coEvery { repository.cancelPendingTransition(USER_WALLET_ID) } returns Unit.right()
coEvery { paymentAccountStatusFetcher.invoke(USER_WALLET_ID) } returns Unit.right()
// WHEN
val result = useCase(USER_WALLET_ID)
// THEN
assertThat(result.isRight()).isTrue()
coVerify(exactly = 1) { paymentAccountStatusFetcher.invoke(USER_WALLET_ID) }
}
private companion object {
val USER_WALLET_ID = UserWalletId("aabbcc112233")
}
}

View file

@ -0,0 +1,59 @@
package com.tangem.domain.pay.usecase
import arrow.core.left
import arrow.core.right
import com.google.common.truth.Truth.assertThat
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.pay.flow.PaymentAccountStatusFetcher
import com.tangem.domain.pay.repository.TangemPayTariffPlanTransitionsRepository
import com.tangem.domain.visa.error.VisaApiError
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.mockk
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
internal class SetTariffPlanPendingTransitionUseCaseTest {
private val repository: TangemPayTariffPlanTransitionsRepository = mockk()
private val paymentAccountStatusFetcher: PaymentAccountStatusFetcher = mockk()
private val useCase = SetTariffPlanPendingTransitionUseCase(
repository = repository,
paymentAccountStatusFetcher = paymentAccountStatusFetcher,
)
@Test
fun `GIVEN setPendingTransition fails WHEN invoke THEN returns Left and skips fetch`() = runTest {
// GIVEN
coEvery {
repository.setPendingTransition(USER_WALLET_ID, PENDING_PLAN_ID)
} returns VisaApiError.Unspecified.left()
// WHEN
val result = useCase(USER_WALLET_ID, PENDING_PLAN_ID)
// THEN
assertThat(result.leftOrNull()).isEqualTo(VisaApiError.Unspecified)
coVerify(exactly = 0) { paymentAccountStatusFetcher.invoke(any<UserWalletId>()) }
}
@Test
fun `GIVEN setPendingTransition succeeds WHEN invoke THEN refreshes account status`() = runTest {
// GIVEN
coEvery { repository.setPendingTransition(USER_WALLET_ID, PENDING_PLAN_ID) } returns Unit.right()
coEvery { paymentAccountStatusFetcher.invoke(USER_WALLET_ID) } returns Unit.right()
// WHEN
val result = useCase(USER_WALLET_ID, PENDING_PLAN_ID)
// THEN
assertThat(result.isRight()).isTrue()
coVerify(exactly = 1) { paymentAccountStatusFetcher.invoke(USER_WALLET_ID) }
}
private companion object {
val USER_WALLET_ID = UserWalletId("aabbcc112233")
const val PENDING_PLAN_ID = "plan-basic"
}
}