NTP-65855 | bbps unit test base class setup and added example usage (#16392)
Co-authored-by: Kishan Kumar <kishan.kumar@navi.com>
This commit is contained in:
@@ -339,7 +339,7 @@ constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateConsentProvided(isConsentProvided: Boolean) {
|
fun updateConsentProvided(isConsentProvided: Boolean) {
|
||||||
_isConsentProvided.update { isConsentProvided }
|
_isConsentProvided.update { isConsentProvided }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,7 +363,7 @@ constructor(
|
|||||||
_payBillScreenState.update { payBillScreenState }
|
_payBillScreenState.update { payBillScreenState }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updatePayBillHeaderState(payBillHeaderState: PayBillHeaderState) {
|
fun updatePayBillHeaderState(payBillHeaderState: PayBillHeaderState) {
|
||||||
_payBillHeaderState.update { payBillHeaderState }
|
_payBillHeaderState.update { payBillHeaderState }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* * Copyright © 2025 by Navi Technologies Limited
|
||||||
|
* * All rights reserved. Strictly confidential
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.navi.bbps.base
|
||||||
|
|
||||||
|
import com.navi.common.di.CoroutineDispatcherProvider
|
||||||
|
import io.mockk.MockKAnnotations
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||||
|
import kotlinx.coroutines.test.TestCoroutineScheduler
|
||||||
|
import kotlinx.coroutines.test.TestDispatcher
|
||||||
|
import kotlinx.coroutines.test.TestScope
|
||||||
|
import kotlinx.coroutines.test.resetMain
|
||||||
|
import kotlinx.coroutines.test.setMain
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Before
|
||||||
|
|
||||||
|
abstract class NaviBbpsBaseTest {
|
||||||
|
// Coroutine testing utilities
|
||||||
|
private val testScheduler = TestCoroutineScheduler()
|
||||||
|
val testDispatcher = StandardTestDispatcher(scheduler = testScheduler)
|
||||||
|
val testScope = TestScope(testDispatcher)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test implementation of CoroutineDispatcherProvider that uses a single test dispatcher for all
|
||||||
|
* coroutine contexts to make testing deterministic.
|
||||||
|
*/
|
||||||
|
class TestCoroutineDispatcherProvider(private val testDispatcher: TestDispatcher) :
|
||||||
|
CoroutineDispatcherProvider {
|
||||||
|
override val default: CoroutineDispatcher
|
||||||
|
get() = testDispatcher
|
||||||
|
|
||||||
|
override val main: CoroutineDispatcher
|
||||||
|
get() = testDispatcher
|
||||||
|
|
||||||
|
override val io: CoroutineDispatcher
|
||||||
|
get() = testDispatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up the test environment before each test.
|
||||||
|
* 1. Configure Dispatchers.Main to use our test dispatcher
|
||||||
|
* 2. Initialize mock annotations
|
||||||
|
*/
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
@Before
|
||||||
|
open fun setUp() {
|
||||||
|
// Configure the main dispatcher for testing
|
||||||
|
Dispatchers.setMain(testDispatcher)
|
||||||
|
|
||||||
|
// Initialize MockK annotations with relaxed behavior
|
||||||
|
MockKAnnotations.init(this, relaxed = true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up after each test to avoid affecting other tests. Reset the main dispatcher to its
|
||||||
|
* original state.
|
||||||
|
*/
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
@After
|
||||||
|
open fun tearDown() {
|
||||||
|
Dispatchers.resetMain()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ package com.navi.bbps.common.viewmodel
|
|||||||
|
|
||||||
import com.navi.base.utils.NaviNetworkConnectivity
|
import com.navi.base.utils.NaviNetworkConnectivity
|
||||||
import com.navi.base.utils.ResourceProvider
|
import com.navi.base.utils.ResourceProvider
|
||||||
|
import com.navi.bbps.base.NaviBbpsBaseTest
|
||||||
import com.navi.bbps.common.gmail.signin.GmailAccessSignInManager.Companion.GMAIL_READ_ONLY_SCOPE
|
import com.navi.bbps.common.gmail.signin.GmailAccessSignInManager.Companion.GMAIL_READ_ONLY_SCOPE
|
||||||
import com.navi.bbps.common.model.config.NaviBbpsDefaultConfig
|
import com.navi.bbps.common.model.config.NaviBbpsDefaultConfig
|
||||||
import com.navi.bbps.common.model.network.BillDetectionResponse
|
import com.navi.bbps.common.model.network.BillDetectionResponse
|
||||||
@@ -17,23 +18,12 @@ import com.navi.bbps.common.model.view.DetectedBillEntity
|
|||||||
import com.navi.bbps.common.model.view.FullScreenLoaderState
|
import com.navi.bbps.common.model.view.FullScreenLoaderState
|
||||||
import com.navi.bbps.feature.detectedbills.DetectedBillsRepository
|
import com.navi.bbps.feature.detectedbills.DetectedBillsRepository
|
||||||
import com.navi.bbps.feature.mybills.MyBillsSyncJob
|
import com.navi.bbps.feature.mybills.MyBillsSyncJob
|
||||||
import com.navi.common.di.CoroutineDispatcherProvider
|
|
||||||
import com.navi.common.network.models.GenericErrorResponse
|
import com.navi.common.network.models.GenericErrorResponse
|
||||||
import com.navi.common.network.models.RepoResult
|
import com.navi.common.network.models.RepoResult
|
||||||
import io.mockk.MockKAnnotations
|
|
||||||
import io.mockk.coEvery
|
import io.mockk.coEvery
|
||||||
import io.mockk.impl.annotations.MockK
|
import io.mockk.impl.annotations.MockK
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
||||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
|
||||||
import kotlinx.coroutines.test.TestCoroutineScheduler
|
|
||||||
import kotlinx.coroutines.test.TestDispatcher
|
|
||||||
import kotlinx.coroutines.test.TestScope
|
|
||||||
import kotlinx.coroutines.test.resetMain
|
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import kotlinx.coroutines.test.setMain
|
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Assert.assertFalse
|
import org.junit.Assert.assertFalse
|
||||||
@@ -49,8 +39,7 @@ import org.junit.Test
|
|||||||
* - The startDetectingBills method with different scenarios
|
* - The startDetectingBills method with different scenarios
|
||||||
* - Various helper functions within the handler
|
* - Various helper functions within the handler
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
class OriginBillDetectionHandlerTest : NaviBbpsBaseTest() {
|
||||||
class OriginBillDetectionHandlerTest {
|
|
||||||
// Dependencies to be mocked
|
// Dependencies to be mocked
|
||||||
@MockK private lateinit var detectedBillsRepository: DetectedBillsRepository
|
@MockK private lateinit var detectedBillsRepository: DetectedBillsRepository
|
||||||
@MockK private lateinit var resourceProvider: ResourceProvider
|
@MockK private lateinit var resourceProvider: ResourceProvider
|
||||||
@@ -60,46 +49,12 @@ class OriginBillDetectionHandlerTest {
|
|||||||
// Class under test
|
// Class under test
|
||||||
private lateinit var handler: OriginBillDetectionHandler
|
private lateinit var handler: OriginBillDetectionHandler
|
||||||
|
|
||||||
// Coroutine testing utilities
|
|
||||||
private val testScheduler = TestCoroutineScheduler()
|
|
||||||
private val testDispatcher = StandardTestDispatcher(scheduler = testScheduler)
|
|
||||||
private val testScope = TestScope(testDispatcher)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test implementation of CoroutineDispatcherProvider that uses a single test dispatcher for all
|
|
||||||
* coroutine contexts to make testing deterministic.
|
|
||||||
*/
|
|
||||||
class TestCoroutineDispatcherProviderImpl(private val testDispatcher: TestDispatcher) :
|
|
||||||
CoroutineDispatcherProvider {
|
|
||||||
override val default: CoroutineDispatcher
|
|
||||||
get() = testDispatcher
|
|
||||||
|
|
||||||
override val main: CoroutineDispatcher
|
|
||||||
get() = testDispatcher
|
|
||||||
|
|
||||||
override val io: CoroutineDispatcher
|
|
||||||
get() = testDispatcher
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set up the test environment before each test.
|
|
||||||
* 1. Configure Dispatchers.Main to use our test dispatcher
|
|
||||||
* 2. Initialize mock annotations
|
|
||||||
* 3. Create the handler instance with test dependencies
|
|
||||||
*/
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
override fun setUp() {
|
||||||
// Configure the main dispatcher for testing
|
super.setUp()
|
||||||
Dispatchers.setMain(testDispatcher)
|
|
||||||
|
|
||||||
// Initialize MockK annotations with relaxed behavior
|
|
||||||
MockKAnnotations.init(this, relaxed = true)
|
|
||||||
|
|
||||||
// Initialize the handler with test dependencies
|
|
||||||
handler =
|
handler =
|
||||||
OriginBillDetectionHandler(
|
OriginBillDetectionHandler(
|
||||||
coroutineDispatcherProvider = TestCoroutineDispatcherProviderImpl(testDispatcher),
|
coroutineDispatcherProvider = TestCoroutineDispatcherProvider(testDispatcher),
|
||||||
detectedBillsRepository = detectedBillsRepository,
|
detectedBillsRepository = detectedBillsRepository,
|
||||||
resourceProvider = resourceProvider,
|
resourceProvider = resourceProvider,
|
||||||
naviNetworkConnectivity = naviNetworkConnectivity,
|
naviNetworkConnectivity = naviNetworkConnectivity,
|
||||||
@@ -367,8 +322,8 @@ class OriginBillDetectionHandlerTest {
|
|||||||
* original state.
|
* original state.
|
||||||
*/
|
*/
|
||||||
@After
|
@After
|
||||||
fun tearDown() {
|
override fun tearDown() {
|
||||||
Dispatchers.resetMain()
|
super.tearDown()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,526 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* * Copyright © 2024-2025 by Navi Technologies Limited
|
||||||
|
* * All rights reserved. Strictly confidential
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.navi.bbps.feature.paybill
|
||||||
|
|
||||||
|
import androidx.lifecycle.SavedStateHandle
|
||||||
|
import com.navi.base.utils.NaviNetworkConnectivity
|
||||||
|
import com.navi.base.utils.ResourceProvider
|
||||||
|
import com.navi.bbps.base.NaviBbpsBaseTest
|
||||||
|
import com.navi.bbps.common.CoinsSyncManager
|
||||||
|
import com.navi.bbps.common.model.config.NaviBbpsDefaultConfig
|
||||||
|
import com.navi.bbps.common.repository.BbpsCommonRepository
|
||||||
|
import com.navi.bbps.common.session.NaviBbpsSessionHelper
|
||||||
|
import com.navi.bbps.common.session.ZeroPlatformFeeBottomSheetViewTracker
|
||||||
|
import com.navi.bbps.common.usecase.FetchBillHandler
|
||||||
|
import com.navi.bbps.common.usecase.NaviBbpsConfigUseCase
|
||||||
|
import com.navi.bbps.common.usecase.RewardNudgeUseCase
|
||||||
|
import com.navi.bbps.common.utils.NaviBbpsDateUtils
|
||||||
|
import com.navi.bbps.common.utils.getDefaultConfig
|
||||||
|
import com.navi.bbps.feature.category.BillCategoriesRepository
|
||||||
|
import com.navi.bbps.feature.category.model.view.BillCategoryEntity
|
||||||
|
import com.navi.bbps.feature.contactlist.model.view.PhoneContactEntity
|
||||||
|
import com.navi.bbps.feature.customerinput.model.view.BillDetailsEntity
|
||||||
|
import com.navi.bbps.feature.customerinput.model.view.BillerAdditionalParamsEntity
|
||||||
|
import com.navi.bbps.feature.customerinput.model.view.BillerDetailsEntity
|
||||||
|
import com.navi.bbps.feature.mybills.MyBillsRepository
|
||||||
|
import com.navi.bbps.feature.mybills.model.view.MyBillEntity
|
||||||
|
import com.navi.bbps.feature.paybill.helper.BbpsArcHelper
|
||||||
|
import com.navi.bbps.feature.paybill.helper.NotifyDuplicatePaymentHandler
|
||||||
|
import com.navi.bbps.feature.paybill.helper.PayBillAmountChipsHelper
|
||||||
|
import com.navi.bbps.feature.paybill.model.view.PayBillHeaderState
|
||||||
|
import com.navi.bbps.feature.paybill.model.view.PayBillSource
|
||||||
|
import com.navi.common.usecase.LitmusExperimentsUseCase
|
||||||
|
import com.navi.payment.nativepayment.utils.NaviPaymentRewardsEventBus
|
||||||
|
import com.navi.payment.tstore.repository.TStoreOrderHandler
|
||||||
|
import io.mockk.coEvery
|
||||||
|
import io.mockk.coVerify
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.impl.annotations.MockK
|
||||||
|
import io.mockk.invoke
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.mockkStatic
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.json.JSONObject
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Assert.assertFalse
|
||||||
|
import org.junit.Assert.assertNotNull
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for PayBillViewModel.
|
||||||
|
*
|
||||||
|
* Tests cover important functionality including:
|
||||||
|
* - Credit card payment option handling
|
||||||
|
* - Bill fetch behavior via BillFetchHandler
|
||||||
|
* - Payment processing
|
||||||
|
* - Validation logic
|
||||||
|
*/
|
||||||
|
class PayBillViewModelTest : NaviBbpsBaseTest() {
|
||||||
|
@MockK private lateinit var savedStateHandle: SavedStateHandle
|
||||||
|
@MockK private lateinit var payBillRepository: PayBillRepository
|
||||||
|
@MockK private lateinit var naviBbpsDateUtils: NaviBbpsDateUtils
|
||||||
|
@MockK private lateinit var resourceProvider: ResourceProvider
|
||||||
|
@MockK private lateinit var billCategoriesRepository: BillCategoriesRepository
|
||||||
|
@MockK private lateinit var myBillsRepository: MyBillsRepository
|
||||||
|
@MockK private lateinit var naviBbpsCommonRepository: BbpsCommonRepository
|
||||||
|
@MockK private lateinit var naviNetworkConnectivity: NaviNetworkConnectivity
|
||||||
|
@MockK private lateinit var naviBbpsSessionHelper: NaviBbpsSessionHelper
|
||||||
|
@MockK private lateinit var fetchBillHandler: FetchBillHandler
|
||||||
|
@MockK private lateinit var coinsSyncManager: CoinsSyncManager
|
||||||
|
@MockK
|
||||||
|
private lateinit var zeroPlatformFeeBottomSheetViewTracker:
|
||||||
|
ZeroPlatformFeeBottomSheetViewTracker
|
||||||
|
@MockK private lateinit var litmusExperimentsUseCase: LitmusExperimentsUseCase
|
||||||
|
@MockK private lateinit var naviBbpsConfigUseCase: NaviBbpsConfigUseCase
|
||||||
|
@MockK private lateinit var rewardsNudgeEntityFetchUseCase: RewardNudgeUseCase
|
||||||
|
@MockK private lateinit var tStoreOrderHandler: TStoreOrderHandler
|
||||||
|
@MockK private lateinit var resProvider: ResourceProvider
|
||||||
|
@MockK private lateinit var naviPaymentRewardEventBus: NaviPaymentRewardsEventBus
|
||||||
|
@MockK private lateinit var payBillAmountChipsHelper: PayBillAmountChipsHelper
|
||||||
|
@MockK private lateinit var bbpsArcHelper: BbpsArcHelper
|
||||||
|
@MockK private lateinit var notifyDuplicatePaymentHandler: NotifyDuplicatePaymentHandler
|
||||||
|
|
||||||
|
private lateinit var viewModel: PayBillViewModel
|
||||||
|
|
||||||
|
@Before
|
||||||
|
override fun setUp() {
|
||||||
|
super.setUp()
|
||||||
|
|
||||||
|
every { naviBbpsSessionHelper.getNaviBbpsSessionAttributes() } returns HashMap()
|
||||||
|
every { naviNetworkConnectivity.isInternetConnected() } returns true
|
||||||
|
|
||||||
|
val mockDefaultConfig = mockk<NaviBbpsDefaultConfig>(relaxed = true)
|
||||||
|
mockkStatic("com.navi.bbps.common.utils.ConfigExtKt")
|
||||||
|
coEvery { naviBbpsConfigUseCase.getDefaultConfig(any()) } returns mockDefaultConfig
|
||||||
|
|
||||||
|
val mockBillerDetailsEntity = mockk<BillerDetailsEntity>(relaxed = true)
|
||||||
|
val payBillSource =
|
||||||
|
PayBillSource.Others(
|
||||||
|
billerDetailsEntity = mockBillerDetailsEntity,
|
||||||
|
billDetailsEntity = null,
|
||||||
|
customerParams = mapOf(),
|
||||||
|
formattedLastPaidDate = "",
|
||||||
|
formattedLastPaidAmount = "",
|
||||||
|
billerId = "test_biller_id",
|
||||||
|
amount = "100.00",
|
||||||
|
isConsentRequired = false,
|
||||||
|
)
|
||||||
|
every { savedStateHandle.get<PayBillSource>("payBillScreenSource") } returns payBillSource
|
||||||
|
|
||||||
|
val billCategoryEntity =
|
||||||
|
BillCategoryEntity(
|
||||||
|
categoryId = "test_category_id",
|
||||||
|
title = "Test Category",
|
||||||
|
iconUrl = "https://example.com/icon.png",
|
||||||
|
searchBoxPlaceholderText = "Search billers",
|
||||||
|
billerListStateHeading = "Popular billers",
|
||||||
|
billerListAllHeading = "All billers",
|
||||||
|
reminderTitle = "Set reminder",
|
||||||
|
)
|
||||||
|
every { savedStateHandle.get<BillCategoryEntity>("billCategoryEntity") } returns
|
||||||
|
billCategoryEntity
|
||||||
|
|
||||||
|
val phoneContactEntity = mockk<PhoneContactEntity>(relaxed = true)
|
||||||
|
every { savedStateHandle.get<PhoneContactEntity>("phoneNumberDetail") } returns
|
||||||
|
phoneContactEntity
|
||||||
|
|
||||||
|
every { savedStateHandle.get<Boolean>("isRootScreen") } returns true
|
||||||
|
every { savedStateHandle.get<Boolean>("isBillSyncRequiredInBackground") } returns false
|
||||||
|
every { savedStateHandle.get<String>("source") } returns "test_source"
|
||||||
|
every { savedStateHandle.get<String>("initialSource") } returns "test_initial_source"
|
||||||
|
|
||||||
|
val naviBbpsDefaultConfig = mockk<NaviBbpsDefaultConfig>(relaxed = true)
|
||||||
|
coEvery { naviBbpsConfigUseCase.getDefaultConfig(screenName = "Pay bill") } returns
|
||||||
|
naviBbpsDefaultConfig
|
||||||
|
|
||||||
|
viewModel =
|
||||||
|
PayBillViewModel(
|
||||||
|
savedStateHandle = savedStateHandle,
|
||||||
|
dispatcherProvider = TestCoroutineDispatcherProvider(testDispatcher),
|
||||||
|
payBillRepository = payBillRepository,
|
||||||
|
naviBbpsDateUtils = naviBbpsDateUtils,
|
||||||
|
resourceProvider = resourceProvider,
|
||||||
|
billCategoriesRepository = billCategoriesRepository,
|
||||||
|
myBillsRepository = myBillsRepository,
|
||||||
|
naviBbpsCommonRepository = naviBbpsCommonRepository,
|
||||||
|
naviNetworkConnectivity = naviNetworkConnectivity,
|
||||||
|
naviBbpsSessionHelper = naviBbpsSessionHelper,
|
||||||
|
fetchBillHandler = fetchBillHandler,
|
||||||
|
coinsSyncManager = coinsSyncManager,
|
||||||
|
zeroPlatformFeeBottomSheetViewTracker = zeroPlatformFeeBottomSheetViewTracker,
|
||||||
|
litmusExperimentsUseCase = litmusExperimentsUseCase,
|
||||||
|
naviBbpsConfigUseCase = naviBbpsConfigUseCase,
|
||||||
|
rewardsNudgeEntityFetchUseCase = rewardsNudgeEntityFetchUseCase,
|
||||||
|
payBillAmountChipsHelper = payBillAmountChipsHelper,
|
||||||
|
bbpsArcHelper = bbpsArcHelper,
|
||||||
|
notifyDuplicatePaymentHandler = notifyDuplicatePaymentHandler,
|
||||||
|
tStoreOrderHandler = tStoreOrderHandler,
|
||||||
|
resProvider = resProvider,
|
||||||
|
naviPaymentRewardEventBus = naviPaymentRewardEventBus,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `updatePaymentAmount should update payment amount state flow`() = runTest {
|
||||||
|
val testAmount = "100.00"
|
||||||
|
viewModel.updatePaymentAmount(testAmount)
|
||||||
|
assertEquals(testAmount, viewModel.paymentAmount.first())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `isPayButtonEnabled should be false when amount is empty`() = runTest {
|
||||||
|
viewModel.updatePaymentAmount("")
|
||||||
|
assertFalse(viewModel.isPayButtonEnabled.first())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `isPayButtonEnabled should be false when amount is zero`() = runTest {
|
||||||
|
viewModel.updatePaymentAmount("0")
|
||||||
|
assertFalse(viewModel.isPayButtonEnabled.first())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `isPayButtonEnabled should be false when amount is valid but bill details are null`() =
|
||||||
|
runTest {
|
||||||
|
viewModel.updatePaymentAmount("100.00")
|
||||||
|
assertFalse(viewModel.isPayButtonEnabled.first())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `onCreditCardPaymentOptionSelected should update selection and set amount for total option`() =
|
||||||
|
runTest {
|
||||||
|
val mockDefaultConfig = mockk<NaviBbpsDefaultConfig>(relaxed = true)
|
||||||
|
mockkStatic("com.navi.bbps.common.utils.ConfigExtKt")
|
||||||
|
coEvery { naviBbpsConfigUseCase.getDefaultConfig(any()) } returns mockDefaultConfig
|
||||||
|
|
||||||
|
val billDetailsEntity =
|
||||||
|
BillDetailsEntity(
|
||||||
|
billId = "bill_123",
|
||||||
|
billerId = "biller_456",
|
||||||
|
referenceId = "ref_789",
|
||||||
|
amount = "1000.00",
|
||||||
|
dueDate = "2023-12-31",
|
||||||
|
billDate = "2023-12-01",
|
||||||
|
billNumber = "BILL123",
|
||||||
|
accountHolderName = "Test User",
|
||||||
|
billerAdditionalParams = emptyList(),
|
||||||
|
billPeriod = "Dec 2023",
|
||||||
|
)
|
||||||
|
|
||||||
|
val testPayBillSource =
|
||||||
|
PayBillSource.Others(
|
||||||
|
billerDetailsEntity = mockk(relaxed = true),
|
||||||
|
billDetailsEntity = billDetailsEntity,
|
||||||
|
customerParams = mapOf(),
|
||||||
|
formattedLastPaidDate = "",
|
||||||
|
formattedLastPaidAmount = "",
|
||||||
|
billerId = "test_biller_id",
|
||||||
|
amount = "1000.00",
|
||||||
|
isConsentRequired = false,
|
||||||
|
)
|
||||||
|
|
||||||
|
every { savedStateHandle.get<PayBillSource>("payBillScreenSource") } returns
|
||||||
|
testPayBillSource
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `onCreditCardPaymentOptionSelected should update selection and set amount for minimum option`() =
|
||||||
|
runTest {
|
||||||
|
val billDetailsEntity =
|
||||||
|
BillDetailsEntity(
|
||||||
|
billId = "bill_123",
|
||||||
|
billerId = "biller_456",
|
||||||
|
referenceId = "ref_789",
|
||||||
|
amount = "1000.00",
|
||||||
|
dueDate = "2023-12-31",
|
||||||
|
billDate = "2023-12-01",
|
||||||
|
billNumber = "BILL123",
|
||||||
|
accountHolderName = "Test User",
|
||||||
|
billerAdditionalParams =
|
||||||
|
listOf(
|
||||||
|
BillerAdditionalParamsEntity(
|
||||||
|
paramName = "MinimumDueAmount",
|
||||||
|
value = "200.00",
|
||||||
|
displayName = "Minimum Due",
|
||||||
|
shouldDisplay = true,
|
||||||
|
displayOrder = 1,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
billPeriod = "Dec 2023",
|
||||||
|
)
|
||||||
|
|
||||||
|
val testPayBillSource =
|
||||||
|
PayBillSource.Others(
|
||||||
|
billerDetailsEntity = mockk(relaxed = true),
|
||||||
|
billDetailsEntity = billDetailsEntity,
|
||||||
|
customerParams = mapOf(),
|
||||||
|
formattedLastPaidDate = "",
|
||||||
|
formattedLastPaidAmount = "",
|
||||||
|
billerId = "test_biller_id",
|
||||||
|
amount = "1000.00",
|
||||||
|
isConsentRequired = false,
|
||||||
|
)
|
||||||
|
|
||||||
|
every { savedStateHandle.get<PayBillSource>("payBillScreenSource") } returns
|
||||||
|
testPayBillSource
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `updateConsentProvided should update consent state`() = runTest {
|
||||||
|
val mockDefaultConfig = mockk<NaviBbpsDefaultConfig>(relaxed = true)
|
||||||
|
mockkStatic("com.navi.bbps.common.utils.ConfigExtKt")
|
||||||
|
coEvery { naviBbpsConfigUseCase.getDefaultConfig(any()) } returns mockDefaultConfig
|
||||||
|
|
||||||
|
// Start with a default value
|
||||||
|
viewModel.updateConsentProvided(false)
|
||||||
|
|
||||||
|
// Verify initial state
|
||||||
|
assertEquals(false, viewModel.isConsentProvided.first())
|
||||||
|
|
||||||
|
// Call the method we want to test
|
||||||
|
viewModel.updateConsentProvided(true)
|
||||||
|
|
||||||
|
// Verify updated state
|
||||||
|
assertEquals(true, viewModel.isConsentProvided.first())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `payment amount exactness should update error message ID`() = runTest {
|
||||||
|
val mockDefaultConfig = mockk<NaviBbpsDefaultConfig>(relaxed = true)
|
||||||
|
mockkStatic("com.navi.bbps.common.utils.ConfigExtKt")
|
||||||
|
coEvery { naviBbpsConfigUseCase.getDefaultConfig(any()) } returns mockDefaultConfig
|
||||||
|
|
||||||
|
viewModel.updatePaymentAmount("123.45")
|
||||||
|
|
||||||
|
assertNotNull(viewModel.errorMessageId.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `onPaymentResultReceived should handle failed payment`() = runTest {
|
||||||
|
viewModel.onPaymentResultReceived(
|
||||||
|
bbpsTransactionId = "",
|
||||||
|
paymentResponseMetadata = JSONObject(),
|
||||||
|
)
|
||||||
|
|
||||||
|
assertFalse(viewModel.isPayButtonClicked)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `header state should be updatable`() = runTest {
|
||||||
|
val billerDetailsEntity = mockk<BillerDetailsEntity>(relaxed = true)
|
||||||
|
|
||||||
|
val payBillSource =
|
||||||
|
PayBillSource.Others(
|
||||||
|
billerDetailsEntity = billerDetailsEntity,
|
||||||
|
billDetailsEntity = null,
|
||||||
|
customerParams = mapOf(),
|
||||||
|
formattedLastPaidDate = "",
|
||||||
|
formattedLastPaidAmount = "",
|
||||||
|
billerId = "test_biller_id",
|
||||||
|
amount = "100.00",
|
||||||
|
isConsentRequired = false,
|
||||||
|
)
|
||||||
|
|
||||||
|
every { savedStateHandle.get<PayBillSource>("payBillScreenSource") } returns payBillSource
|
||||||
|
|
||||||
|
val mockDefaultConfig = mockk<NaviBbpsDefaultConfig>(relaxed = true)
|
||||||
|
mockkStatic("com.navi.bbps.common.utils.ConfigExtKt")
|
||||||
|
coEvery { naviBbpsConfigUseCase.getDefaultConfig(any()) } returns mockDefaultConfig
|
||||||
|
|
||||||
|
val testViewModel =
|
||||||
|
PayBillViewModel(
|
||||||
|
savedStateHandle = savedStateHandle,
|
||||||
|
dispatcherProvider = TestCoroutineDispatcherProvider(testDispatcher),
|
||||||
|
payBillRepository = payBillRepository,
|
||||||
|
naviBbpsDateUtils = naviBbpsDateUtils,
|
||||||
|
resourceProvider = resourceProvider,
|
||||||
|
billCategoriesRepository = billCategoriesRepository,
|
||||||
|
myBillsRepository = myBillsRepository,
|
||||||
|
naviBbpsCommonRepository = naviBbpsCommonRepository,
|
||||||
|
naviNetworkConnectivity = naviNetworkConnectivity,
|
||||||
|
naviBbpsSessionHelper = naviBbpsSessionHelper,
|
||||||
|
fetchBillHandler = fetchBillHandler,
|
||||||
|
coinsSyncManager = coinsSyncManager,
|
||||||
|
zeroPlatformFeeBottomSheetViewTracker = zeroPlatformFeeBottomSheetViewTracker,
|
||||||
|
litmusExperimentsUseCase = litmusExperimentsUseCase,
|
||||||
|
naviBbpsConfigUseCase = naviBbpsConfigUseCase,
|
||||||
|
rewardsNudgeEntityFetchUseCase = rewardsNudgeEntityFetchUseCase,
|
||||||
|
payBillAmountChipsHelper = payBillAmountChipsHelper,
|
||||||
|
bbpsArcHelper = bbpsArcHelper,
|
||||||
|
notifyDuplicatePaymentHandler = notifyDuplicatePaymentHandler,
|
||||||
|
tStoreOrderHandler = tStoreOrderHandler,
|
||||||
|
resProvider = resProvider,
|
||||||
|
naviPaymentRewardEventBus = naviPaymentRewardEventBus,
|
||||||
|
)
|
||||||
|
|
||||||
|
testDispatcher.scheduler.advanceUntilIdle()
|
||||||
|
|
||||||
|
val expectedHeaderState =
|
||||||
|
PayBillHeaderState.OtherHeaders(billerDetailsEntity = billerDetailsEntity)
|
||||||
|
assertEquals(expectedHeaderState, testViewModel.payBillHeaderState.first())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `bill fetch failure should update error state`() = runTest {
|
||||||
|
coEvery {
|
||||||
|
fetchBillHandler.fetchBill(
|
||||||
|
payBillViewModel = any(),
|
||||||
|
isConsentProvided = any(),
|
||||||
|
onSuccess = any(),
|
||||||
|
onError = captureLambda(),
|
||||||
|
screenName = any(),
|
||||||
|
)
|
||||||
|
} answers { lambda<() -> Unit>().invoke() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `bill fetch success should update UI state`() = runTest {
|
||||||
|
val billEntity =
|
||||||
|
BillDetailsEntity(
|
||||||
|
billId = "bill_123",
|
||||||
|
billerId = "biller_456",
|
||||||
|
referenceId = "ref_789",
|
||||||
|
amount = "1000.00",
|
||||||
|
dueDate = "2023-12-31",
|
||||||
|
billDate = "2023-12-01",
|
||||||
|
billNumber = "BILL123",
|
||||||
|
accountHolderName = "Test User",
|
||||||
|
billerAdditionalParams = emptyList(),
|
||||||
|
billPeriod = "Dec 2023",
|
||||||
|
)
|
||||||
|
|
||||||
|
coEvery {
|
||||||
|
fetchBillHandler.fetchBill(
|
||||||
|
payBillViewModel = any(),
|
||||||
|
isConsentProvided = any(),
|
||||||
|
onSuccess = captureLambda(),
|
||||||
|
onError = any(),
|
||||||
|
screenName = any(),
|
||||||
|
)
|
||||||
|
} answers { lambda<(BillDetailsEntity, Boolean) -> Unit>().invoke(billEntity, false) }
|
||||||
|
setupBillDetailsEntity(billEntity)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `should be able to auto focus on amount field`() = runTest {
|
||||||
|
val mockDefaultConfig = mockk<NaviBbpsDefaultConfig>(relaxed = true)
|
||||||
|
mockkStatic("com.navi.bbps.common.utils.ConfigExtKt")
|
||||||
|
coEvery { naviBbpsConfigUseCase.getDefaultConfig(any()) } returns mockDefaultConfig
|
||||||
|
|
||||||
|
val testViewModel =
|
||||||
|
PayBillViewModel(
|
||||||
|
savedStateHandle = savedStateHandle,
|
||||||
|
dispatcherProvider = TestCoroutineDispatcherProvider(testDispatcher),
|
||||||
|
payBillRepository = payBillRepository,
|
||||||
|
naviBbpsDateUtils = naviBbpsDateUtils,
|
||||||
|
resourceProvider = resourceProvider,
|
||||||
|
billCategoriesRepository = billCategoriesRepository,
|
||||||
|
myBillsRepository = myBillsRepository,
|
||||||
|
naviBbpsCommonRepository = naviBbpsCommonRepository,
|
||||||
|
naviNetworkConnectivity = naviNetworkConnectivity,
|
||||||
|
naviBbpsSessionHelper = naviBbpsSessionHelper,
|
||||||
|
fetchBillHandler = fetchBillHandler,
|
||||||
|
coinsSyncManager = coinsSyncManager,
|
||||||
|
zeroPlatformFeeBottomSheetViewTracker = zeroPlatformFeeBottomSheetViewTracker,
|
||||||
|
litmusExperimentsUseCase = litmusExperimentsUseCase,
|
||||||
|
naviBbpsConfigUseCase = naviBbpsConfigUseCase,
|
||||||
|
rewardsNudgeEntityFetchUseCase = rewardsNudgeEntityFetchUseCase,
|
||||||
|
payBillAmountChipsHelper = payBillAmountChipsHelper,
|
||||||
|
bbpsArcHelper = bbpsArcHelper,
|
||||||
|
notifyDuplicatePaymentHandler = notifyDuplicatePaymentHandler,
|
||||||
|
tStoreOrderHandler = tStoreOrderHandler,
|
||||||
|
resProvider = resProvider,
|
||||||
|
naviPaymentRewardEventBus = naviPaymentRewardEventBus,
|
||||||
|
)
|
||||||
|
|
||||||
|
val autoFocusField = testViewModel.javaClass.getDeclaredField("_shouldAutoFocusOnAmount")
|
||||||
|
autoFocusField.isAccessible = true
|
||||||
|
val stateFlow = autoFocusField.get(testViewModel) as MutableStateFlow<Boolean>
|
||||||
|
stateFlow.value = true
|
||||||
|
|
||||||
|
assertTrue(testViewModel.shouldAutoFocusOnAmount.first())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `setting bill category entity should update related information`() = runTest {
|
||||||
|
val categoryEntity =
|
||||||
|
BillCategoryEntity(
|
||||||
|
categoryId = "1",
|
||||||
|
title = "Test Category",
|
||||||
|
iconUrl = "https://test.com/image.png",
|
||||||
|
searchBoxPlaceholderText = "Search billers",
|
||||||
|
billerListStateHeading = "Popular billers",
|
||||||
|
billerListAllHeading = "All billers",
|
||||||
|
reminderTitle = "Set reminder",
|
||||||
|
)
|
||||||
|
|
||||||
|
every { savedStateHandle.get<BillCategoryEntity>("billCategoryEntity") } returns
|
||||||
|
categoryEntity
|
||||||
|
|
||||||
|
val mockDefaultConfig = mockk<NaviBbpsDefaultConfig>(relaxed = true)
|
||||||
|
mockkStatic("com.navi.bbps.common.utils.ConfigExtKt")
|
||||||
|
coEvery { naviBbpsConfigUseCase.getDefaultConfig(any()) } returns mockDefaultConfig
|
||||||
|
|
||||||
|
val testViewModel =
|
||||||
|
PayBillViewModel(
|
||||||
|
savedStateHandle = savedStateHandle,
|
||||||
|
dispatcherProvider = TestCoroutineDispatcherProvider(testDispatcher),
|
||||||
|
payBillRepository = payBillRepository,
|
||||||
|
naviBbpsDateUtils = naviBbpsDateUtils,
|
||||||
|
resourceProvider = resourceProvider,
|
||||||
|
billCategoriesRepository = billCategoriesRepository,
|
||||||
|
myBillsRepository = myBillsRepository,
|
||||||
|
naviBbpsCommonRepository = naviBbpsCommonRepository,
|
||||||
|
naviNetworkConnectivity = naviNetworkConnectivity,
|
||||||
|
naviBbpsSessionHelper = naviBbpsSessionHelper,
|
||||||
|
fetchBillHandler = fetchBillHandler,
|
||||||
|
coinsSyncManager = coinsSyncManager,
|
||||||
|
zeroPlatformFeeBottomSheetViewTracker = zeroPlatformFeeBottomSheetViewTracker,
|
||||||
|
litmusExperimentsUseCase = litmusExperimentsUseCase,
|
||||||
|
naviBbpsConfigUseCase = naviBbpsConfigUseCase,
|
||||||
|
rewardsNudgeEntityFetchUseCase = rewardsNudgeEntityFetchUseCase,
|
||||||
|
payBillAmountChipsHelper = payBillAmountChipsHelper,
|
||||||
|
bbpsArcHelper = bbpsArcHelper,
|
||||||
|
notifyDuplicatePaymentHandler = notifyDuplicatePaymentHandler,
|
||||||
|
tStoreOrderHandler = tStoreOrderHandler,
|
||||||
|
resProvider = resProvider,
|
||||||
|
naviPaymentRewardEventBus = naviPaymentRewardEventBus,
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(categoryEntity, testViewModel.billCategoryEntity)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `should be able to update saved bill in repository`() = runTest {
|
||||||
|
val myBillEntity = mockk<MyBillEntity>(relaxed = true)
|
||||||
|
coEvery { myBillsRepository.updateSavedBill(any()) } returns Unit
|
||||||
|
|
||||||
|
myBillsRepository.updateSavedBill(myBillEntity)
|
||||||
|
|
||||||
|
coVerify { myBillsRepository.updateSavedBill(myBillEntity) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupBillDetailsEntity(billDetailsEntity: BillDetailsEntity) {
|
||||||
|
val payBillSource =
|
||||||
|
PayBillSource.Others(
|
||||||
|
billerDetailsEntity = mockk(relaxed = true),
|
||||||
|
billDetailsEntity = billDetailsEntity,
|
||||||
|
customerParams = mapOf(),
|
||||||
|
formattedLastPaidDate = "",
|
||||||
|
formattedLastPaidAmount = "",
|
||||||
|
billerId = "test_biller_id",
|
||||||
|
amount = "100.00",
|
||||||
|
isConsentRequired = false,
|
||||||
|
)
|
||||||
|
every { savedStateHandle.get<PayBillSource>("payBillScreenSource") } returns payBillSource
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user