Updated on 2026-08-14

This commit is contained in:
Tangem 2026-07-13 23:39:01 +03:00
parent ece1122e14
commit d792ac6304
13 changed files with 73 additions and 30 deletions

View file

@ -223,6 +223,8 @@ abstract class BaseTestCase : TestCase(
"AND_15489_EXPRESS_SHARE_BUTTON_ENABLED" to true,
"AND_15235_VISA_MULTIPLE_CARDS" to true,
"AND_15715_SWAP_BEST_DEX_RATE_ENABLED" to true,
// 6.1
"TWI_1638_VA_MVP0_ENABLED" to true,
)
)
}

View file

@ -86,13 +86,23 @@ fun BaseTestCase.addMissingReceiveTokenToWallet(token: String, recipientWalletNa
runCatching { onSwapSelectTokenScreen { marketsTokenWithName(token).performClick() } }.isSuccess
}
}
// The 'Add token' sheet pre-selects the recipient (the only wallet missing the token, since the source already holds it).
step("Assert recipient wallet '$recipientWalletName' is selected") {
step("Select recipient wallet '$recipientWalletName'") {
composeTestRule.waitUntil(timeoutMillis = WAIT_UNTIL_TIMEOUT_LONG) {
runCatching { onAddToPortfolioScreen { walletName(recipientWalletName).assertIsDisplayed() } }.isSuccess
runCatching { onAddToPortfolioScreen { selectedWalletRow.performClick() } }.isSuccess
}
composeTestRule.waitUntil(timeoutMillis = WAIT_UNTIL_TIMEOUT_LONG) {
runCatching { onAddToPortfolioScreen { walletOption(recipientWalletName).performClick() } }.isSuccess
}
}
step("Click on 'Add' button") {
onAddToPortfolioScreen { addButton.performClick() }
step("Select network '$token'") {
composeTestRule.waitUntil(timeoutMillis = WAIT_UNTIL_TIMEOUT_LONG) {
runCatching { onAddToPortfolioScreen { networkRow.performClick() } }.isSuccess
}
composeTestRule.waitUntil(timeoutMillis = WAIT_UNTIL_TIMEOUT_LONG) {
runCatching { onAddToPortfolioScreen { networkOption(token).performClick() } }.isSuccess
}
}
step("Click on 'Confirm' button") {
onAddToPortfolioScreen { confirmButton.performClick() }
}
}

View file

@ -317,6 +317,9 @@ fun BaseTestCase.openSwapInTransferModeWithHotWallet(
}
private fun BaseTestCase.navigateToSwapForToken(tokenName: String, fromAccountName: String) {
step("Collapse header") {
onMainScreen { collapseHeader() }
}
step("Scroll '$fromAccountName' into view (semantics, not touch — avoids the Markets sheet)") {
onMainScreen { scrollToAccount(fromAccountName) }
}

View file

@ -1,24 +1,53 @@
package com.tangem.screens
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
import androidx.compose.ui.test.hasClickAction
import com.tangem.common.BaseTestCase
import com.tangem.core.ui.test.BaseBottomSheetTestTags
import com.tangem.wallet.R
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
// Scoped to the bottom-sheet container: the swap token-search screen stays behind the sheet and
// would otherwise make text matches (wallet tabs, market 'Ethereum' item) ambiguous.
class AddToPortfolioPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<AddToPortfolioPageObject>(semanticsProvider = semanticsProvider) {
ComposeScreen<AddToPortfolioPageObject>(
semanticsProvider = semanticsProvider,
viewBuilderAction = { hasTestTag(BaseBottomSheetTestTags.CONTAINER) },
) {
fun walletName(walletName: String): KNode = child {
hasText(walletName)
useUnmergedTree = true
}
val addButton: KNode = child {
hasText(getResourceString(R.string.common_add))
/** The wallet row on the 'Add token' screen (label + selected value); tap to open the wallet selector. */
val selectedWalletRow: KNode = child {
hasText(getResourceString(R.string.wc_common_wallet))
hasClickAction()
}
/** A wallet item inside the portfolio selector screen. */
fun walletOption(walletName: String): KNode = child {
hasText(walletName)
hasClickAction()
}
/** The network row on the 'Add token' screen; tap to open the 'Choose network' selector. */
val networkRow: KNode = child {
hasText(getResourceString(R.string.wc_common_network))
hasClickAction()
}
/** A network item inside the 'Choose network' selector. */
fun networkOption(networkName: String): KNode = child {
hasText(networkName)
hasClickAction()
}
val confirmButton: KNode = child {
hasText(getResourceString(R.string.common_confirm))
hasClickAction()
}
}

View file

@ -26,9 +26,9 @@ class AddTokenBottomSheetPageObject(semanticsProvider: SemanticsNodeInteractions
useUnmergedTree = true
}
val addButton: KNode = child {
val confirmButton: KNode = child {
hasTestTag(BaseButtonTestTags.TEXT)
hasText(getResourceString(R.string.common_add))
hasText(getResourceString(R.string.common_confirm))
useUnmergedTree = true
}

View file

@ -96,7 +96,7 @@ class MainScreenPageObject(private val semanticsProvider: SemanticsNodeInteracti
* Required because TangemCollapsingTopBar places the body at y=collapsingHeight, which
* pushes lower list items off-screen when the header is expanded.
*/
private fun collapseHeader() {
fun collapseHeader() {
screenContainer {
performTouchInput { swipeUp(startY = visibleSize.height * 0.6f, endY = visibleSize.height * 0.1f) }
}

View file

@ -6,7 +6,6 @@ import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
import androidx.compose.ui.test.captureToImage
import com.tangem.common.BaseTestCase
import com.tangem.core.ui.test.BaseBottomSheetTestTags
import com.tangem.core.ui.test.BaseButtonTestTags
import com.tangem.core.ui.test.TokenReceiveQrCodeBottomSheetTestTags
import com.tangem.wallet.R
import io.github.kakaocup.compose.intercept.operation.ComposeOperationType
@ -44,15 +43,13 @@ class TokenReceiveQrCodeBottomSheetPageObject(semanticsProvider: SemanticsNodeIn
}
val copyButton: KNode = child {
hasTestTag(BaseButtonTestTags.TEXT)
hasText(getResourceString(R.string.common_copy))
useUnmergedTree = true
hasClickAction()
}
val shareButton: KNode = child {
hasTestTag(BaseButtonTestTags.TEXT)
hasText(getResourceString(R.string.common_share))
useUnmergedTree = true
hasClickAction()
}
/** Captures the QR code node as a bitmap via the Kakao node delegate (no raw composeTestRule access). */

View file

@ -21,11 +21,13 @@ import dagger.hilt.android.testing.HiltAndroidTest
import io.github.kakaocup.kakao.common.utilities.getResourceString
import io.qameta.allure.kotlin.AllureId
import io.qameta.allure.kotlin.junit4.DisplayName
import org.junit.Ignore
import org.junit.Test
@HiltAndroidTest
class BlockchainTest : BaseTestCase() {
@Ignore("[REDACTED_JIRA]")
@AllureId("3644")
@DisplayName("ADA: Checking the min amount/change = 1ADA")
@Test

View file

@ -68,8 +68,8 @@ class BuyTest : BaseTestCase() {
step("Click on $token in Trending list") {
onAddFundsBottomSheet { trendingTokenWithTitle(token).clickWithAssertion() }
}
step("Click on 'Add' button") {
onAddTokenBottomSheet { addButton.clickWithAssertion() }
step("Click on 'Confirm' button") {
onAddTokenBottomSheet { confirmButton.clickWithAssertion() }
}
step("Close 'Get token' screen") {
onAddFundsBottomSheet { closeButton.clickWithAssertion() }

View file

@ -86,9 +86,9 @@ class TotalBalanceUpdateTest : BaseTestCase() {
step("Click on 'Add' button in 'Markets' bottom sheet") {
onMarketsScreen { addButton.clickWithAssertion() }
}
step("Click on 'Add' button in 'Add token' bottom sheet") {
step("Click on 'Confirm' button in 'Add token' bottom sheet") {
flakySafely(WAIT_UNTIL_TIMEOUT) {
onAddTokenBottomSheet { addButton.performClick() }
onAddTokenBottomSheet { confirmButton.performClick() }
}
}
step("Press 'Back' button") {

View file

@ -24,6 +24,7 @@ import org.junit.Test
@HiltAndroidTest
class SendConfirmScreenTest : BaseTestCase() {
@Ignore("[REDACTED_JIRA]")
@AllureId("4003")
@DisplayName("Send (Confirm screen): change sending amount")
@Test

View file

@ -58,8 +58,8 @@ class SearchAndSwapTest : BaseTestCase() {
onSwapSelectTokenScreen { marketsTokenWithName(receiveTokenName).clickWithAssertion() }
}
}
step("Click on 'Add' button") {
onAddTokenBottomSheet { addButton.performClick() }
step("Click on 'Confirm' button") {
onAddTokenBottomSheet { confirmButton.performClick() }
}
step("Assert swap token symbol: '$swapTokenSymbol' is displayed") {
onSwapTokenScreen { swapTokenSymbol(swapTokenSymbol).assertIsDisplayed() }
@ -106,8 +106,8 @@ class SearchAndSwapTest : BaseTestCase() {
onSwapSelectTokenScreen { marketsTokenWithName(receiveTokenName).clickWithAssertion() }
}
}
step("Click on 'Add' button") {
onAddTokenBottomSheet { addButton.performClick() }
step("Click on 'Confirm' button") {
onAddTokenBottomSheet { confirmButton.performClick() }
}
step("Assert swap token symbol: '$swapTokenSymbol' is displayed") {
onSwapTokenScreen { swapTokenSymbol(swapTokenSymbol).assertIsDisplayed() }
@ -195,8 +195,8 @@ class SearchAndSwapTest : BaseTestCase() {
onSwapSelectTokenScreen { marketsTokenWithName(receiveTokenName).clickWithAssertion() }
}
}
step("Click on 'Add' button") {
onAddTokenBottomSheet { addButton.performClick() }
step("Click on 'Confirm' button") {
onAddTokenBottomSheet { confirmButton.performClick() }
}
step("Assert warning title '$warningTitle' is displayed") {
onSwapTokenScreen { warningTitle(warningTitle).assertIsDisplayed() }
@ -251,8 +251,8 @@ class SearchAndSwapTest : BaseTestCase() {
onSwapSelectTokenScreen { marketsTokenWithName(swapTokenName).performClick() }
}
}
step("Click on 'Add' button") {
onAddTokenBottomSheet { addButton.performClick() }
step("Click on 'Confirm' button") {
onAddTokenBottomSheet { confirmButton.performClick() }
}
step("Assert swap token symbol: '$swapTokenSymbol' is displayed") {
onSwapTokenScreen { swapTokenSymbol(swapTokenSymbol).assertIsDisplayed() }

View file

@ -19,7 +19,6 @@ import com.tangem.tap.domain.sdk.mocks.content.Wallet2WithDerivationsMockContent
import com.tangem.tap.domain.sdk.mocks.content.WalletMockContent
import dagger.hilt.android.testing.HiltAndroidTest
import io.github.kakaocup.kakao.common.utilities.getResourceString
import io.qameta.allure.kotlin.Allure.step
import io.qameta.allure.kotlin.AllureId
import io.qameta.allure.kotlin.junit4.DisplayName
import org.junit.Ignore