Updated on 2026-08-14

This commit is contained in:
Tangem 2026-07-16 11:42:49 +02:00
commit 1583ff1144
10 changed files with 326 additions and 7 deletions

View file

@ -34,6 +34,19 @@ fun BaseTestCase.openTangemPayCardPage() {
}
}
/** Opens the card page and taps 'Change' on the daily limit block to reach the limit setup screen. */
fun BaseTestCase.openTangemPayDailyLimitSetup() {
openTangemPayCardPage()
step("Click on 'Change' daily limit button") {
awaitSuccess { onTangemPayCardPageScreen { dailyLimitChangeButton.assertIsDisplayed() } }
onTangemPayCardPageScreen { dailyLimitChangeButton.performClick() }
}
step("Assert daily limit setup screen is displayed") {
awaitSuccess { onTangemPayDailyLimitScreen { amountField.assertIsDisplayed() } }
onTangemPayDailyLimitScreen { setLimitsButton.assertIsDisplayed() }
}
}
/** From the card page, opens the 'Replace card' reissue bottom sheet via the 'More' menu. */
fun BaseTestCase.openReissueSheet() {
step("Click on 'More' button") {

View file

@ -89,6 +89,16 @@ class TangemPayCardPagePageObject(semanticsProvider: SemanticsNodeInteractionsPr
hasTestTag(TangemPayTestTags.CARD_DETAILS_COPY_CVC)
useUnmergedTree = true
}
val dailyLimitChangeButton: KNode = child {
hasTestTag(TangemPayTestTags.DAILY_LIMIT_CHANGE_BUTTON)
useUnmergedTree = true
}
val dailyLimitValue: KNode = child {
hasTestTag(TangemPayTestTags.DAILY_LIMIT_CURRENT_VALUE)
useUnmergedTree = true
}
}
internal fun BaseTestCase.onTangemPayCardPageScreen(function: TangemPayCardPagePageObject.() -> Unit) =

View file

@ -0,0 +1,47 @@
package com.tangem.screens.tangempay
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
import com.tangem.common.BaseTestCase
import com.tangem.core.ui.test.SendScreenTestTags
import com.tangem.core.ui.test.TangemPayTestTags
import io.github.kakaocup.compose.node.element.ComposeScreen
import io.github.kakaocup.compose.node.element.ComposeScreen.Companion.onComposeScreen
import io.github.kakaocup.compose.node.element.KNode
class TangemPayDailyLimitPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<TangemPayDailyLimitPageObject>(semanticsProvider = semanticsProvider) {
// AmountTextField tags its editable field with SendScreenTestTags.INPUT_TEXT_FIELD; it's the only one here.
val amountField: KNode = child {
hasTestTag(SendScreenTestTags.INPUT_TEXT_FIELD)
useUnmergedTree = true
}
val hint: KNode = child {
hasTestTag(TangemPayTestTags.DAILY_LIMIT_HINT)
useUnmergedTree = true
}
val setLimitsButton: KNode = child {
hasTestTag(TangemPayTestTags.DAILY_LIMIT_SET_BUTTON)
useUnmergedTree = true
}
val successTitle: KNode = child {
hasTestTag(TangemPayTestTags.DAILY_LIMIT_SUCCESS_TITLE)
useUnmergedTree = true
}
val doneButton: KNode = child {
hasTestTag(TangemPayTestTags.DAILY_LIMIT_DONE_BUTTON)
useUnmergedTree = true
}
fun presetChip(rawValue: String): KNode = child {
hasTestTag(TangemPayTestTags.dailyLimitPresetChip(rawValue))
useUnmergedTree = true
}
}
internal fun BaseTestCase.onTangemPayDailyLimitScreen(function: TangemPayDailyLimitPageObject.() -> Unit) =
onComposeScreen(composeTestRule, function)

View file

@ -0,0 +1,204 @@
package com.tangem.tests.tangempay
import com.tangem.common.BaseTestCase
import com.tangem.common.constants.TestConstants.TANGEM_PAY_ELIGIBILITY_SCENARIO
import com.tangem.common.constants.TestConstants.WAIT_UNTIL_TIMEOUT_LONG
import com.tangem.common.extensions.assertTextContainsSafe
import com.tangem.common.extensions.clickWithAssertion
import com.tangem.common.utils.resetWireMockScenarioState
import com.tangem.common.utils.resetWireMockScenarios
import com.tangem.common.utils.setWireMockScenarioState
import com.tangem.core.res.R as CoreResR
import com.tangem.scenarios.openTangemPayDailyLimitSetup
import com.tangem.screens.onDialog
import com.tangem.screens.tangempay.onTangemPayCardPageScreen
import com.tangem.screens.tangempay.onTangemPayDailyLimitScreen
import dagger.hilt.android.testing.HiltAndroidTest
import io.github.kakaocup.kakao.common.utilities.getResourceString
import io.qameta.allure.kotlin.AllureId
import io.qameta.allure.kotlin.junit4.DisplayName
import org.junit.Test
@HiltAndroidTest
class TangemPayDailyLimitTest : BaseTestCase() {
private val dailyLimitScenario = "tangem_pay_daily_limit"
private val highLimitState = "HighLimit"
private val setErrorState = "SetError"
private val eligibilityState = "PaeraCustomer"
@AllureId("9726")
@DisplayName("Tangem Pay: daily limit screen is displayed correctly")
@Test
fun dailyLimitScreenIsDisplayedCorrectlyTest() {
setupHooks(
additionalBeforeSection = {
resetWireMockScenarios()
setWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO, eligibilityState)
setWireMockScenarioState(dailyLimitScenario, highLimitState)
},
additionalAfterSection = {
resetWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO)
resetWireMockScenarioState(dailyLimitScenario)
},
).run {
step("Open daily limit setup screen") { openTangemPayDailyLimitSetup() }
step("Assert amount field is displayed") {
onTangemPayDailyLimitScreen { amountField.assertIsDisplayed() }
}
step("Assert hint is displayed") {
onTangemPayDailyLimitScreen { hint.assertIsDisplayed() }
}
step("Assert 'Set limits' button is displayed") {
onTangemPayDailyLimitScreen { setLimitsButton.assertIsDisplayed() }
}
step("Assert quick value preset '1' is displayed") {
onTangemPayDailyLimitScreen { presetChip("1").assertIsDisplayed() }
}
step("Assert quick value preset '5000' is displayed") {
onTangemPayDailyLimitScreen { presetChip("5000").assertIsDisplayed() }
}
step("Assert quick value preset '10000' is displayed") {
onTangemPayDailyLimitScreen { presetChip("10000").assertIsDisplayed() }
}
step("Assert quick value preset '25000' is displayed") {
onTangemPayDailyLimitScreen { presetChip("25000").assertIsDisplayed() }
}
}
}
@AllureId("9724")
@DisplayName("Tangem Pay: selected quick value is applied to the amount field")
@Test
fun selectedQuickValueIsAppliedToAmountFieldTest() {
val presetValue = "5000"
setupHooks(
additionalBeforeSection = {
resetWireMockScenarios()
setWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO, eligibilityState)
setWireMockScenarioState(dailyLimitScenario, highLimitState)
},
additionalAfterSection = {
resetWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO)
resetWireMockScenarioState(dailyLimitScenario)
},
).run {
step("Open daily limit setup screen") { openTangemPayDailyLimitSetup() }
step("Click on '$presetValue' quick value preset") {
onTangemPayDailyLimitScreen { presetChip(presetValue).clickWithAssertion() }
}
step("Assert amount field contains '$presetValue'") {
onTangemPayDailyLimitScreen { amountField.assertTextContainsSafe(presetValue) }
}
}
}
@AllureId("9725")
@DisplayName("Tangem Pay: 'Set limits' is disabled when the amount is above the limit")
@Test
fun setLimitsIsDisabledWhenAmountAboveLimitTest() {
val amountAboveLimit = "300000"
setupHooks(
additionalBeforeSection = {
resetWireMockScenarios()
setWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO, eligibilityState)
setWireMockScenarioState(dailyLimitScenario, highLimitState)
},
additionalAfterSection = {
resetWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO)
resetWireMockScenarioState(dailyLimitScenario)
},
).run {
step("Open daily limit setup screen") { openTangemPayDailyLimitSetup() }
step("Enter amount '$amountAboveLimit' above the limit") {
onTangemPayDailyLimitScreen { amountField.performTextReplacement(amountAboveLimit) }
}
step("Assert 'Set limits' button is not enabled") {
onTangemPayDailyLimitScreen { setLimitsButton.assertIsNotEnabled() }
}
}
}
@AllureId("9739")
@DisplayName("Tangem Pay: successful daily limit setup")
@Test
fun successfulDailyLimitSetupTest() {
val newLimit = "5000"
val displayedLimit = "5,000"
setupHooks(
additionalBeforeSection = {
resetWireMockScenarios()
setWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO, eligibilityState)
setWireMockScenarioState(dailyLimitScenario, highLimitState)
},
additionalAfterSection = {
resetWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO)
resetWireMockScenarioState(dailyLimitScenario)
},
).run {
step("Open daily limit setup screen") { openTangemPayDailyLimitSetup() }
step("Enter amount '$newLimit'") {
onTangemPayDailyLimitScreen { amountField.performTextReplacement(newLimit) }
}
step("Click on 'Set limits' button") {
onTangemPayDailyLimitScreen { setLimitsButton.clickWithAssertion() }
}
step("Assert daily limit success screen is displayed") {
flakySafely(WAIT_UNTIL_TIMEOUT_LONG) {
onTangemPayDailyLimitScreen { successTitle.assertIsDisplayed() }
}
}
step("Click on 'Done' button") {
onTangemPayDailyLimitScreen { doneButton.clickWithAssertion() }
}
step("Assert daily limit value contains '$displayedLimit'") {
flakySafely(WAIT_UNTIL_TIMEOUT_LONG) {
onTangemPayCardPageScreen {
dailyLimitValue.assertTextContainsSafe(displayedLimit, substring = true)
}
}
}
}
}
@AllureId("9727")
@DisplayName("Tangem Pay: error is shown when the limit change fails")
@Test
fun errorIsShownWhenLimitChangeFailsTest() {
val newLimit = "5000"
val errorTitle = getResourceString(CoreResR.string.common_something_went_wrong)
setupHooks(
additionalBeforeSection = {
resetWireMockScenarios()
setWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO, eligibilityState)
setWireMockScenarioState(dailyLimitScenario, setErrorState)
},
additionalAfterSection = {
resetWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO)
resetWireMockScenarioState(dailyLimitScenario)
},
).run {
step("Open daily limit setup screen") { openTangemPayDailyLimitSetup() }
step("Enter amount '$newLimit'") {
onTangemPayDailyLimitScreen { amountField.performTextReplacement(newLimit) }
}
step("Click on 'Set limits' button") {
onTangemPayDailyLimitScreen { setLimitsButton.clickWithAssertion() }
}
step("Assert limit change error dialog is displayed") {
flakySafely(WAIT_UNTIL_TIMEOUT_LONG) {
onDialog {
title.assertTextContainsSafe(errorTitle)
}
}
}
step("Click on 'OK' button") {
onDialog { okButton.clickWithAssertion() }
}
}
}
}