Updated on 2026-08-14
This commit is contained in:
parent
18da968728
commit
81abb6b699
13 changed files with 488 additions and 5 deletions
|
|
@ -23,6 +23,31 @@ fun BaseTestCase.openTangemPay() {
|
|||
}
|
||||
}
|
||||
|
||||
/** Opens Tangem Pay and taps the card to reach the card management page. */
|
||||
fun BaseTestCase.openTangemPayCardPage() {
|
||||
openTangemPay()
|
||||
step("Click on 'Card' button") {
|
||||
onTangemPayMainScreen { cardButton.clickWithAssertion() }
|
||||
}
|
||||
step("Assert card page 'More' button is displayed") {
|
||||
awaitSuccess { onTangemPayCardPageScreen { moreButton.assertIsDisplayed() } }
|
||||
}
|
||||
}
|
||||
|
||||
/** From the card page, opens the 'Replace card' reissue bottom sheet via the 'More' menu. */
|
||||
fun BaseTestCase.openReissueSheet() {
|
||||
step("Click on 'More' button") {
|
||||
onTangemPayCardPageScreen { moreButton.clickWithAssertion() }
|
||||
}
|
||||
step("Click on 'Replace card' menu item") {
|
||||
awaitSuccess { onTangemPayCardPageScreen { replaceCardMenuItem.assertIsDisplayed() } }
|
||||
onTangemPayCardPageScreen { replaceCardMenuItem.performClick() }
|
||||
}
|
||||
step("Assert reissue bottom sheet is displayed") {
|
||||
awaitSuccess { onTangemPayReissueSheet { confirmButton.assertIsDisplayed() } }
|
||||
}
|
||||
}
|
||||
|
||||
// Compose Test gesture — UiAutomator swipe doesn't reach Material3 PullToRefreshBox's NestedScrollConnection.
|
||||
fun BaseTestCase.pullToRefreshTangemPay() {
|
||||
val balance = composeTestRule.onNode(hasTestTag(TangemPayTestTags.PAYMENT_ACCOUNT_BALANCE))
|
||||
|
|
|
|||
|
|
@ -19,6 +19,11 @@ class TokenReceiveWarningBottomSheetPageObject(semanticsProvider: SemanticsNodeI
|
|||
val gotItButton: KNode = child {
|
||||
hasText(getResourceString(R.string.common_got_it))
|
||||
}
|
||||
|
||||
fun networkName(name: String): KNode = child {
|
||||
hasText(text = name, substring = true)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
}
|
||||
|
||||
internal fun BaseTestCase.onTokenReceiveWarningBottomSheet(function: TokenReceiveWarningBottomSheetPageObject.() -> Unit) =
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class TangemPayAddFundsSheetPageObject(semanticsProvider: SemanticsNodeInteracti
|
|||
}
|
||||
|
||||
val receiveOption: KNode = child {
|
||||
hasText(getResourceString(CoreResR.string.common_receive))
|
||||
hasText(getResourceString(CoreResR.string.tangempay_topup_receive_title))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,14 +2,39 @@ package com.tangem.screens.tangempay
|
|||
|
||||
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.core.res.R as CoreResR
|
||||
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
|
||||
import io.github.kakaocup.kakao.common.utilities.getResourceString
|
||||
|
||||
class TangemPayCardPagePageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
|
||||
ComposeScreen<TangemPayCardPagePageObject>(semanticsProvider = semanticsProvider) {
|
||||
|
||||
val moreButton: KNode = child {
|
||||
hasTestTag(TangemPayTestTags.CARD_PAGE_MORE_BUTTON)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val replaceCardMenuItem: KNode = child {
|
||||
hasText(getResourceString(CoreResR.string.tangempay_card_details_reissue_card))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val cardNumberShort: KNode = child {
|
||||
hasTestTag(TangemPayTestTags.CARD_NUMBER_SHORT)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val reissueInProgressBlock: KNode = child {
|
||||
hasText(
|
||||
text = getResourceString(CoreResR.string.tangempay_reissue_card_in_progress),
|
||||
substring = true,
|
||||
)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val changePinRow: KNode = child {
|
||||
hasTestTag(TangemPayTestTags.CHANGE_PIN_ROW)
|
||||
useUnmergedTree = true
|
||||
|
|
|
|||
|
|
@ -61,6 +61,14 @@ class TangemPayMainPageObject(semanticsProvider: SemanticsNodeInteractionsProvid
|
|||
hasText(text)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val reissueInProgressBanner: KNode = child {
|
||||
hasText(
|
||||
text = getResourceString(CoreResR.string.tangempay_reissue_card_in_progress),
|
||||
substring = true,
|
||||
)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
}
|
||||
|
||||
internal fun BaseTestCase.onTangemPayMainScreen(function: TangemPayMainPageObject.() -> Unit) =
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
package com.tangem.screens.tangempay
|
||||
|
||||
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.core.res.R as CoreResR
|
||||
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
|
||||
import io.github.kakaocup.kakao.common.utilities.getResourceString
|
||||
|
||||
class TangemPayReissueSheetPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
|
||||
ComposeScreen<TangemPayReissueSheetPageObject>(semanticsProvider = semanticsProvider) {
|
||||
|
||||
val title: KNode = child {
|
||||
hasText(getResourceString(CoreResR.string.tangempay_reissue_card_title))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val description: KNode = child {
|
||||
hasText(getResourceString(CoreResR.string.tangempay_reissue_card_description))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val feeLabel: KNode = child {
|
||||
hasText(getResourceString(CoreResR.string.tangempay_reissue_card_fee_label))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val feeValue: KNode = child {
|
||||
hasTestTag(TangemPayTestTags.REISSUE_SHEET_FEE_VALUE)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val confirmButton: KNode = child {
|
||||
hasTestTag(TangemPayTestTags.REISSUE_SHEET_CONFIRM_BUTTON)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val feeErrorTitle: KNode = child {
|
||||
hasText(getResourceString(CoreResR.string.tangempay_reissue_card_fee_unreachable_error_title))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val refreshButton: KNode = child {
|
||||
hasText(getResourceString(CoreResR.string.warning_button_refresh))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val insufficientFundsTitle: KNode = child {
|
||||
hasText(getResourceString(CoreResR.string.tangempay_reissue_card_insufficient_funds_title))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val addFundsButton: KNode = child {
|
||||
hasText(getResourceString(CoreResR.string.tangempay_card_details_add_funds))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
}
|
||||
|
||||
internal fun BaseTestCase.onTangemPayReissueSheet(function: TangemPayReissueSheetPageObject.() -> Unit) =
|
||||
onComposeScreen(composeTestRule, function)
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package com.tangem.screens.tangempay
|
||||
|
||||
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.core.res.R as CoreResR
|
||||
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
|
||||
import io.github.kakaocup.kakao.common.utilities.getResourceString
|
||||
|
||||
class TangemPayTransactionDetailsSheetPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
|
||||
ComposeScreen<TangemPayTransactionDetailsSheetPageObject>(semanticsProvider = semanticsProvider) {
|
||||
|
||||
val feeTitle: KNode = child {
|
||||
hasText(getResourceString(CoreResR.string.tangem_pay_fee_title))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val serviceFeesCategory: KNode = child {
|
||||
hasText(getResourceString(CoreResR.string.tangem_pay_fee_subtitle))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val amount: KNode = child {
|
||||
hasTestTag(TangemPayTestTags.TRANSACTION_DETAILS_AMOUNT)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
}
|
||||
|
||||
internal fun BaseTestCase.onTangemPayTransactionDetailsSheet(
|
||||
function: TangemPayTransactionDetailsSheetPageObject.() -> Unit,
|
||||
) = onComposeScreen(composeTestRule, function)
|
||||
|
|
@ -0,0 +1,299 @@
|
|||
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
|
||||
import com.tangem.common.constants.TestConstants.WAIT_UNTIL_TIMEOUT_VERY_LONG
|
||||
import com.tangem.common.extensions.assertTextContainsSafe
|
||||
import com.tangem.common.extensions.clickWithAssertion
|
||||
import com.tangem.common.extensions.extractText
|
||||
import com.tangem.common.utils.resetWireMockScenarioState
|
||||
import com.tangem.common.utils.resetWireMockScenarios
|
||||
import com.tangem.common.utils.setWireMockScenarioState
|
||||
import com.tangem.scenarios.*
|
||||
import com.tangem.screens.onTokenReceiveWarningBottomSheet
|
||||
import com.tangem.screens.tangempay.*
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import io.qameta.allure.kotlin.AllureId
|
||||
import io.qameta.allure.kotlin.junit4.DisplayName
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
|
||||
@HiltAndroidTest
|
||||
class TangemPayReissueTest : BaseTestCase() {
|
||||
|
||||
private val eligibilityState = "PaeraCustomer"
|
||||
private val balanceScenario = "tangem_pay_balance_update"
|
||||
private val balanceInitialState = "InitialBalance"
|
||||
private val cardReissueScenario = "tangem_pay_card_reissue"
|
||||
private val cardReissueStartedState = "Started"
|
||||
private val cardReissueFeeErrorState = "FeeError"
|
||||
private val reissueOrderScenario = "tangem_pay_reissue_order"
|
||||
private val reissueOrderStartedState = "Started"
|
||||
private val reissueOrderCompletedState = "Completed"
|
||||
private val reissueScenario = "tangem_pay_reissue"
|
||||
private val reissueCompletedState = "Completed"
|
||||
private val historyScenario = "tangem_pay_transaction_history"
|
||||
private val historyInitialEmptyState = "InitialEmpty"
|
||||
private val historyAfterReissueFeeState = "AfterReissueFee"
|
||||
|
||||
@AllureId("9749")
|
||||
@DisplayName("Tangem Pay: card reissue bottom sheet displays replace card details")
|
||||
@Test
|
||||
fun reissueBottomSheetDisplaysReplaceCardDetailsTest() {
|
||||
setupHooks(
|
||||
additionalBeforeSection = {
|
||||
resetWireMockScenarios()
|
||||
setWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO, eligibilityState)
|
||||
setWireMockScenarioState(balanceScenario, balanceInitialState)
|
||||
setWireMockScenarioState(cardReissueScenario, cardReissueStartedState)
|
||||
},
|
||||
additionalAfterSection = {
|
||||
resetWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO)
|
||||
resetWireMockScenarioState(balanceScenario)
|
||||
resetWireMockScenarioState(cardReissueScenario)
|
||||
},
|
||||
).run {
|
||||
step("Open Tangem Pay card page") { openTangemPayCardPage() }
|
||||
step("Open the 'Replace card' reissue bottom sheet") { openReissueSheet() }
|
||||
step("Assert reissue sheet title, description and fee label are displayed") {
|
||||
onTangemPayReissueSheet {
|
||||
title.assertIsDisplayed()
|
||||
description.assertIsDisplayed()
|
||||
feeLabel.assertIsDisplayed()
|
||||
}
|
||||
}
|
||||
step("Assert replacement fee value is displayed") {
|
||||
flakySafely(WAIT_UNTIL_TIMEOUT) {
|
||||
onTangemPayReissueSheet { feeValue.assertTextContainsSafe("1.00", substring = true) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AllureId("9833")
|
||||
@DisplayName("Tangem Pay: error is shown when reissue cost is not fetched")
|
||||
@Test
|
||||
fun reissueFeeErrorShowsErrorWhenFeeRequestFailsTest() {
|
||||
setupHooks(
|
||||
additionalBeforeSection = {
|
||||
resetWireMockScenarios()
|
||||
setWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO, eligibilityState)
|
||||
setWireMockScenarioState(cardReissueScenario, cardReissueFeeErrorState)
|
||||
},
|
||||
additionalAfterSection = {
|
||||
resetWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO)
|
||||
resetWireMockScenarioState(cardReissueScenario)
|
||||
},
|
||||
).run {
|
||||
step("Open Tangem Pay card page") { openTangemPayCardPage() }
|
||||
step("Open the 'Replace card' reissue bottom sheet") { openReissueSheet() }
|
||||
step("Assert fee unreachable error and 'Refresh' button are displayed") {
|
||||
flakySafely(WAIT_UNTIL_TIMEOUT) {
|
||||
onTangemPayReissueSheet {
|
||||
feeErrorTitle.assertIsDisplayed()
|
||||
refreshButton.assertIsDisplayed()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AllureId("9752")
|
||||
@DisplayName("Tangem Pay: reissue fee transaction appears in history and details")
|
||||
@Test
|
||||
fun reissueFeeTransactionAppearsInHistoryAndDetailsTest() {
|
||||
val feeMerchantName = "Card replacement fee"
|
||||
|
||||
setupHooks(
|
||||
additionalBeforeSection = {
|
||||
resetWireMockScenarios()
|
||||
setWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO, eligibilityState)
|
||||
setWireMockScenarioState(balanceScenario, balanceInitialState)
|
||||
setWireMockScenarioState(cardReissueScenario, cardReissueStartedState)
|
||||
setWireMockScenarioState(reissueOrderScenario, reissueOrderStartedState)
|
||||
setWireMockScenarioState(historyScenario, historyInitialEmptyState)
|
||||
},
|
||||
additionalAfterSection = {
|
||||
resetWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO)
|
||||
resetWireMockScenarioState(balanceScenario)
|
||||
resetWireMockScenarioState(cardReissueScenario)
|
||||
resetWireMockScenarioState(reissueOrderScenario)
|
||||
resetWireMockScenarioState(historyScenario)
|
||||
},
|
||||
).run {
|
||||
step("Open Tangem Pay card page") { openTangemPayCardPage() }
|
||||
step("Open the 'Replace card' reissue bottom sheet") { openReissueSheet() }
|
||||
step("Wait for replacement fee to load") {
|
||||
flakySafely(WAIT_UNTIL_TIMEOUT) {
|
||||
onTangemPayReissueSheet { feeValue.assertTextContainsSafe("1.00", substring = true) }
|
||||
}
|
||||
}
|
||||
step("Click on 'Replace card' confirm button") {
|
||||
onTangemPayReissueSheet { confirmButton.clickWithAssertion() }
|
||||
}
|
||||
step("Assert reissue started and the sheet is dismissed") {
|
||||
flakySafely(WAIT_UNTIL_TIMEOUT) {
|
||||
onTangemPayCardPageScreen { reissueInProgressBlock.assertIsDisplayed() }
|
||||
}
|
||||
}
|
||||
step("Return to the payment account screen") {
|
||||
device.uiDevice.pressBack()
|
||||
flakySafely(WAIT_UNTIL_TIMEOUT) {
|
||||
onTangemPayMainScreen { balance.assertIsDisplayed() }
|
||||
}
|
||||
}
|
||||
step("Switch WireMock scenario '$historyScenario' to '$historyAfterReissueFeeState'") {
|
||||
setWireMockScenarioState(historyScenario, historyAfterReissueFeeState)
|
||||
}
|
||||
step("Pull to refresh Tangem Pay") { pullToRefreshTangemPay() }
|
||||
step("Assert '$feeMerchantName' transaction is displayed") {
|
||||
flakySafely(WAIT_UNTIL_TIMEOUT) {
|
||||
onTangemPayMainScreen { transactionRowWithText(feeMerchantName).assertIsDisplayed() }
|
||||
}
|
||||
}
|
||||
step("Click on '$feeMerchantName' transaction row") {
|
||||
onTangemPayMainScreen { transactionRowWithText(feeMerchantName).performClick() }
|
||||
}
|
||||
step("Assert fee transaction details are displayed") {
|
||||
flakySafely(WAIT_UNTIL_TIMEOUT) {
|
||||
onTangemPayTransactionDetailsSheet {
|
||||
feeTitle.assertIsDisplayed()
|
||||
serviceFeesCategory.assertIsDisplayed()
|
||||
amount.assertTextContainsSafe("1.00", substring = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AllureId("9743")
|
||||
@DisplayName("Tangem Pay: card reissue end-to-end replaces card with new details")
|
||||
@Test
|
||||
fun reissueEndToEndReplacesCardWithNewDetailsTest() {
|
||||
val reissuedCardLastDigits = "5353"
|
||||
val balanceAfterWithdrawState = "AfterWithdraw"
|
||||
|
||||
// AfterWithdraw funds the fee check without a customer/me stub, so reissued customer/me wins.
|
||||
setupHooks(
|
||||
additionalBeforeSection = {
|
||||
resetWireMockScenarios()
|
||||
setWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO, eligibilityState)
|
||||
setWireMockScenarioState(balanceScenario, balanceAfterWithdrawState)
|
||||
setWireMockScenarioState(cardReissueScenario, cardReissueStartedState)
|
||||
setWireMockScenarioState(reissueOrderScenario, reissueOrderStartedState)
|
||||
},
|
||||
additionalAfterSection = {
|
||||
resetWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO)
|
||||
resetWireMockScenarioState(balanceScenario)
|
||||
resetWireMockScenarioState(cardReissueScenario)
|
||||
resetWireMockScenarioState(reissueOrderScenario)
|
||||
resetWireMockScenarioState(reissueScenario)
|
||||
},
|
||||
).run {
|
||||
var oldCardNumber = ""
|
||||
step("Open Tangem Pay card page") { openTangemPayCardPage() }
|
||||
step("Read the current card number") {
|
||||
onTangemPayCardPageScreen { cardNumberShort.assertIsDisplayed() }
|
||||
onTangemPayCardPageScreen { oldCardNumber = cardNumberShort.extractText() }
|
||||
}
|
||||
step("Open the 'Replace card' reissue bottom sheet") { openReissueSheet() }
|
||||
step("Wait for replacement fee to load") {
|
||||
flakySafely(WAIT_UNTIL_TIMEOUT) {
|
||||
onTangemPayReissueSheet { feeValue.assertTextContainsSafe("1.00", substring = true) }
|
||||
}
|
||||
}
|
||||
step("Click on 'Replace card' confirm button") {
|
||||
onTangemPayReissueSheet { confirmButton.clickWithAssertion() }
|
||||
}
|
||||
step("Assert reissue started (sheet dismissed, card is replacing)") {
|
||||
flakySafely(WAIT_UNTIL_TIMEOUT) {
|
||||
onTangemPayReissueSheet { confirmButton.assertDoesNotExist() }
|
||||
onTangemPayCardPageScreen { reissueInProgressBlock.assertIsDisplayed() }
|
||||
}
|
||||
}
|
||||
step("Switch WireMock scenario '$reissueOrderScenario' to '$reissueOrderCompletedState'") {
|
||||
setWireMockScenarioState(reissueOrderScenario, reissueOrderCompletedState)
|
||||
}
|
||||
step("Switch WireMock scenario '$reissueScenario' to '$reissueCompletedState'") {
|
||||
setWireMockScenarioState(reissueScenario, reissueCompletedState)
|
||||
}
|
||||
step("Return to the payment account screen") {
|
||||
device.uiDevice.pressBack()
|
||||
flakySafely(WAIT_UNTIL_TIMEOUT) {
|
||||
onTangemPayMainScreen { balance.assertIsDisplayed() }
|
||||
}
|
||||
}
|
||||
step("Refresh until the card leaves the replacing state") {
|
||||
pullToRefreshTangemPay()
|
||||
flakySafely(WAIT_UNTIL_TIMEOUT_VERY_LONG) {
|
||||
onTangemPayMainScreen { reissueInProgressBanner.assertDoesNotExist() }
|
||||
}
|
||||
}
|
||||
step("Reopen the reissued card") {
|
||||
onTangemPayMainScreen { cardButton.clickWithAssertion() }
|
||||
}
|
||||
var newCardNumber = ""
|
||||
step("Read the new card number") {
|
||||
flakySafely(WAIT_UNTIL_TIMEOUT) {
|
||||
onTangemPayCardPageScreen {
|
||||
cardNumberShort.assertTextContainsSafe(reissuedCardLastDigits, substring = true)
|
||||
}
|
||||
}
|
||||
onTangemPayCardPageScreen { newCardNumber = cardNumberShort.extractText() }
|
||||
}
|
||||
step("Assert the card number changed after reissue") {
|
||||
Assert.assertNotEquals(oldCardNumber, newCardNumber)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AllureId("9746")
|
||||
@DisplayName("Tangem Pay: top up via card reissue when unable to cover fee")
|
||||
@Test
|
||||
fun reissueTopUpUnableToCoverFeeAddFundsReceiveTest() {
|
||||
val depositNetworkName = "Polygon"
|
||||
|
||||
setupHooks(
|
||||
additionalBeforeSection = {
|
||||
resetWireMockScenarios()
|
||||
setWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO, eligibilityState)
|
||||
setWireMockScenarioState(cardReissueScenario, cardReissueStartedState)
|
||||
},
|
||||
additionalAfterSection = {
|
||||
resetWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO)
|
||||
resetWireMockScenarioState(cardReissueScenario)
|
||||
},
|
||||
).run {
|
||||
step("Open Tangem Pay card page") { openTangemPayCardPage() }
|
||||
step("Open the 'Replace card' reissue bottom sheet") { openReissueSheet() }
|
||||
step("Assert 'Unable to cover fee' state is displayed") {
|
||||
flakySafely(WAIT_UNTIL_TIMEOUT) {
|
||||
onTangemPayReissueSheet { insufficientFundsTitle.assertIsDisplayed() }
|
||||
}
|
||||
}
|
||||
step("Click on 'Add funds' button") {
|
||||
onTangemPayReissueSheet { addFundsButton.clickWithAssertion() }
|
||||
}
|
||||
step("Assert 'Add funds' sheet shows Swap and Receive options") {
|
||||
flakySafely(WAIT_UNTIL_TIMEOUT) {
|
||||
onTangemPayAddFundsSheet {
|
||||
swapOption.assertIsDisplayed()
|
||||
receiveOption.assertIsDisplayed()
|
||||
}
|
||||
}
|
||||
}
|
||||
step("Click on 'Receive' option") {
|
||||
onTangemPayAddFundsSheet { receiveOption.clickWithAssertion() }
|
||||
}
|
||||
step("Assert deposit info for the '$depositNetworkName' network is displayed") {
|
||||
flakySafely(WAIT_UNTIL_TIMEOUT) {
|
||||
onTokenReceiveWarningBottomSheet {
|
||||
bottomSheet.assertIsDisplayed()
|
||||
networkName(depositNetworkName).assertIsDisplayed()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -24,6 +24,19 @@ object TangemPayTestTags {
|
|||
const val FREEZE_CARD_ROW = "TANGEM_PAY_FREEZE_CARD_ROW"
|
||||
const val CARD_FROZEN_BADGE = "TANGEM_PAY_CARD_FROZEN_BADGE"
|
||||
|
||||
// Card page top bar more-actions menu (redesign)
|
||||
const val CARD_PAGE_MORE_BUTTON = "TANGEM_PAY_CARD_PAGE_MORE_BUTTON"
|
||||
|
||||
// Masked card number shown on the card face (e.g. "*4242")
|
||||
const val CARD_NUMBER_SHORT = "TANGEM_PAY_CARD_NUMBER_SHORT"
|
||||
|
||||
// Replace card (reissue) bottom sheet
|
||||
const val REISSUE_SHEET_CONFIRM_BUTTON = "TANGEM_PAY_REISSUE_SHEET_CONFIRM_BUTTON"
|
||||
const val REISSUE_SHEET_FEE_VALUE = "TANGEM_PAY_REISSUE_SHEET_FEE_VALUE"
|
||||
|
||||
// Transaction details bottom sheet
|
||||
const val TRANSACTION_DETAILS_AMOUNT = "TANGEM_PAY_TRANSACTION_DETAILS_AMOUNT"
|
||||
|
||||
// Freeze confirmation bottom sheet
|
||||
const val FREEZE_CONFIRMATION_SUBMIT_BUTTON = "TANGEM_PAY_FREEZE_CONFIRMATION_SUBMIT_BUTTON"
|
||||
|
||||
|
|
|
|||
|
|
@ -448,7 +448,8 @@ private fun ConstraintLayoutScope.CardNumberBlock(
|
|||
start.linkTo(parent.start)
|
||||
bottom.linkTo(parent.bottom)
|
||||
}
|
||||
.padding(bottom = 8.dp),
|
||||
.padding(bottom = 8.dp)
|
||||
.testTag(TangemPayTestTags.CARD_NUMBER_SHORT),
|
||||
)
|
||||
} else {
|
||||
Text(
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import com.tangem.core.ui.ds.topbar.TangemTopBar
|
|||
import com.tangem.core.ui.ds2.button.TangemButton
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.res.*
|
||||
import com.tangem.core.ui.test.TangemPayTestTags
|
||||
import com.tangem.domain.models.pay.TangemPayCardFrozenState
|
||||
import com.tangem.domain.models.pay.TangemPayCardState
|
||||
import com.tangem.features.tangempay.details.impl.R
|
||||
|
|
@ -355,6 +356,7 @@ private fun CardPageTopBar(
|
|||
endContent = {
|
||||
Box {
|
||||
TangemButton(
|
||||
modifier = Modifier.testTag(TangemPayTestTags.CARD_PAGE_MORE_BUTTON),
|
||||
iconStart = TangemIconUM.Icon(iconRes = CoreUiR.drawable.ic_more_default_24),
|
||||
onClick = { isDropdownMenuShown = true },
|
||||
size = TangemButton.Size.X11,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
|
|
@ -39,6 +40,7 @@ import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
|||
import com.tangem.core.ui.res.generated.icons.Icons
|
||||
import com.tangem.core.ui.res.generated.icons.ic_arrow_refresh_32
|
||||
import com.tangem.core.ui.res.generated.icons.ic_error_28
|
||||
import com.tangem.core.ui.test.TangemPayTestTags
|
||||
import com.tangem.features.tangempay.details.impl.R
|
||||
import com.tangem.features.tangempay.entity.TangemPayReissueCardError
|
||||
import com.tangem.features.tangempay.entity.TangemPayReissueCardUM
|
||||
|
|
@ -155,6 +157,7 @@ private fun FeeBlock(
|
|||
titleRes = R.string.tangempay_reissue_card_fee_label,
|
||||
value = state.feeAmount,
|
||||
showDivider = appearance.shouldShowBalanceRow,
|
||||
valueTestTag = TangemPayTestTags.REISSUE_SHEET_FEE_VALUE,
|
||||
)
|
||||
if (appearance.shouldShowBalanceRow) {
|
||||
FeeInfoRow(
|
||||
|
|
@ -166,7 +169,7 @@ private fun FeeBlock(
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun FeeInfoRow(titleRes: Int, value: String, showDivider: Boolean = false) {
|
||||
private fun FeeInfoRow(titleRes: Int, value: String, showDivider: Boolean = false, valueTestTag: String? = null) {
|
||||
TangemRow(
|
||||
divider = showDivider,
|
||||
contentLead = TangemRowContentLead.Start,
|
||||
|
|
@ -185,6 +188,7 @@ private fun FeeInfoRow(titleRes: Int, value: String, showDivider: Boolean = fals
|
|||
)
|
||||
} else {
|
||||
TangemRowText(
|
||||
modifier = if (valueTestTag != null) Modifier.testTag(valueTestTag) else Modifier,
|
||||
text = value,
|
||||
role = TangemRowTextRole.Value,
|
||||
)
|
||||
|
|
@ -213,7 +217,9 @@ private fun BottomButtonsBlock(
|
|||
text = resourceReference(R.string.common_cancel),
|
||||
)
|
||||
TangemButton(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(TangemPayTestTags.REISSUE_SHEET_CONFIRM_BUTTON),
|
||||
size = TangemButton.Size.X12,
|
||||
onClick = appearance.primaryAction(state),
|
||||
isEnabled = !state.isFeeLoading && !state.isReissuingInProgress,
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Devices
|
||||
|
|
@ -40,6 +41,7 @@ import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
|||
import com.tangem.core.ui.res.generated.icons.Icons
|
||||
import com.tangem.core.ui.res.generated.icons.ic_arrow_down_24
|
||||
import com.tangem.core.ui.res.generated.icons.ic_arrow_refresh_20
|
||||
import com.tangem.core.ui.test.TangemPayTestTags
|
||||
import com.tangem.features.tangempay.details.impl.R
|
||||
import com.tangem.features.tangempay.entity.*
|
||||
|
||||
|
|
@ -83,7 +85,9 @@ internal fun TangemPayTxHistoryDetailsContentV2(state: TangemPayTxHistoryDetails
|
|||
modifier = Modifier.padding(top = TangemTheme.dimens2.x12),
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.padding(top = TangemTheme.dimens2.x6),
|
||||
modifier = Modifier
|
||||
.padding(top = TangemTheme.dimens2.x6)
|
||||
.testTag(TangemPayTestTags.TRANSACTION_DETAILS_AMOUNT),
|
||||
text = state.transactionAmount.orMaskWithStars(state.isBalanceHidden),
|
||||
style = TangemTheme.typography3.display.medium,
|
||||
color = TangemTheme.colors3.text.primary,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue