From ea9dbe405cb0540997fb298dd1269710239d46f9 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 9 Jul 2026 15:50:09 +0200 Subject: [PATCH] Updated on 2026-08-14 --- .../tangempay/TangemPayMainPageObject.kt | 10 +++ ...gemPayServiceUnavailableSheetPageObject.kt | 35 ++++++++ .../tangem/tests/tangempay/TangemPayTest.kt | 83 +++++++++++++++++++ .../tangempay/ui/TangemPayDetailsScreenV2.kt | 2 + 4 files changed, 130 insertions(+) create mode 100644 app/src/androidTest/kotlin/com/tangem/screens/tangempay/TangemPayServiceUnavailableSheetPageObject.kt diff --git a/app/src/androidTest/kotlin/com/tangem/screens/tangempay/TangemPayMainPageObject.kt b/app/src/androidTest/kotlin/com/tangem/screens/tangempay/TangemPayMainPageObject.kt index 731172c3e2..caee319f6b 100644 --- a/app/src/androidTest/kotlin/com/tangem/screens/tangempay/TangemPayMainPageObject.kt +++ b/app/src/androidTest/kotlin/com/tangem/screens/tangempay/TangemPayMainPageObject.kt @@ -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 diff --git a/app/src/androidTest/kotlin/com/tangem/screens/tangempay/TangemPayServiceUnavailableSheetPageObject.kt b/app/src/androidTest/kotlin/com/tangem/screens/tangempay/TangemPayServiceUnavailableSheetPageObject.kt new file mode 100644 index 0000000000..c79b163135 --- /dev/null +++ b/app/src/androidTest/kotlin/com/tangem/screens/tangempay/TangemPayServiceUnavailableSheetPageObject.kt @@ -0,0 +1,35 @@ +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(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 + } + + val gotItButton: KNode = child { + hasTestTag(WarningBottomSheetTestTags.BUTTON_PRIMARY) + useUnmergedTree = true + } +} + +internal fun BaseTestCase.onTangemPayServiceUnavailableSheet( + function: TangemPayServiceUnavailableSheetPageObject.() -> Unit, +) = onComposeScreen(composeTestRule, function) \ No newline at end of file diff --git a/app/src/androidTest/kotlin/com/tangem/tests/tangempay/TangemPayTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/tangempay/TangemPayTest.kt index fa4e3f9910..34224ad4f7 100644 --- a/app/src/androidTest/kotlin/com/tangem/tests/tangempay/TangemPayTest.kt +++ b/app/src/androidTest/kotlin/com/tangem/tests/tangempay/TangemPayTest.kt @@ -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,77 @@ class TangemPayTest : BaseTestCase() { } } } + + @AllureId("9592") + @DisplayName("Tangem Pay: Terms and fees opens the tariffs document") + @Test + fun termsAndFeesOpensTariffsFromMoreActionsMenuTest() { + val eligibilityState = "PaeraCustomer" + + setupHooks( + additionalBeforeSection = { + resetWireMockScenarios() + setWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO, eligibilityState) + }, + additionalAfterSection = { + resetWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO) + }, + ).run { + 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 = { + resetWireMockScenarios() + setWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO, eligibilityState) + setWireMockScenarioState(depositAddressScenario, noDepositAddressState) + }, + additionalAfterSection = { + resetWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO) + resetWireMockScenarioState(depositAddressScenario) + }, + ).run { + 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() } + } + } + } } \ No newline at end of file diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreenV2.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreenV2.kt index ac0ea74c33..c73cf4a4ee 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreenV2.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayDetailsScreenV2.kt @@ -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 @@ -304,6 +305,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()