NTP-62762 | Shiv Natani | unit test setup pms (#16193)

This commit is contained in:
Shiv Natani
2025-05-16 19:56:26 +05:30
committed by GitHub
parent 077ebf8d5a
commit e325da37de
4 changed files with 732 additions and 2 deletions

View File

@@ -56,6 +56,14 @@ android {
resValue 'string', 'navi_pay_manifest_url', 'https://pl.navifinserv.com/payments-gateway'
}
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
merges += "META-INF/LICENSE.md"
merges += "META-INF/LICENSE-notice.md"
}
}
}
dependencies {
@@ -86,10 +94,19 @@ dependencies {
releaseImplementation libs.chucker.libraryNoOp
androidTestImplementation libs.androidx.test.espresso.core
androidTestImplementation libs.androidx.test.junit
testImplementation libs.dagger.hiltAndroidTesting
testImplementation libs.junit
testImplementation libs.kotlinx.coroutines.test
testImplementation libs.mockk
androidTestImplementation libs.androidx.test.runner
androidTestImplementation libs.dagger.hiltAndroidTesting
androidTestImplementation libs.kotlinx.coroutines.test
androidTestImplementation libs.mockk.android
androidTestImplementation libs.turbine
androidTestImplementation libs.androidx.work.testing
ksp libs.androidx.hilt.compiler
ksp libs.androidx.room.compiler

View File

@@ -33,7 +33,8 @@
android:allowBackup="false"
android:hardwareAccelerated="true"
android:largeHeap="true"
android:supportsRtl="true">
android:supportsRtl="true"
tools:replace="android:allowBackup">
<activity
android:name=".nativepayment.activity.WebPaymentActivity"

View File

@@ -0,0 +1,123 @@
/*
*
* * Copyright © 2025 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
package com.navi.payment
import com.navi.pay.management.common.sendmoney.model.view.EligibilityState
import com.navi.pay.management.lite.models.view.UPILiteEntity
import com.navi.pay.onboarding.account.common.model.view.VpaEntity
import com.navi.pay.onboarding.account.detail.model.view.LinkedAccountEntity
import com.navi.payment.nativepayment.model.PMSLinkedAccountEntity
import org.joda.time.DateTime
object LinkedAccountTestData {
fun createPMSLinkedAccountEntity(
accountId: String = "12345",
bankCode: String = "HDFC",
bankName: String = "HDFC Bank",
name: String = "John Doe",
ifsc: String = "HDFC0001234",
fallbackBankLogoResId: Int = 0,
maskedAccountNumber: String = "XXXX1234",
originalMaskedAccountNumber: String = "XXXX1234",
accountType: String = "SAVINGS",
vpaEntityList: List<VpaEntity> = emptyList(),
isMPinSet: Boolean = true,
mPinLength: String = "4",
otpLength: String = "6",
atmPinLength: String = "4",
isAadhaarConsentProvided: Boolean = false,
bankIconImageUrl: String = "https://bank.com/logo.png",
isAccountPrimary: Boolean = true,
upiLiteInfo: List<UPILiteEntity> = emptyList(),
balance: String? = "5000",
accountTypeFormatted: String = "Savings Account",
updatedAt: DateTime = DateTime.now(),
isDisabled: Boolean = false,
creditLineAllowedMCC: List<String> = emptyList(),
creditLineNotAllowedMCC: List<String> = emptyList(),
): PMSLinkedAccountEntity {
return PMSLinkedAccountEntity(
accountId = accountId,
bankCode = bankCode,
bankName = bankName,
name = name,
ifsc = ifsc,
fallbackBankLogoResId = fallbackBankLogoResId,
maskedAccountNumber = maskedAccountNumber,
originalMaskedAccountNumber = originalMaskedAccountNumber,
accountType = accountType,
vpaEntityList = vpaEntityList,
isMPinSet = isMPinSet,
mPinLength = mPinLength,
otpLength = otpLength,
atmPinLength = atmPinLength,
isAadhaarConsentProvided = isAadhaarConsentProvided,
bankIconImageUrl = bankIconImageUrl,
isAccountPrimary = isAccountPrimary,
upiLiteInfo = upiLiteInfo,
balance = balance,
accountTypeFormatted = accountTypeFormatted,
updatedAt = updatedAt,
creditLineAllowedMCC = creditLineAllowedMCC,
creditLineNotAllowedMCC = creditLineNotAllowedMCC,
isDisabled = isDisabled,
)
}
fun createLinkedAccountEntity(
accountId: String = "12345",
bankCode: String = "HDFC",
bankName: String = "HDFC Bank",
name: String = "John Doe",
ifsc: String = "HDFC0001234",
fallbackBankLogoResId: Int = 0,
maskedAccountNumber: String = "XXXX1234",
originalMaskedAccountNumber: String = "XXXX1234",
accountType: String = "SAVINGS",
vpaEntityList: List<VpaEntity> = emptyList(),
isMPinSet: Boolean = true,
mPinLength: String = "4",
otpLength: String = "6",
atmPinLength: String = "4",
isAadhaarConsentProvided: Boolean = false,
bankIconImageUrl: String = "https://bank.com/logo.png",
isAccountPrimary: Boolean = true,
upiLiteInfo: List<UPILiteEntity> = emptyList(),
balance: String? = "5000",
accountTypeFormatted: String = "Savings Account",
updatedAt: DateTime = DateTime.now(),
eligibilityState: EligibilityState = EligibilityState(isAccountEligible = true),
): LinkedAccountEntity {
val linkedAccountEntity =
LinkedAccountEntity(
accountId = accountId,
bankCode = bankCode,
bankName = bankName,
name = name,
ifsc = ifsc,
fallbackBankLogoResId = fallbackBankLogoResId,
maskedAccountNumber = maskedAccountNumber,
originalMaskedAccountNumber = originalMaskedAccountNumber,
accountType = accountType,
vpaEntityList = vpaEntityList,
isMPinSet = isMPinSet,
mPinLength = mPinLength,
otpLength = otpLength,
atmPinLength = atmPinLength,
isAadhaarConsentProvided = isAadhaarConsentProvided,
bankIconImageUrl = bankIconImageUrl,
isAccountPrimary = isAccountPrimary,
upiLiteInfo = upiLiteInfo,
balance = balance,
accountTypeFormatted = accountTypeFormatted,
updatedAt = updatedAt,
)
linkedAccountEntity.eligibilityState = eligibilityState
return linkedAccountEntity
}
}

View File

@@ -0,0 +1,589 @@
/*
*
* * Copyright © 2025 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
package com.navi.payment.utils
import com.google.gson.Gson
import com.navi.base.utils.ResourceProvider
import com.navi.common.utils.CommonUtils.getDisplayableAmount
import com.navi.common.utils.EMPTY
import com.navi.common.utils.SPACE
import com.navi.common.utils.appendStrings
import com.navi.pay.R as NaviPayR
import com.navi.pay.R
import com.navi.pay.management.common.sendmoney.model.view.EligibilityState
import com.navi.pay.onboarding.account.detail.model.view.LinkedAccountEntity
import com.navi.pay.utils.RUPEE_SYMBOL
import com.navi.payment.LinkedAccountTestData
import com.navi.payment.nativepayment.utils.getDiscountAdjustedAmount
import com.navi.payment.nativepayment.utils.getEligibilityStateForUpiLiteAccount
import com.navi.payment.nativepayment.utils.getFirstEligibleAccount
import com.navi.payment.nativepayment.utils.getLastSelectedAccountBeforeAccountsUpdate
import com.navi.payment.nativepayment.utils.getLinkedAccountEntityState
import com.navi.payment.nativepayment.utils.getPayloadBasedOnType
import com.navi.payment.nativepayment.utils.getScreenIdentifier
import com.navi.payment.nativepayment.utils.mapToLinkedAccountEntity
import com.navi.payment.nativepayment.utils.rankUpiAccountsByEligibility
import com.navi.payment.nativepayment.utils.updateAccountEligibilityStatusForNonUpiLiteAccounts
import com.navi.payment.nativepayment.utils.updateEligibilityStateForAmount
import io.mockk.every
import io.mockk.mockk
import io.mockk.spyk
import org.json.JSONObject
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test
class ScreenIdentifierTest {
@Test
fun `getScreenIdentifier returnsLastSegment whenUrlHasSlashes`() {
val url = "https://example.com/home/dashboard"
val expected = "dashboard"
val actual = getScreenIdentifier(url)
assertEquals(expected, actual)
}
@Test
fun `getScreenIdentifier returnsEmptyString whenUrlEndsWithSlash`() {
val url = "https://example.com/home/"
val expected = ""
val actual = getScreenIdentifier(url)
assertEquals(expected, actual)
}
@Test
fun `getScreenIdentifier returnsEntireString ifNoSlash`() {
val url = "dashboard"
val expected = "dashboard"
val actual = getScreenIdentifier(url)
assertEquals(expected, actual)
}
@Test
fun `getScreenIdentifier returnsEmptyString forEmptyInput`() {
val url = ""
val expected = ""
val actual = getScreenIdentifier(url)
assertEquals(expected, actual)
}
}
class LinkedAccountMapperTest {
@Test
fun `mapToLinkedAccountEntity should correctly map PMSLinkedAccountEntity to LinkedAccountEntity`() {
val pmsLinkedAccountEntity = LinkedAccountTestData.createPMSLinkedAccountEntity()
val pmsLinkedAccountEntityList = listOf(pmsLinkedAccountEntity)
val result = mapToLinkedAccountEntity(pmsLinkedAccountEntityList)
assertNotNull(result)
assertEquals(pmsLinkedAccountEntityList.size, result.size)
val linkedAccountEntity = result[0]
assertEquals(pmsLinkedAccountEntity.accountId, linkedAccountEntity.accountId)
assertEquals(pmsLinkedAccountEntity.bankCode, linkedAccountEntity.bankCode)
assertEquals(pmsLinkedAccountEntity.bankName, linkedAccountEntity.bankName)
assertEquals(pmsLinkedAccountEntity.name, linkedAccountEntity.name)
assertEquals(pmsLinkedAccountEntity.ifsc, linkedAccountEntity.ifsc)
assertEquals(
pmsLinkedAccountEntity.maskedAccountNumber,
linkedAccountEntity.maskedAccountNumber,
)
assertEquals(
pmsLinkedAccountEntity.originalMaskedAccountNumber,
linkedAccountEntity.originalMaskedAccountNumber,
)
assertEquals(pmsLinkedAccountEntity.accountType, linkedAccountEntity.accountType)
assertEquals(pmsLinkedAccountEntity.vpaEntityList, linkedAccountEntity.vpaEntityList)
assertEquals(pmsLinkedAccountEntity.isMPinSet, linkedAccountEntity.isMPinSet)
assertEquals(pmsLinkedAccountEntity.mPinLength, linkedAccountEntity.mPinLength)
assertEquals(pmsLinkedAccountEntity.otpLength, linkedAccountEntity.otpLength)
assertEquals(pmsLinkedAccountEntity.atmPinLength, linkedAccountEntity.atmPinLength)
assertEquals(
pmsLinkedAccountEntity.isAadhaarConsentProvided,
linkedAccountEntity.isAadhaarConsentProvided,
)
assertEquals(pmsLinkedAccountEntity.bankIconImageUrl, linkedAccountEntity.bankIconImageUrl)
assertEquals(pmsLinkedAccountEntity.isAccountPrimary, linkedAccountEntity.isAccountPrimary)
assertEquals(pmsLinkedAccountEntity.balance, linkedAccountEntity.balance)
assertEquals(
pmsLinkedAccountEntity.accountTypeFormatted,
linkedAccountEntity.accountTypeFormatted,
)
assertEquals(pmsLinkedAccountEntity.updatedAt, linkedAccountEntity.updatedAt)
}
}
class UpdateAccountEligibilityStatusForNonUpiLiteAccountsTest {
@Test
fun `updateAccountEligibilityStatusForNonUpiLiteAccounts updates eligibility for non UPI Lite accounts`() {
val connectedAccounts =
listOf(
LinkedAccountTestData.createLinkedAccountEntity(accountId = "1"),
LinkedAccountTestData.createLinkedAccountEntity(accountId = "2"),
LinkedAccountTestData.createLinkedAccountEntity(accountId = "3"),
)
val connectedAccountsEligibilityMap =
mapOf(
"1" to EligibilityState(isAccountEligible = true),
"2" to EligibilityState(isAccountEligible = false),
"3" to EligibilityState(isAccountEligible = true),
)
updateAccountEligibilityStatusForNonUpiLiteAccounts(
connectedAccountsEligibilityMap,
connectedAccounts,
)
assertEquals(true, connectedAccounts[0].eligibilityState.isAccountEligible)
assertEquals(false, connectedAccounts[1].eligibilityState.isAccountEligible)
assertEquals(true, connectedAccounts[2].eligibilityState.isAccountEligible)
}
@Test
fun `updateAccountEligibilityStatusForNonUpiLiteAccounts ignores UPI Lite accounts`() {
val connectedAccounts =
listOf(
LinkedAccountTestData.createLinkedAccountEntity(accountId = "1"),
LinkedAccountTestData.createLinkedAccountEntity(
accountId = "upi_lite"
), // it should have a underscore
)
val upiLiteEligibilityState = connectedAccounts[1].eligibilityState
val connectedAccountsEligibilityMap =
mapOf("1" to EligibilityState(isAccountEligible = false))
updateAccountEligibilityStatusForNonUpiLiteAccounts(
connectedAccountsEligibilityMap,
connectedAccounts,
)
assertEquals(false, connectedAccounts[0].eligibilityState.isAccountEligible)
assertEquals(upiLiteEligibilityState, connectedAccounts[1].eligibilityState)
}
}
class RankUpiAccountsByEligibilityTest {
@Test
fun `rankUpiAccountsByEligibility returns enabled accounts followed by disabled accounts`() {
val accountList =
listOf(
LinkedAccountTestData.createLinkedAccountEntity(
eligibilityState = EligibilityState(isAccountEligible = false)
),
LinkedAccountTestData.createLinkedAccountEntity(
eligibilityState = EligibilityState(isAccountEligible = true)
),
LinkedAccountTestData.createLinkedAccountEntity(
eligibilityState = EligibilityState(isAccountEligible = true)
),
LinkedAccountTestData.createLinkedAccountEntity(
eligibilityState = EligibilityState(isAccountEligible = false)
),
)
val result = rankUpiAccountsByEligibility(accountList)
assertEquals(true, result[0].eligibilityState.isAccountEligible)
assertEquals(true, result[1].eligibilityState.isAccountEligible)
assertEquals(false, result[2].eligibilityState.isAccountEligible)
assertEquals(false, result[3].eligibilityState.isAccountEligible)
}
@Test
fun `rankUpiAccountsByEligibility returns empty list for empty input`() {
val result = rankUpiAccountsByEligibility(emptyList())
assertTrue(result.isEmpty())
}
}
class GetEligibilityStateForUpiLiteAccountTest {
private val resourceProvider: ResourceProvider = mockk()
@Test
fun `getEligibilityStateForUpiLiteAccount return ineligible if balance is empty or upi lite unavailable`() {
val liteBalance = EMPTY
val liteAccount = LinkedAccountTestData.createLinkedAccountEntity(balance = liteBalance)
every {
resourceProvider
.getString(resId = NaviPayR.string.balance)
.appendStrings(
SPACE,
RUPEE_SYMBOL,
liteAccount.balance.orEmpty().getDisplayableAmount(),
)
} returns "Balance: ₹${liteBalance.getDisplayableAmount()}"
every { resourceProvider.getString(resId = R.string.np_upi_lite_sync_needed) } returns
"UPI Lite is temporarily unavailable"
val result =
getEligibilityStateForUpiLiteAccount(
paymentAmount = 200.0,
liteAccount = liteAccount,
liteMaxPayableAmount = 1000.0,
resourceProvider = resourceProvider,
)
assertEquals(false, result.isAccountEligible)
}
@Test
fun `getEligibilityStateForUpiLiteAccount return ineligible if upi lite max limit exceeded`() {
val liteBalance = "1100"
val liteAccount = LinkedAccountTestData.createLinkedAccountEntity(balance = liteBalance)
every {
resourceProvider
.getString(resId = NaviPayR.string.balance)
.appendStrings(
SPACE,
RUPEE_SYMBOL,
liteAccount.balance.orEmpty().getDisplayableAmount(),
)
} returns "Balance: ₹${liteBalance.getDisplayableAmount()}"
every {
resourceProvider.getString(
R.string.np_supported_up_to_amount_limit,
"1000.0".getDisplayableAmount(),
)
} returns "Only supported for transaction up to ₹1000.0"
val result =
getEligibilityStateForUpiLiteAccount(
paymentAmount = 1050.0,
liteAccount = liteAccount,
liteMaxPayableAmount = 1000.0,
resourceProvider = resourceProvider,
)
assertEquals(false, result.isAccountEligible)
}
@Test
fun `getEligibilityStateForUpiLiteAccount returns ineligible if balance is insufficient`() {
val liteBalance = "100"
val liteAccount = LinkedAccountTestData.createLinkedAccountEntity(balance = liteBalance)
every {
resourceProvider
.getString(resId = NaviPayR.string.balance)
.appendStrings(
SPACE,
RUPEE_SYMBOL,
liteAccount.balance.orEmpty().getDisplayableAmount(),
)
} returns "Balance: ₹100"
val result =
getEligibilityStateForUpiLiteAccount(
paymentAmount = 200.0,
liteAccount = liteAccount,
liteMaxPayableAmount = 1000.0,
resourceProvider = resourceProvider,
)
assertEquals(false, result.isAccountEligible)
}
@Test
fun `getEligibilityStateForUpiLiteAccount return eligible if upi lite is enabled and all other check pass`() {
val liteBalance = "100"
val liteAccount = LinkedAccountTestData.createLinkedAccountEntity(balance = liteBalance)
every {
resourceProvider
.getString(resId = NaviPayR.string.balance)
.appendStrings(
SPACE,
RUPEE_SYMBOL,
liteAccount.balance.orEmpty().getDisplayableAmount(),
)
} returns "Balance: ₹${liteBalance.getDisplayableAmount()}"
val result =
getEligibilityStateForUpiLiteAccount(
paymentAmount = 10.0,
liteAccount = liteAccount,
liteMaxPayableAmount = 1000.0,
resourceProvider = resourceProvider,
)
assertEquals(true, result.isAccountEligible)
}
@Test
fun `getEligibilityStateForUpiLiteAccount return inEligible if upi lite is disabled but all other check pass`() {
val liteBalance = "100"
val pmsLiteAccountEntity =
LinkedAccountTestData.createPMSLinkedAccountEntity(
balance = liteBalance,
isDisabled = true,
)
val liteAccount =
mapToLinkedAccountEntity(accountList = listOf(pmsLiteAccountEntity)).first()
every {
resourceProvider
.getString(resId = NaviPayR.string.balance)
.appendStrings(
SPACE,
RUPEE_SYMBOL,
liteAccount.balance.orEmpty().getDisplayableAmount(),
)
} returns "Balance: ₹${liteBalance.getDisplayableAmount()}"
val result =
getEligibilityStateForUpiLiteAccount(
paymentAmount = 10.0,
liteAccount = liteAccount,
liteMaxPayableAmount = 1000.0,
resourceProvider = resourceProvider,
)
assertEquals(false, result.isAccountEligible)
}
}
class GetLinkedAccountEntityStateTest {
@Test
fun `getLinkedAccountEntityState returns ineligible state when account is disabled`() {
val linkedAccountEntity = LinkedAccountTestData.createLinkedAccountEntity()
linkedAccountEntity.isDisabled = true
val accountEligibility = EligibilityState(isAccountEligible = true)
val result = getLinkedAccountEntityState(accountEligibility, linkedAccountEntity)
assertEquals(false, result.isAccountEligible)
}
@Test
fun `getLinkedAccountEntityState returns eligible state with mpin not set when mpin is not set`() {
val linkedAccountEntity = LinkedAccountTestData.createLinkedAccountEntity(isMPinSet = false)
val accountEligibility = EligibilityState(isAccountEligible = true)
val result = getLinkedAccountEntityState(accountEligibility, linkedAccountEntity)
assertEquals(true, result.isAccountEligible)
assertEquals(R.string.mpin_not_set, result.inEligibilityReasonResId)
}
@Test
fun `getLinkedAccountEntityState returns provided eligibility state when account is enabled and mpin is set`() {
// Account is eligible
val linkedAccountEntity =
LinkedAccountTestData.createLinkedAccountEntity(
eligibilityState = EligibilityState(isAccountEligible = true)
)
val eligibleResult =
getLinkedAccountEntityState(
EligibilityState(isAccountEligible = true),
linkedAccountEntity,
)
assertEquals(true, eligibleResult.isAccountEligible)
// Account is not eligible
linkedAccountEntity.eligibilityState = EligibilityState(isAccountEligible = false)
val inEligibleResult =
getLinkedAccountEntityState(
accountEligibility = EligibilityState(isAccountEligible = false),
linkedAccountEntity,
)
assertEquals(false, inEligibleResult.isAccountEligible)
}
@Test
fun `getLinkedAccountEntityState returns default eligible state when eligibility is null and account is enabled with mpin set`() {
// Account is eligible
val linkedAccountEntity = LinkedAccountTestData.createLinkedAccountEntity()
val eligibleResult = getLinkedAccountEntityState(null, linkedAccountEntity)
assertEquals(true, eligibleResult.isAccountEligible)
// Account is not eligible
linkedAccountEntity.eligibilityState = EligibilityState(isAccountEligible = false)
val inEligibleResult = getLinkedAccountEntityState(null, linkedAccountEntity)
assertEquals(true, inEligibleResult.isAccountEligible)
}
}
class UpdateEligibilityStateForAmountTest {
private val resourceProvider: ResourceProvider = mockk()
@Test
fun `updateEligibilityStateForAmount returns early when eligibilityState is null`() {
val linkedAccountEntity = LinkedAccountTestData.createLinkedAccountEntity()
val result =
updateEligibilityStateForAmount(
account = linkedAccountEntity,
amount = 100.0,
upiSendMoneylimit = 1000.0,
upiLiteSendMoneyLimit = 500.0,
eligibilityState = null,
resourceProvider = resourceProvider,
)
assertEquals(true, linkedAccountEntity.eligibilityState.isAccountEligible)
}
@Test
fun `updateEligibilityStateForAmount sets ineligible for non UpiLite when amount exceeds limit`() {
val linkedAccountEntity = LinkedAccountTestData.createLinkedAccountEntity()
every {
resourceProvider.getString(com.navi.payment.R.string.payment_instrument_not_support)
} returns "Amount exceeds limit"
updateEligibilityStateForAmount(
account = linkedAccountEntity,
amount = 2000.0,
upiSendMoneylimit = 1000.0,
upiLiteSendMoneyLimit = 500.0,
eligibilityState = EligibilityState(isAccountEligible = true),
resourceProvider = resourceProvider,
)
assertEquals(false, linkedAccountEntity.eligibilityState.isAccountEligible)
assertEquals(
"Amount exceeds limit",
linkedAccountEntity.eligibilityState.inEligibilityReason,
)
}
@Test
fun `updateEligibilityStateForAmount sets provided eligibility for non UpiLite when amount within limit`() {
val linkedAccountEntity = LinkedAccountTestData.createLinkedAccountEntity()
val providedEligibilityState =
EligibilityState(isAccountEligible = true, inEligibilityReason = "Some reason")
updateEligibilityStateForAmount(
account = linkedAccountEntity,
amount = 500.0,
upiSendMoneylimit = 1000.0,
upiLiteSendMoneyLimit = 500.0,
eligibilityState = providedEligibilityState,
resourceProvider = resourceProvider,
)
assertEquals(
providedEligibilityState.isAccountEligible,
linkedAccountEntity.eligibilityState.isAccountEligible,
)
assertEquals(
providedEligibilityState.inEligibilityReason,
linkedAccountEntity.eligibilityState.inEligibilityReason,
)
}
}
class GetFirstEligibleAccountTest {
@Test
fun `getFirstEligibleAccount returns first eligible account`() {
val linkedAccountList =
listOf(
LinkedAccountTestData.createLinkedAccountEntity(
eligibilityState = EligibilityState(isAccountEligible = false)
),
LinkedAccountTestData.createLinkedAccountEntity(
eligibilityState = EligibilityState(isAccountEligible = true)
),
)
val result = getFirstEligibleAccount(linkedAccountList)
assertNotNull(result)
assertEquals(linkedAccountList[1], result)
}
@Test
fun `getFirstEligibleAccount returns null if no eligible accounts`() {
val linkedAccountList =
listOf(
LinkedAccountTestData.createLinkedAccountEntity(
eligibilityState = EligibilityState(isAccountEligible = false)
),
LinkedAccountTestData.createLinkedAccountEntity(
eligibilityState = EligibilityState(isAccountEligible = false)
),
)
val result = getFirstEligibleAccount(linkedAccountList)
assertNull(result)
}
}
class DiscountAdjustedAmountTest {
@Test
fun `getDiscountAdjustedAmount correctly applies discount and rounds`() {
val amount = 100.0
val discount = 15.237
val expected = 84.76 // 100.0 - 15.237 = 84.763 -> rounded to 2 decimals
val actual = getDiscountAdjustedAmount(amount, discount)
assertEquals(expected, actual, 0.001)
}
@Test
fun `getDiscountAdjustedAmount zeroDiscount returns original amount`() {
val amount = 200.0
val discount = 0.0
val expected = 200.0
val actual = getDiscountAdjustedAmount(amount, discount)
assertEquals(expected, actual, 0.001)
}
}
class GetPayloadBasedOnTypeTest {
private val deserializer: Gson = mockk()
@Test
fun `getPayloadBasedOnType returns null for null payload`() {
val spy = spyk(JSONObject())
every { spy.has("type") } returns false
every { spy.has("data") } returns false
val result = getPayloadBasedOnType(deserializer, null)
assertNull(result)
}
@Test
fun `getPayloadBasedOnType returns null when type is missing`() {
val spy = spyk(JSONObject())
every { spy.has("type") } returns false
every { spy.has("data") } returns true
val result = getPayloadBasedOnType(deserializer, spy)
assertNull(result)
}
@Test
fun `getPayloadBasedOnType returns null when data is missing`() {
val spy = spyk(JSONObject())
every { spy.has("type") } returns true
every { spy.has("data") } returns false
val result = getPayloadBasedOnType(deserializer, spy)
assertNull(result)
}
}
class GetLastSelectedAccountBeforeAccountsUpdateTest {
@Test
fun `getLastSelectedAccountBeforeAccountsUpdate returns correct account`() {
val linkedAccountList =
listOf(
LinkedAccountTestData.createLinkedAccountEntity(accountId = "1"),
LinkedAccountTestData.createLinkedAccountEntity(accountId = "2"),
LinkedAccountTestData.createLinkedAccountEntity(accountId = "3"),
)
val lastSelectedAccountId = "2"
val result =
getLastSelectedAccountBeforeAccountsUpdate(linkedAccountList, lastSelectedAccountId)
assertNotNull(result)
assertEquals("2", result?.accountId)
}
@Test
fun `getLastSelectedAccountBeforeAccountsUpdate returns first eligible account if not found`() {
val linkedAccountList =
listOf(
LinkedAccountTestData.createLinkedAccountEntity(accountId = "1"),
LinkedAccountTestData.createLinkedAccountEntity(accountId = "3"),
)
val lastSelectedAccountId = "2"
val result =
getLastSelectedAccountBeforeAccountsUpdate(linkedAccountList, lastSelectedAccountId)
assertEquals(getFirstEligibleAccount(linkedAccountList), result)
}
@Test
fun `getLastSelectedAccountsBeforeAccountUpdate return null if list is empty`() {
val linkedAccountList = emptyList<LinkedAccountEntity>()
val lastSelectedAccountId = "1"
val result =
getLastSelectedAccountBeforeAccountsUpdate(
updatedAccountList = linkedAccountList,
lastSelectedBankAccountId = lastSelectedAccountId,
)
assertNull(result)
}
}