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:
Mohit Rajput
2025-06-16 04:21:19 -07:00
committed by GitHub
parent 37780e010a
commit 8bc287b0db
4 changed files with 605 additions and 54 deletions

View File

@@ -339,7 +339,7 @@ constructor(
}
}
private fun updateConsentProvided(isConsentProvided: Boolean) {
fun updateConsentProvided(isConsentProvided: Boolean) {
_isConsentProvided.update { isConsentProvided }
}
@@ -363,7 +363,7 @@ constructor(
_payBillScreenState.update { payBillScreenState }
}
private fun updatePayBillHeaderState(payBillHeaderState: PayBillHeaderState) {
fun updatePayBillHeaderState(payBillHeaderState: PayBillHeaderState) {
_payBillHeaderState.update { payBillHeaderState }
}

View File

@@ -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()
}
}

View File

@@ -9,6 +9,7 @@ package com.navi.bbps.common.viewmodel
import com.navi.base.utils.NaviNetworkConnectivity
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.model.config.NaviBbpsDefaultConfig
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.feature.detectedbills.DetectedBillsRepository
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.RepoResult
import io.mockk.MockKAnnotations
import io.mockk.coEvery
import io.mockk.impl.annotations.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.setMain
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
@@ -49,8 +39,7 @@ import org.junit.Test
* - The startDetectingBills method with different scenarios
* - Various helper functions within the handler
*/
@OptIn(ExperimentalCoroutinesApi::class)
class OriginBillDetectionHandlerTest {
class OriginBillDetectionHandlerTest : NaviBbpsBaseTest() {
// Dependencies to be mocked
@MockK private lateinit var detectedBillsRepository: DetectedBillsRepository
@MockK private lateinit var resourceProvider: ResourceProvider
@@ -60,46 +49,12 @@ class OriginBillDetectionHandlerTest {
// Class under test
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
fun setUp() {
// Configure the main dispatcher for testing
Dispatchers.setMain(testDispatcher)
// Initialize MockK annotations with relaxed behavior
MockKAnnotations.init(this, relaxed = true)
// Initialize the handler with test dependencies
override fun setUp() {
super.setUp()
handler =
OriginBillDetectionHandler(
coroutineDispatcherProvider = TestCoroutineDispatcherProviderImpl(testDispatcher),
coroutineDispatcherProvider = TestCoroutineDispatcherProvider(testDispatcher),
detectedBillsRepository = detectedBillsRepository,
resourceProvider = resourceProvider,
naviNetworkConnectivity = naviNetworkConnectivity,
@@ -367,8 +322,8 @@ class OriginBillDetectionHandlerTest {
* original state.
*/
@After
fun tearDown() {
Dispatchers.resetMain()
override fun tearDown() {
super.tearDown()
}
/**

View File

@@ -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
}
}