From 5618f44c8b234525e85f37a27a12e129c52207a0 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 17 Jun 2026 11:00:59 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../screens/AddFundsBottomSheetPageObject.kt | 26 +++++- .../screens/AddTokenBottomSheetPageObject.kt | 5 ++ .../tangem/screens/MainScreenPageObject.kt | 8 ++ .../com/tangem/tests/addFunds/BuyTest.kt | 86 +++++++++++++++++++ .../ui/test/AddFundsBottomSheetTestTags.kt | 5 ++ .../core/ui/test/TokenActionsTestTags.kt | 5 ++ .../impl/addfunds/DefaultAddFundsComponent.kt | 12 ++- .../tokenactions/ui/TokenActionsContentV2.kt | 8 ++ 8 files changed, 151 insertions(+), 4 deletions(-) create mode 100644 app/src/androidTest/kotlin/com/tangem/tests/addFunds/BuyTest.kt create mode 100644 core/ui/src/main/java/com/tangem/core/ui/test/AddFundsBottomSheetTestTags.kt create mode 100644 core/ui/src/main/java/com/tangem/core/ui/test/TokenActionsTestTags.kt diff --git a/app/src/androidTest/kotlin/com/tangem/screens/AddFundsBottomSheetPageObject.kt b/app/src/androidTest/kotlin/com/tangem/screens/AddFundsBottomSheetPageObject.kt index 5586e86757..f27e8c0785 100644 --- a/app/src/androidTest/kotlin/com/tangem/screens/AddFundsBottomSheetPageObject.kt +++ b/app/src/androidTest/kotlin/com/tangem/screens/AddFundsBottomSheetPageObject.kt @@ -3,11 +3,17 @@ package com.tangem.screens import androidx.compose.ui.test.SemanticsNodeInteractionsProvider import com.tangem.common.BaseTestCase import com.tangem.core.ui.R +import com.tangem.core.ui.test.AddFundsBottomSheetTestTags import com.tangem.core.ui.test.BaseBottomSheetTestTags +import com.tangem.core.ui.test.BuyTokenScreenTestTags +import com.tangem.core.ui.test.MarketsTestTags +import com.tangem.core.ui.test.TokenActionsTestTags +import com.tangem.core.ui.test.TokenElementsTestTags 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 +import androidx.compose.ui.test.hasTestTag as withTestTag import androidx.compose.ui.test.hasText as withText class AddFundsBottomSheetPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) : @@ -32,7 +38,25 @@ class AddFundsBottomSheetPageObject(semanticsProvider: SemanticsNodeInteractions } val closeButton: KNode = child { - hasAnyChild(withText(getResourceString(R.string.common_close))) + hasTestTag(AddFundsBottomSheetTestTags.CLOSE_BUTTON) + useUnmergedTree = true + } + + val buyTokenButton: KNode = child { + hasTestTag(TokenActionsTestTags.BUY_ACTION) + useUnmergedTree = true + } + + fun userTokenWithTitle(tokenTitle: String): KNode = child { + hasTestTag(BuyTokenScreenTestTags.LAZY_LIST_ITEM) + hasAnyDescendant(withTestTag(TokenElementsTestTags.TOKEN_TITLE)) + hasAnyDescendant(withText(tokenTitle)) + useUnmergedTree = true + } + + fun trendingTokenWithTitle(tokenTitle: String): KNode = child { + hasTestTag(MarketsTestTags.TOKENS_LIST_ITEM) + hasAnyDescendant(withText(tokenTitle)) useUnmergedTree = true } } diff --git a/app/src/androidTest/kotlin/com/tangem/screens/AddTokenBottomSheetPageObject.kt b/app/src/androidTest/kotlin/com/tangem/screens/AddTokenBottomSheetPageObject.kt index e870bbb20e..61a833964a 100644 --- a/app/src/androidTest/kotlin/com/tangem/screens/AddTokenBottomSheetPageObject.kt +++ b/app/src/androidTest/kotlin/com/tangem/screens/AddTokenBottomSheetPageObject.kt @@ -21,6 +21,11 @@ class AddTokenBottomSheetPageObject(semanticsProvider: SemanticsNodeInteractions hasText(getResourceString(R.string.common_add_token)) } + val closeButton: KNode = child { + hasTestTag(BaseBottomSheetTestTags.CLOSE_BUTTON) + useUnmergedTree = true + } + val addButton: KNode = child { hasTestTag(BaseButtonTestTags.TEXT) hasText(getResourceString(R.string.common_add)) diff --git a/app/src/androidTest/kotlin/com/tangem/screens/MainScreenPageObject.kt b/app/src/androidTest/kotlin/com/tangem/screens/MainScreenPageObject.kt index ec4df4e127..5127d23985 100644 --- a/app/src/androidTest/kotlin/com/tangem/screens/MainScreenPageObject.kt +++ b/app/src/androidTest/kotlin/com/tangem/screens/MainScreenPageObject.kt @@ -439,6 +439,14 @@ class MainScreenPageObject(private val semanticsProvider: SemanticsNodeInteracti .onAllNodes(withTestTag(MainScreenTestTags.TOKEN_LIST_ITEM), useUnmergedTree = true) .assertCountEquals(expectedCount) } + + fun assertTokenExists(tokenTitle: String) { + lazyList.child { + hasTestTag(MainScreenTestTags.TOKEN_LIST_ITEM) + hasAnyDescendant(withText(tokenTitle)) + useUnmergedTree = true + }.assertIsDisplayed() + } } internal fun BaseTestCase.onMainScreen(function: MainScreenPageObject.() -> Unit) = diff --git a/app/src/androidTest/kotlin/com/tangem/tests/addFunds/BuyTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/addFunds/BuyTest.kt new file mode 100644 index 0000000000..91f7c4781d --- /dev/null +++ b/app/src/androidTest/kotlin/com/tangem/tests/addFunds/BuyTest.kt @@ -0,0 +1,86 @@ +package com.tangem.tests.addFunds + +import com.tangem.common.BaseTestCase +import com.tangem.common.extensions.assertTextContainsSafe +import com.tangem.common.extensions.clickWithAssertion +import com.tangem.scenarios.openMainScreen +import com.tangem.scenarios.synchronizeAddresses +import com.tangem.screens.onAddTokenBottomSheet +import com.tangem.screens.onAddFundsBottomSheet +import com.tangem.screens.onBuyTokenDetailsScreen +import com.tangem.screens.onMainScreen +import dagger.hilt.android.testing.HiltAndroidTest +import io.qameta.allure.kotlin.AllureId +import io.qameta.allure.kotlin.junit4.DisplayName +import org.junit.Test + +@HiltAndroidTest +class BuyTest : BaseTestCase() { + + @AllureId("587") + @DisplayName("Buy. Display tokens available for purchase") + @Test + fun buyDisplayTokensAvailableForPurchaseTest() { + val token = "Bitcoin" + + setupHooks().run { + step("Open 'Main' screen") { + openMainScreen() + } + step("Synchronize addresses") { + synchronizeAddresses() + } + step("Click on 'Add Funds' button") { + onMainScreen { addFundsButton.clickWithAssertion() } + } + step("Click on $token in Wallet list") { + onAddFundsBottomSheet { userTokenWithTitle(token).clickWithAssertion() } + } + step("Click on 'Buy' button") { + onAddFundsBottomSheet { buyTokenButton.clickWithAssertion() } + } + step("Verify 'Buy $token' title is displayed") { + onBuyTokenDetailsScreen { + topBarTitle.assertTextContainsSafe("Buy $token", substring = true) + } + } + } + } + + @AllureId("590") + @DisplayName("Buy. Adding trending token to the main screen") + @Test + fun buyAddingTrendingTokenToMainScreenTest() { + val token = "Solana" + + setupHooks().run { + step("Open 'Main' screen") { + openMainScreen() + } + step("Synchronize addresses") { + synchronizeAddresses() + } + step("Click on 'Add Funds' button") { + onMainScreen { addFundsButton.clickWithAssertion() } + } + step("Click on $token in Trending list") { + onAddFundsBottomSheet { trendingTokenWithTitle(token).clickWithAssertion() } + } + step("Click on 'Add' button") { + onAddTokenBottomSheet { addButton.clickWithAssertion() } + } + step("Close 'Get token' screen") { + onAddFundsBottomSheet { closeButton.clickWithAssertion() } + } + step("Verify token $token exists on main screen") { + onMainScreen { assertTokenExists(token) } + } + step("Click on 'Add Funds' button") { + onMainScreen { addFundsButton.clickWithAssertion() } + } + step("Verify token $token in Wallet list") { + onAddFundsBottomSheet { userTokenWithTitle(token).assertIsDisplayed() } + } + } + } +} \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/test/AddFundsBottomSheetTestTags.kt b/core/ui/src/main/java/com/tangem/core/ui/test/AddFundsBottomSheetTestTags.kt new file mode 100644 index 0000000000..b7d46405a3 --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/test/AddFundsBottomSheetTestTags.kt @@ -0,0 +1,5 @@ +package com.tangem.core.ui.test + +object AddFundsBottomSheetTestTags { + const val CLOSE_BUTTON = "ADD_FUNDS_BOTTOM_SHEET_CLOSE_BUTTON" +} \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/test/TokenActionsTestTags.kt b/core/ui/src/main/java/com/tangem/core/ui/test/TokenActionsTestTags.kt new file mode 100644 index 0000000000..de5853d4ab --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/test/TokenActionsTestTags.kt @@ -0,0 +1,5 @@ +package com.tangem.core.ui.test + +object TokenActionsTestTags { + const val BUY_ACTION = "TOKEN_ACTIONS_BUY_ACTION" +} \ No newline at end of file diff --git a/features/common-features/impl/src/main/java/com/tangem/features/commonfeatures/impl/addfunds/DefaultAddFundsComponent.kt b/features/common-features/impl/src/main/java/com/tangem/features/commonfeatures/impl/addfunds/DefaultAddFundsComponent.kt index bd8a8d939e..b04fce2df3 100644 --- a/features/common-features/impl/src/main/java/com/tangem/features/commonfeatures/impl/addfunds/DefaultAddFundsComponent.kt +++ b/features/common-features/impl/src/main/java/com/tangem/features/commonfeatures/impl/addfunds/DefaultAddFundsComponent.kt @@ -11,6 +11,7 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.vectorResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.tangem.core.decompose.context.AppComponentContext @@ -26,6 +27,7 @@ import com.tangem.core.ui.ds.topbar.TangemTopBarType import com.tangem.core.ui.extensions.clickableSingle import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemeRedesign +import com.tangem.core.ui.test.AddFundsBottomSheetTestTags import com.tangem.features.commonfeatures.api.addfunds.AddFundsComponent import com.tangem.features.commonfeatures.api.choosetoken.ChooseTokenComponent import com.tangem.features.commonfeatures.impl.R @@ -198,7 +200,11 @@ internal class DefaultAddFundsComponent @AssistedInject constructor( null }, endContent = { - CircleIconButton(iconRes = R.drawable.ic_close_24, onClick = onCloseClick) + CircleIconButton( + iconRes = R.drawable.ic_close_24, + onClick = onCloseClick, + modifier = Modifier.testTag(AddFundsBottomSheetTestTags.CLOSE_BUTTON), + ) }, ) } @@ -213,12 +219,12 @@ internal class DefaultAddFundsComponent @AssistedInject constructor( } @Composable - private fun CircleIconButton(iconRes: Int, onClick: () -> Unit) { + private fun CircleIconButton(iconRes: Int, onClick: () -> Unit, modifier: Modifier = Modifier) { Icon( imageVector = ImageVector.vectorResource(id = iconRes), contentDescription = null, tint = TangemTheme.colors2.graphic.neutral.primary, - modifier = Modifier + modifier = modifier .size(TangemTheme.dimens2.x11) .background( color = TangemTheme.colors2.button.backgroundSecondary, diff --git a/features/common-features/impl/src/main/java/com/tangem/features/commonfeatures/impl/tokenactions/ui/TokenActionsContentV2.kt b/features/common-features/impl/src/main/java/com/tangem/features/commonfeatures/impl/tokenactions/ui/TokenActionsContentV2.kt index f1df9cffe7..20c555716f 100644 --- a/features/common-features/impl/src/main/java/com/tangem/features/commonfeatures/impl/tokenactions/ui/TokenActionsContentV2.kt +++ b/features/common-features/impl/src/main/java/com/tangem/features/commonfeatures/impl/tokenactions/ui/TokenActionsContentV2.kt @@ -18,6 +18,7 @@ import androidx.compose.runtime.remember 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.SpanStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter @@ -42,6 +43,7 @@ import com.tangem.core.ui.format.bigdecimal.fiat import com.tangem.core.ui.format.bigdecimal.formatStyled import com.tangem.core.ui.format.bigdecimal.price import com.tangem.core.ui.res.* +import com.tangem.core.ui.test.TokenActionsTestTags import com.tangem.features.commonfeatures.impl.R import com.tangem.features.commonfeatures.impl.tokenactions.ui.state.PortfolioBadgeUM import com.tangem.features.commonfeatures.impl.tokenactions.ui.state.TokenActionsUM @@ -120,7 +122,13 @@ private fun QuickActionsList(state: TokenActionsUM, modifier: Modifier = Modifie enter = fadeIn() + expandVertically(), exit = fadeOut() + shrinkVertically(), ) { + val actionModifier = when (actionUM) { + is QuickActionUM.V1.Buy, is QuickActionUM.V2.Buy -> + Modifier.testTag(TokenActionsTestTags.BUY_ACTION) + else -> Modifier + } TokenActionRow( + modifier = actionModifier, iconRes = actionUM.icon, title = actionUM.title, description = actionUM.description,