Updated on 2026-08-14

This commit is contained in:
Tangem 2026-05-28 14:09:23 +05:00
parent 2071dd9e2d
commit f8736fa64b
9 changed files with 180 additions and 57 deletions

View file

@ -97,8 +97,8 @@ fun BaseTestCase.checkMultiCurrencyMainScreen(
step("Assert devices count equal to '$devicesCount'") {
onMainScreen { walletDevicesCount.assertTextContains(devicesCount) }
}
step("Assert 'Buy' button is displayed") {
onMainScreen { buyButton.assertIsDisplayed() }
step("Assert 'Add funds' button is displayed") {
onMainScreen { addFundsButton.assertIsDisplayed() }
}
step("Assert 'Swap' button is displayed") {
onMainScreen { swapButton.assertIsDisplayed() }
@ -119,8 +119,8 @@ fun BaseTestCase.checkMultiCurrencyMainScreen(
fun BaseTestCase.assertActionButtonsForMultiCurrencyWallet(isEnabled: Boolean = true) {
if (isEnabled) {
step("Assert 'Buy' button is enabled") {
onMainScreen { buyButton.assertIsEnabled() }
step("Assert 'Add funds' button is enabled") {
onMainScreen { addFundsButton.assertIsEnabled() }
}
step("Assert 'Swap' button is enabled") {
onMainScreen { swapButton.assertIsEnabled() }
@ -129,8 +129,8 @@ fun BaseTestCase.assertActionButtonsForMultiCurrencyWallet(isEnabled: Boolean =
onMainScreen { sellButton.assertIsEnabled() }
}
} else {
step("Assert 'Buy' button is not enabled") {
onMainScreen { buyButton.assertIsNotEnabled() }
step("Assert 'Add funds' button is not enabled") {
onMainScreen { addFundsButton.assertIsNotEnabled() }
}
step("Assert 'Swap' button is not enabled") {
onMainScreen { swapButton.assertIsNotEnabled() }

View file

@ -0,0 +1,39 @@
package com.tangem.screens
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
import com.tangem.common.BaseTestCase
import com.tangem.core.ui.test.BaseSearchBarTestTags
import com.tangem.core.ui.test.BuyTokenScreenTestTags
import com.tangem.core.ui.test.TokenElementsTestTags
import com.tangem.core.ui.test.TopAppBarTestTags
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 androidx.compose.ui.test.hasTestTag as withTestTag
import androidx.compose.ui.test.hasText as withText
/**
* "You receive" token chooser opened from the main-screen "Add funds" button.
*/
class ChooseTokenPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<ChooseTokenPageObject>(semanticsProvider = semanticsProvider) {
val topAppBarTitle: KNode = child {
hasTestTag(TopAppBarTestTags.TITLE)
useUnmergedTree = true
}
val searchBar: KNode = child {
hasTestTag(BaseSearchBarTestTags.SEARCH_BAR)
}
fun tokenWithTitle(tokenTitle: String): KNode = child {
hasTestTag(BuyTokenScreenTestTags.LAZY_LIST_ITEM)
hasAnyDescendant(withTestTag(TokenElementsTestTags.TOKEN_TITLE))
hasAnyDescendant(withText(tokenTitle))
useUnmergedTree = true
}
}
internal fun BaseTestCase.onChooseTokenScreen(function: ChooseTokenPageObject.() -> Unit) =
onComposeScreen(composeTestRule, function)

View file

@ -0,0 +1,45 @@
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.BaseBottomSheetTestTags
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
/**
* "Get token" bottom sheet shown after picking a token in the Add funds flow.
* Contains quick actions (Buy / Receive / ) and the "Go to token" button.
*/
class GetTokenBottomSheetPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<GetTokenBottomSheetPageObject>(semanticsProvider = semanticsProvider) {
val title: KNode = child {
hasTestTag(BaseBottomSheetTestTags.TITLE)
}
val closeButton: KNode = child {
hasTestTag(BaseBottomSheetTestTags.CLOSE_BUTTON)
}
// The "Get token" sheet action rows use combinedClickable; the row's testTag lands on a
// separate zero-bounds semantics node that fails assertIsDisplayed. Matching the merged node
// by its title text yields the displayed, clickable row (performClick injects a touch at its
// center, which the row's clickable handles).
val buyButton: KNode = child {
hasText(getResourceString(R.string.common_buy))
}
val receiveButton: KNode = child {
hasText(getResourceString(R.string.common_receive))
}
val goToTokenButton: KNode = child {
hasText(getResourceString(R.string.common_go_to_token))
}
}
internal fun BaseTestCase.onGetTokenBottomSheet(function: GetTokenBottomSheetPageObject.() -> Unit) =
onComposeScreen(composeTestRule, function)

View file

@ -52,6 +52,11 @@ class MainScreenPageObject(semanticsProvider: SemanticsNodeInteractionsProvider)
hasText(getResourceString(R.string.common_buy))
}
val addFundsButton: KNode = child {
hasTestTag(BaseActionButtonsBlockTestTags.ACTION_BUTTON)
hasText(getResourceString(R.string.common_add_funds))
}
val sendButton: KNode = child {
hasTestTag(BaseActionButtonsBlockTestTags.ACTION_BUTTON)
hasText(getResourceString(R.string.common_send))

View file

@ -12,7 +12,7 @@ class TangemPayAddFundsSheetPageObject(semanticsProvider: SemanticsNodeInteracti
ComposeScreen<TangemPayAddFundsSheetPageObject>(semanticsProvider = semanticsProvider) {
val swapOption: KNode = child {
hasText(getResourceString(CoreResR.string.common_exchange))
hasText(getResourceString(CoreResR.string.tangempay_topup_swap_title))
useUnmergedTree = true
}

View file

@ -40,15 +40,18 @@ class BuyTokenTest : BaseTestCase() {
step("Synchronize addresses") {
synchronizeAddresses()
}
step("Click on 'Buy' button") {
onMainScreen { buyButton.clickWithAssertion() }
step("Click on 'Add funds' button") {
onMainScreen { addFundsButton.clickWithAssertion() }
}
step("Click on token with name: '$tokenTitle'") {
onBuyTokenScreen {
onChooseTokenScreen {
topAppBarTitle.assertIsDisplayed()
tokenWithTitleAndFiatAmount(tokenTitle).clickWithAssertion()
tokenWithTitle(tokenTitle).clickWithAssertion()
}
}
step("Click on 'Buy' in 'Get token' bottom sheet") {
onGetTokenBottomSheet { buyButton.clickWithAssertion() }
}
step("Assert error notification title is displayed") {
onBuyTokenDetailsScreen { errorNotificationTitle.assertIsDisplayed() }
}
@ -84,15 +87,18 @@ class BuyTokenTest : BaseTestCase() {
step("Synchronize addresses") {
synchronizeAddresses()
}
step("Click on 'Buy' button") {
onMainScreen { buyButton.clickWithAssertion() }
step("Click on 'Add funds' button") {
onMainScreen { addFundsButton.clickWithAssertion() }
}
step("Click on token with name: '$tokenTitle'") {
onBuyTokenScreen {
onChooseTokenScreen {
topAppBarTitle.assertIsDisplayed()
tokenWithTitleAndFiatAmount(tokenTitle).clickWithAssertion()
tokenWithTitle(tokenTitle).clickWithAssertion()
}
}
step("Click on 'Buy' in 'Get token' bottom sheet") {
onGetTokenBottomSheet { buyButton.clickWithAssertion() }
}
step("Click on 'Confirm' button in 'Dialog'") {
onDialog { confirmButton.clickWithAssertion() }
}
@ -155,15 +161,18 @@ class BuyTokenTest : BaseTestCase() {
step("Synchronize addresses") {
synchronizeAddresses()
}
step("Click on 'Buy' button") {
onMainScreen { buyButton.clickWithAssertion() }
step("Click on 'Add funds' button") {
onMainScreen { addFundsButton.clickWithAssertion() }
}
step("Click on token with name: '$tokenTitle'") {
onBuyTokenScreen {
onChooseTokenScreen {
topAppBarTitle.assertIsDisplayed()
tokenWithTitleAndFiatAmount(tokenTitle).clickWithAssertion()
tokenWithTitle(tokenTitle).clickWithAssertion()
}
}
step("Click on 'Buy' in 'Get token' bottom sheet") {
onGetTokenBottomSheet { buyButton.clickWithAssertion() }
}
step("Click on 'Confirm' button in 'Dialog'") {
onDialog { confirmButton.clickWithAssertion() }
}
@ -238,15 +247,18 @@ class BuyTokenTest : BaseTestCase() {
step("Synchronize addresses") {
synchronizeAddresses()
}
step("Click on 'Buy' button") {
onMainScreen { buyButton.clickWithAssertion() }
step("Click on 'Add funds' button") {
onMainScreen { addFundsButton.clickWithAssertion() }
}
step("Click on token with name: '$tokenTitle'") {
onBuyTokenScreen {
onChooseTokenScreen {
topAppBarTitle.assertIsDisplayed()
tokenWithTitleAndFiatAmount(tokenTitle).clickWithAssertion()
tokenWithTitle(tokenTitle).clickWithAssertion()
}
}
step("Click on 'Buy' in 'Get token' bottom sheet") {
onGetTokenBottomSheet { buyButton.clickWithAssertion() }
}
step("Click on 'Confirm' button in 'Dialog'") {
onDialog { confirmButton.clickWithAssertion() }
}
@ -320,15 +332,18 @@ class BuyTokenTest : BaseTestCase() {
step("Synchronize addresses") {
synchronizeAddresses()
}
step("Click on 'Buy' button") {
onMainScreen { buyButton.clickWithAssertion() }
step("Click on 'Add funds' button") {
onMainScreen { addFundsButton.clickWithAssertion() }
}
step("Click on token with name: '$tokenTitle'") {
onBuyTokenScreen {
onChooseTokenScreen {
topAppBarTitle.assertIsDisplayed()
tokenWithTitleAndFiatAmount(tokenTitle).clickWithAssertion()
tokenWithTitle(tokenTitle).clickWithAssertion()
}
}
step("Click on 'Buy' in 'Get token' bottom sheet") {
onGetTokenBottomSheet { buyButton.clickWithAssertion() }
}
step("Click on 'Confirm' button in 'Dialog'") {
onDialog { confirmButton.clickWithAssertion() }
}
@ -406,15 +421,18 @@ class BuyTokenTest : BaseTestCase() {
step("Synchronize addresses") {
synchronizeAddresses()
}
step("Click on 'Buy' button") {
onMainScreen { buyButton.clickWithAssertion() }
step("Click on 'Add funds' button") {
onMainScreen { addFundsButton.clickWithAssertion() }
}
step("Click on token with name: '$tokenTitle'") {
onBuyTokenScreen {
onChooseTokenScreen {
topAppBarTitle.assertIsDisplayed()
tokenWithTitleAndFiatAmount(tokenTitle).clickWithAssertion()
tokenWithTitle(tokenTitle).clickWithAssertion()
}
}
step("Click on 'Buy' in 'Get token' bottom sheet") {
onGetTokenBottomSheet { buyButton.clickWithAssertion() }
}
step("Click on 'Confirm' button in 'Dialog'") {
onDialog { confirmButton.clickWithAssertion() }
}

View file

@ -419,17 +419,17 @@ class MainScreenActionButtonsTest : BaseTestCase() {
step("Synchronize addresses") {
synchronizeAddresses()
}
step("Assert 'Buy' button is displayed") {
onMainScreen { buyButton.assertIsDisplayed() }
step("Assert 'Add funds' button is displayed") {
onMainScreen { addFundsButton.assertIsDisplayed() }
}
step("Click on 'Buy' button") {
onMainScreen { buyButton.performClick() }
step("Click on 'Add funds' button") {
onMainScreen { addFundsButton.performClick() }
}
step("Assert 'Buy' screen title is displayed") {
onBuyTokenScreen { topAppBarTitle.assertIsDisplayed() }
step("Assert 'Choose token' screen title is displayed") {
onChooseTokenScreen { topAppBarTitle.assertIsDisplayed() }
}
step("Assert token with title: '$tokenTitle' is displayed") {
onBuyTokenScreen { tokenWithTitleAndFiatAmount(tokenTitle).assertIsDisplayed() }
onChooseTokenScreen { tokenWithTitle(tokenTitle).assertIsDisplayed() }
}
step("Press 'Back' button") {
device.uiDevice.pressBack()
@ -478,17 +478,18 @@ class MainScreenActionButtonsTest : BaseTestCase() {
step("Open 'Main Screen'") {
openMainScreen()
}
step("Assert 'Buy' button is displayed") {
onMainScreen { buyButton.assertIsDisplayed() }
step("Assert 'Add funds' button is displayed") {
onMainScreen { addFundsButton.assertIsDisplayed() }
}
step("Click on 'Buy' button") {
onMainScreen { buyButton.performClick() }
step("Click on 'Add funds' button") {
onMainScreen { addFundsButton.performClick() }
}
step("Check 'Action is unavailable' dialog") {
checkActionIsUnavailableDialog()
step("Assert 'Choose token' screen opens (Add funds is always available)") {
onChooseTokenScreen { topAppBarTitle.assertIsDisplayed() }
}
step("Click on 'Ok' button") {
onDialog { okButton.performClick() }
step("Press 'Back' to return to main screen") {
device.uiDevice.pressBack()
waitForIdle()
}
step("Assert 'Swap' button is displayed") {
onMainScreen { swapButton.assertIsDisplayed() }
@ -535,17 +536,18 @@ class MainScreenActionButtonsTest : BaseTestCase() {
step("Open 'Main Screen'") {
openMainScreen()
}
step("Assert 'Buy' button is displayed") {
onMainScreen { buyButton.assertIsDisplayed() }
step("Assert 'Add funds' button is displayed") {
onMainScreen { addFundsButton.assertIsDisplayed() }
}
step("Click on 'Buy' button") {
onMainScreen { buyButton.performClick() }
step("Click on 'Add funds' button") {
onMainScreen { addFundsButton.performClick() }
}
step("Check 'Action is unavailable' dialog") {
checkActionIsUnavailableDialog()
step("Assert 'Choose token' screen opens (Add funds is always available)") {
onChooseTokenScreen { topAppBarTitle.assertIsDisplayed() }
}
step("Click on 'Ok' button") {
onDialog { okButton.performClick() }
step("Press 'Back' to return to main screen") {
device.uiDevice.pressBack()
waitForIdle()
}
step("Assert 'Swap' button is displayed") {
onMainScreen { swapButton.assertIsDisplayed() }

View file

@ -51,9 +51,12 @@ class HideTokenTest : BaseTestCase() {
dialogContainer.assertIsDisplayed()
okButton.clickWithAssertion()
}
waitForIdle()
}
step("Assert token: '$tokenTitle' is not displayed") {
onMainScreen { assertTokenDoesNotExist(tokenTitle) }
flakySafely {
onMainScreen { assertTokenDoesNotExist(tokenTitle) }
}
}
}
}

View file

@ -2,10 +2,12 @@ package com.tangem.tests.main
import com.tangem.common.BaseTestCase
import com.tangem.common.constants.TestConstants.USER_TOKENS_API_SCENARIO
import com.tangem.common.extensions.clickWithAssertion
import com.tangem.common.utils.resetWireMockScenarioState
import com.tangem.common.utils.setWireMockScenarioState
import com.tangem.scenarios.openMainScreen
import com.tangem.scenarios.synchronizeAddresses
import com.tangem.screens.onAddAndManageBottomSheet
import com.tangem.screens.onMainScreen
import dagger.hilt.android.testing.HiltAndroidTest
import io.qameta.allure.kotlin.AllureId
@ -81,8 +83,17 @@ class MainScreenTest : BaseTestCase() {
step("Open 'Main Screen'") {
openMainScreen()
}
step("Assert 'Add & Manage' button is not displayed") {
onMainScreen { addAndManageButtonNode.assertIsNotDisplayed()}
step("Assert 'Add & Manage' button is displayed") {
onMainScreen { addAndManageButtonNode.assertIsDisplayed() }
}
step("Click 'Add & Manage' button") {
onMainScreen { addAndManageButtonNode.clickWithAssertion() }
}
step("Assert 'Organize tokens' option is not displayed (nothing to organize)") {
onAddAndManageBottomSheet { organizeTokensButton.assertIsNotDisplayed() }
}
step("Assert 'Add tokens' option is displayed") {
onAddAndManageBottomSheet { addTokensButton.assertIsDisplayed() }
}
}
}