Updated on 2026-08-14

This commit is contained in:
Tangem 2026-07-09 17:17:29 +02:00
commit 0583a20c60
4 changed files with 129 additions and 0 deletions

View file

@ -4,6 +4,7 @@ import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
import com.tangem.common.BaseTestCase
import com.tangem.core.ui.test.BaseActionButtonsBlockTestTags
import com.tangem.core.ui.test.TangemPayTestTags
import com.tangem.core.ui.test.TokenDetailsTopBarTestTags
import com.tangem.core.res.R as CoreResR
import io.github.kakaocup.compose.node.element.ComposeScreen
import io.github.kakaocup.compose.node.element.ComposeScreen.Companion.onComposeScreen
@ -41,6 +42,15 @@ class TangemPayMainPageObject(semanticsProvider: SemanticsNodeInteractionsProvid
useUnmergedTree = true
}
val moreActionsButton: KNode = child {
hasTestTag(TokenDetailsTopBarTestTags.MORE_BUTTON)
useUnmergedTree = true
}
val termsAndFeesMenuItem: KNode = child {
hasText(getResourceString(CoreResR.string.tangem_pay_terms_limits))
}
fun transactionRowWithText(text: String): KNode = child {
hasText(text)
useUnmergedTree = true

View file

@ -0,0 +1,36 @@
package com.tangem.screens.tangempay
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
import com.tangem.common.BaseTestCase
import com.tangem.core.ui.test.WarningBottomSheetTestTags
import com.tangem.core.res.R as CoreResR
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 TangemPayServiceUnavailableSheetPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<TangemPayServiceUnavailableSheetPageObject>(semanticsProvider = semanticsProvider) {
val title: KNode = child {
hasTestTag(WarningBottomSheetTestTags.TITLE)
hasText(getResourceString(CoreResR.string.tangempay_service_unavailable_title))
useUnmergedTree = true
}
val description: KNode = child {
hasTestTag(WarningBottomSheetTestTags.MESSAGE)
hasText(getResourceString(CoreResR.string.tangempay_service_unavailable_description))
useUnmergedTree = true
}
// Merged tree: BUTTON_PRIMARY tags the button, its label is a child — only the merged node has both.
val gotItButton: KNode = child {
hasTestTag(WarningBottomSheetTestTags.BUTTON_PRIMARY)
hasText(getResourceString(CoreResR.string.common_got_it))
}
}
internal fun BaseTestCase.onTangemPayServiceUnavailableSheet(
function: TangemPayServiceUnavailableSheetPageObject.() -> Unit,
) = onComposeScreen(composeTestRule, function)

View file

@ -1,5 +1,12 @@
package com.tangem.tests.tangempay
import android.app.Activity
import android.app.Instrumentation.ActivityResult
import android.content.Intent
import androidx.test.espresso.intent.Intents.intended
import androidx.test.espresso.intent.Intents.intending
import androidx.test.espresso.intent.matcher.IntentMatchers.hasAction
import androidx.test.espresso.intent.matcher.IntentMatchers.hasData
import androidx.test.platform.app.InstrumentationRegistry
import com.tangem.common.BaseTestCase
import com.tangem.common.constants.TestConstants.TANGEM_PAY_ELIGIBILITY_SCENARIO
@ -11,11 +18,14 @@ import com.tangem.common.utils.assertClipboardTextEquals
import com.tangem.common.utils.resetWireMockScenarioState
import com.tangem.common.utils.resetWireMockScenarios
import com.tangem.common.utils.setWireMockScenarioState
import com.tangem.features.tangempay.TangemPayConstants
import com.tangem.scenarios.*
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.hamcrest.CoreMatchers.allOf
import org.junit.Ignore
import org.junit.Test
@HiltAndroidTest
@ -240,4 +250,75 @@ class TangemPayTest : BaseTestCase() {
}
}
}
@AllureId("9592")
@DisplayName("Tangem Pay: Terms and fees opens the tariffs document")
@Test
fun termsAndFeesOpensTariffsFromMoreActionsMenuTest() {
val eligibilityState = "PaeraCustomer"
setupHooks(
additionalBeforeSection = {
setWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO, eligibilityState)
},
additionalAfterSection = {
resetWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO)
},
).run {
step("Open Tangem Pay") { openTangemPay() }
step("Click on 'More actions' button") {
onTangemPayMainScreen { moreActionsButton.clickWithAssertion() }
}
step("Stub external browser so the tariffs document is not actually opened") {
intending(hasAction(Intent.ACTION_VIEW))
.respondWith(ActivityResult(Activity.RESULT_OK, null))
}
step("Click on 'Terms and fees' menu item") {
onTangemPayMainScreen { termsAndFeesMenuItem.clickWithAssertion() }
}
step("Assert the tariffs document is opened in an external browser") {
intended(allOf(hasAction(Intent.ACTION_VIEW), hasData(TangemPayConstants.TERMS_AND_LIMITS_LINK)))
}
}
}
// iOS-only: Android has no 'Service temporarily unavailable' sheet and no empty-depositAddress guard in Add funds.
@Ignore("[REDACTED_JIRA]")
@AllureId("9557")
@DisplayName("Tangem Pay: service unavailable error when customer has no deposit address")
@Test
fun addFundsShowsServiceUnavailableErrorWhenNoDepositAddressTest() {
val depositAddressScenario = "tangem_pay_deposit_address"
val noDepositAddressState = "NoDepositAddress"
val eligibilityState = "PaeraCustomer"
setupHooks(
additionalBeforeSection = {
setWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO, eligibilityState)
setWireMockScenarioState(depositAddressScenario, noDepositAddressState)
},
additionalAfterSection = {
resetWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO)
resetWireMockScenarioState(depositAddressScenario)
},
).run {
step("Open Tangem Pay") { openTangemPay() }
step("Click on 'Add funds' button") {
onTangemPayMainScreen { topUpButton.clickWithAssertion() }
}
step("Assert 'Service temporarily unavailable' sheet is displayed") {
onTangemPayServiceUnavailableSheet {
title.assertIsDisplayed()
description.assertIsDisplayed()
gotItButton.assertIsDisplayed()
}
}
step("Click on 'Got it' button") {
onTangemPayServiceUnavailableSheet { gotItButton.clickWithAssertion() }
}
step("Assert 'Service temporarily unavailable' sheet is not displayed") {
onTangemPayServiceUnavailableSheet { title.assertDoesNotExist() }
}
}
}
}

View file

@ -53,6 +53,7 @@ import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreviewRedesign
import com.tangem.core.ui.test.BaseActionButtonsBlockTestTags
import com.tangem.core.ui.test.TangemPayTestTags
import com.tangem.core.ui.test.TokenDetailsTopBarTestTags
import com.tangem.features.tangempay.components.express.PreviewEmptyExpressTransactionsComponent
import com.tangem.features.tangempay.components.txHistory.PreviewTangemPayTxHistoryComponent
import com.tangem.features.tangempay.components.txHistory.TangemPayTxHistoryComponent
@ -305,6 +306,7 @@ private fun PayDetailsTopBar(
var isDropdownMenuShown by rememberSaveable { mutableStateOf(false) }
Box {
TangemButton(
modifier = Modifier.testTag(TokenDetailsTopBarTestTags.MORE_BUTTON),
iconStart = TangemIconUM.Icon(iconRes = CoreUiR.drawable.ic_more_default_24),
onClick = {
config.onOpenMenu()