Updated on 2026-08-14

This commit is contained in:
Tangem 2026-03-31 16:15:55 +03:00
parent d465cafc8d
commit b517fe39dd
32 changed files with 790 additions and 61 deletions

View file

@ -167,6 +167,7 @@ abstract class BaseTestCase : TestCase(
"SWAP_REDESIGN_ENABLED" to false,
"ACCOUNTS_FEATURE_ENABLED" to true,
"GASLESS_APPROVAL_ENABLED" to true,
"MAIN_SCREEN_QR_SCANNING_ENABLED" to true,
)
)
}

View file

@ -1,9 +1,17 @@
package com.tangem.common.extensions
import android.support.annotation.PluralsRes
import androidx.compose.ui.test.SemanticsMatcher
import androidx.test.platform.app.InstrumentationRegistry
import com.tangem.core.ui.utils.LazyListItemPositionSemantics
import io.github.kakaocup.compose.node.builder.ViewBuilder
fun ViewBuilder.hasLazyListItemPosition(position: Int) = apply {
addSemanticsMatcher(SemanticsMatcher.expectValue(LazyListItemPositionSemantics, position))
}
}
fun getQuantityString(@PluralsRes resId: Int, quantity: Int, vararg formatArgs: Any): String =
InstrumentationRegistry.getInstrumentation()
.targetContext
.resources
.getQuantityString(resId, quantity, *formatArgs)

View file

@ -89,7 +89,7 @@ fun BaseTestCase.synchronizeAddresses(
fun BaseTestCase.openDeviceSettingsScreen() {
step("Open wallet details") {
waitForIdle()
onTopBar { moreButton.clickWithAssertion() }
onMainScreenTopBar { moreButton.clickWithAssertion() }
}
step("Open 'Wallet settings' screen") {
onDetailsScreen { walletNameButton.performClick() }
@ -101,7 +101,7 @@ fun BaseTestCase.openDeviceSettingsScreen() {
fun BaseTestCase.openWalletConnectScreen() {
step("Click 'More' button on TopBar") {
onTopBar { moreButton.clickWithAssertion() }
onMainScreenTopBar { moreButton.clickWithAssertion() }
}
step("Click on 'Wallet Connect' button") {
onDetailsScreen { walletConnectButton.clickWithAssertion() }

View file

@ -0,0 +1,24 @@
package com.tangem.screens
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
import com.tangem.common.BaseTestCase
import com.tangem.core.ui.test.AccountDetailsScreenTestTags
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
class AccountDetailsPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<AccountDetailsPageObject>(semanticsProvider = semanticsProvider) {
val topAppBarBackButton: KNode = child {
hasTestTag(TopAppBarTestTags.CLOSE_BUTTON)
}
val manageTokensButton: KNode = child {
hasTestTag(AccountDetailsScreenTestTags.MANAGE_TOKENS_BUTTON)
}
}
internal fun BaseTestCase.onAccountDetails(function: AccountDetailsPageObject.() -> Unit) =
onComposeScreen(composeTestRule, function)

View file

@ -3,6 +3,7 @@ package com.tangem.screens
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
import com.tangem.common.BaseTestCase
import com.tangem.core.ui.test.DetailsScreenTestTags
import com.tangem.core.ui.test.TopAppBarTestTags
import com.tangem.wallet.R
import io.github.kakaocup.compose.node.element.ComposeScreen
import io.github.kakaocup.compose.node.element.ComposeScreen.Companion.onComposeScreen
@ -10,10 +11,11 @@ import io.github.kakaocup.compose.node.element.KNode
import io.github.kakaocup.kakao.common.utilities.getResourceString
class DetailsPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<DetailsPageObject>(
semanticsProvider = semanticsProvider,
viewBuilderAction = { hasTestTag(DetailsScreenTestTags.SCREEN_CONTAINER) }
) {
ComposeScreen<DetailsPageObject>(semanticsProvider = semanticsProvider) {
val topAppBarBackButton: KNode = child {
hasTestTag(TopAppBarTestTags.CLOSE_BUTTON)
}
val walletConnectButton: KNode = child {
hasTestTag(DetailsScreenTestTags.SCREEN_ITEM)

View file

@ -6,6 +6,7 @@ import androidx.compose.ui.test.SemanticsMatcher
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
import androidx.compose.ui.test.hasAnyAncestor
import com.tangem.common.BaseTestCase
import com.tangem.common.extensions.getQuantityString
import com.tangem.common.extensions.hasLazyListItemPosition
import com.tangem.common.utils.LazyListItemNode
import com.tangem.core.ui.test.*
@ -154,6 +155,30 @@ class MainScreenPageObject(semanticsProvider: SemanticsNodeInteractionsProvider)
useUnmergedTree = true
}
val missingAddressNotificationIcon: KNode = child {
hasAnySibling(withText(getResourceString(R.string.warning_missing_derivation_title)))
hasTestTag(NotificationTestTags.ICON)
useUnmergedTree = true
}
val missingAddressNotificationTitle: KNode = child {
hasTestTag(NotificationTestTags.TITLE)
hasText(getResourceString(R.string.warning_missing_derivation_title))
useUnmergedTree = true
}
fun missingAddressNotificationMessage(networkCount: Int): KNode = child {
hasTestTag(NotificationTestTags.MESSAGE)
hasText(
getQuantityString(
R.plurals.warning_missing_derivation_message,
networkCount,
networkCount
)
)
useUnmergedTree = true
}
val totalBalanceContainer: KNode = child {
hasTestTag(MainScreenTestTags.WALLET_LIST_ITEM)
}
@ -189,6 +214,11 @@ class MainScreenPageObject(semanticsProvider: SemanticsNodeInteractionsProvider)
hasText(getResourceString(CoreUiR.string.wallet_notification_address_copied))
}
val organizeTokensButtonNode: KNode = child {
hasTestTag(MainScreenTestTags.ORGANIZE_TOKENS_BUTTON)
useUnmergedTree = true
}
/**
* Find token list item with title and address
*/
@ -203,6 +233,17 @@ class MainScreenPageObject(semanticsProvider: SemanticsNodeInteractionsProvider)
}
}
@OptIn(ExperimentalTestApi::class)
fun tokenWithCustomDerivationIcon(tokenTitle: String): KNode {
return lazyList.childWith<LazyListItemNode> {
hasTestTag(MainScreenTestTags.TOKEN_LIST_ITEM)
hasText(tokenTitle)
}.child<KNode> {
hasTestTag(TokenElementsTestTags.TOKEN_CUSTOM_DERIVATION_ICON)
useUnmergedTree = true
}
}
@OptIn(ExperimentalTestApi::class)
fun organizeTokensButton(): KNode {
return lazyList.childWith<LazyListItemNode> {

View file

@ -7,16 +7,18 @@ 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
class TopBarPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<TopBarPageObject>(
class MainScreenTopBarPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<MainScreenTopBarPageObject>(
semanticsProvider = semanticsProvider,
viewBuilderAction = { hasTestTag(MainScreenTestTags.TOP_BAR) }
) {
val moreButton: KNode = child {
hasTestTag(MainScreenTestTags.MORE_BUTTON)
hasPosition(1)
useUnmergedTree = true
}
}
internal fun BaseTestCase.onTopBar(function: TopBarPageObject.() -> Unit) =
internal fun BaseTestCase.onMainScreenTopBar(function: MainScreenTopBarPageObject.() -> Unit) =
onComposeScreen(composeTestRule, function)

View file

@ -0,0 +1,55 @@
package com.tangem.screens
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
import com.tangem.common.BaseTestCase
import com.tangem.common.R
import com.tangem.core.ui.test.BaseButtonTestTags
import com.tangem.core.ui.test.BaseSearchBarTestTags
import com.tangem.core.ui.test.ManageTokensScreenTestTags
import com.tangem.core.ui.test.SwitchTestTags
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
import androidx.compose.ui.test.hasAnySibling as withAnySibling
import androidx.compose.ui.test.hasAnyDescendant as withAnyDescendant
import androidx.compose.ui.test.hasAnyAncestor as withAnyAncestor
class ManageTokensPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<ManageTokensPageObject>(semanticsProvider = semanticsProvider) {
val searchField: KNode = child {
hasTestTag(BaseSearchBarTestTags.SEARCH_BAR)
}
fun tokenItem(tokenName: String): KNode = child {
hasTestTag(ManageTokensScreenTestTags.TOKEN_ITEM)
hasText(tokenName)
}
fun networkSwitch(networkName: String): KNode = child {
useUnmergedTree = true
addSemanticsMatcher(
withTestTag(SwitchTestTags.SWITCH)
.and(
withAnyAncestor(
withAnySibling(
withTestTag(ManageTokensScreenTestTags.NETWORK_NAME)
.and(withAnyDescendant(withText(networkName)))
)
)
)
)
}
val saveButton: KNode = child {
hasTestTag(BaseButtonTestTags.TEXT)
hasText(getResourceString(R.string.common_save))
useUnmergedTree = true
}
}
internal fun BaseTestCase.onManageTokensScreen(function: ManageTokensPageObject.() -> Unit) =
onComposeScreen(composeTestRule, function)

View file

@ -0,0 +1,42 @@
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.BaseButtonTestTags
import com.tangem.core.ui.test.BaseDialogTestTags
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 UnableToHideDialogPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<UnableToHideDialogPageObject>(semanticsProvider = semanticsProvider) {
fun unableToHideTokenTitle(tokenName: String): KNode = child {
hasTestTag(BaseDialogTestTags.TITLE)
hasText(getResourceString(
R.string.token_details_unable_hide_alert_title,
tokenName))
}
fun unableToHideTokenMessage(tokenName: String, tokenSymbol: String, networkName: String): KNode = child {
hasTestTag(BaseDialogTestTags.TEXT)
hasText(
getResourceString(
R.string.token_details_unable_hide_alert_message,
tokenName,
tokenSymbol,
networkName
)
)
}
val okButton: KNode = child {
hasTestTag(BaseButtonTestTags.BUTTON)
hasText(getResourceString(R.string.common_ok))
}
}
internal fun BaseTestCase.onUnableToHideDialog(function: UnableToHideDialogPageObject.() -> Unit) =
onComposeScreen(composeTestRule, function)

View file

@ -2,18 +2,22 @@ package com.tangem.screens
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
import com.tangem.common.BaseTestCase
import com.tangem.core.ui.test.TopAppBarTestTags
import com.tangem.core.ui.test.WalletSettingsScreenTestTags
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
import androidx.compose.ui.test.hasText as withText
class WalletSettingsPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<WalletSettingsPageObject>(
semanticsProvider = semanticsProvider,
viewBuilderAction = { hasTestTag(WalletSettingsScreenTestTags.SCREEN_CONTAINER) }
) {
ComposeScreen<WalletSettingsPageObject>(semanticsProvider = semanticsProvider) {
val topAppBarBackButton: KNode = child {
hasTestTag(TopAppBarTestTags.CLOSE_BUTTON)
}
private val walletSettingsItem: KNode = child {
hasTestTag(WalletSettingsScreenTestTags.SCREEN_ITEM)
}
@ -21,15 +25,24 @@ class WalletSettingsPageObject(semanticsProvider: SemanticsNodeInteractionsProvi
val linkMoreCardsButton: KNode = walletSettingsItem.child {
hasText(getResourceString(R.string.details_row_title_create_backup))
}
val deviceSettingsButton: KNode = walletSettingsItem.child {
hasText(getResourceString(R.string.card_settings_title))
}
val referralProgramButton: KNode = walletSettingsItem.child {
hasText(getResourceString(R.string.details_referral_title))
}
val forgetWalletButton: KNode = walletSettingsItem.child {
hasText(getResourceString(R.string.settings_forget_wallet))
}
fun accountItem(accountName: String): KNode = walletSettingsItem.child {
hasTestTag(WalletSettingsScreenTestTags.USER_ACCOUNT_ITEM)
hasAnyDescendant(withText(accountName))
useUnmergedTree = true
}
}
internal fun BaseTestCase.onWalletSettingsScreen(function: WalletSettingsPageObject.() -> Unit) =

View file

@ -19,7 +19,7 @@ class DetailsTest : BaseTestCase() {
step("Open 'Main Screen'") {
openMainScreen()
}
onTopBar {
onMainScreenTopBar {
step("Open wallet details") {
moreButton.clickWithAssertion()
}
@ -66,7 +66,7 @@ class DetailsTest : BaseTestCase() {
step("Open 'Main Screen'") {
openMainScreen(productType = ProductType.Wallet2)
}
onTopBar {
onMainScreenTopBar {
step("Open wallet details") {
moreButton.clickWithAssertion()
}
@ -116,7 +116,7 @@ class DetailsTest : BaseTestCase() {
step("Open 'Main Screen'") {
openMainScreen(ProductType.Note)
}
onTopBar {
onMainScreenTopBar {
step("Open wallet details") {
moreButton.clickWithAssertion()
}
@ -163,7 +163,7 @@ class DetailsTest : BaseTestCase() {
openMainScreen()
}
step("Open wallet details") {
onTopBar { moreButton.clickWithAssertion() }
onMainScreenTopBar { moreButton.clickWithAssertion() }
}
step("Open 'Wallet settings' screen") {
onDetailsScreen { walletNameButton.clickWithAssertion() }

View file

@ -26,7 +26,7 @@ import com.tangem.screens.onSendConfirmScreen
import com.tangem.screens.onSendScreen
import com.tangem.screens.onStoriesScreen
import com.tangem.screens.onTokenDetailsScreen
import com.tangem.screens.onTopBar
import com.tangem.screens.onMainScreenTopBar
import com.tangem.tap.domain.sdk.mocks.MockProvider
import com.tangem.tap.store
import dagger.hilt.android.testing.HiltAndroidTest
@ -57,7 +57,7 @@ class FeedbackTest : BaseTestCase() {
}
step("Click 'More' button on TopBar") {
waitForIdle()
onTopBar { moreButton.clickWithAssertion() }
onMainScreenTopBar { moreButton.clickWithAssertion() }
}
step("Click 'Contact support' button") {
waitForIdle()

View file

@ -1,20 +0,0 @@
package com.tangem.tests
import com.tangem.common.BaseTestCase
import com.tangem.scenarios.openMainScreen
import dagger.hilt.android.testing.HiltAndroidTest
import org.junit.Test
@HiltAndroidTest
class MainScreenTest : BaseTestCase() {
@Test
fun goToMain() {
setupHooks().run {
step("Open 'Main Screen'") {
openMainScreen()
}
}
}
}

View file

@ -14,7 +14,6 @@ import com.tangem.tap.domain.sdk.mocks.content.*
import dagger.hilt.android.testing.HiltAndroidTest
import io.qameta.allure.kotlin.AllureId
import io.qameta.allure.kotlin.junit4.DisplayName
import org.junit.Ignore
import org.junit.Test
@HiltAndroidTest
@ -86,7 +85,6 @@ class ScanCardTest : BaseTestCase() {
}
}
@Ignore("TODO: [REDACTED_JIRA]")
@AllureId("870")
@DisplayName("Scan: Card with Ed25519 curve")
@Test

View file

@ -0,0 +1,312 @@
package com.tangem.tests.main
import androidx.compose.ui.test.longClick
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.*
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 HideTokenTest : BaseTestCase() {
@AllureId("3638")
@DisplayName("Main: hide token by long tap")
@Test
fun hideTokenByLongTapTest() {
val tokenTitle = "Polygon"
setupHooks().run {
step("Open 'Main Screen'") {
openMainScreen()
}
step("Synchronize addresses") {
synchronizeAddresses()
}
step("Long click on token with name: '$tokenTitle'") {
waitForIdle()
onMainScreen {
tokenWithTitleAndAddress(tokenTitle).performTouchInput {
longClick(
position = center,
durationMillis = 1000L
)
}
}
}
step("Click on 'Hide token' button") {
onTokenActionsBottomSheet { hideTokenButton.performClick() }
}
step("Click 'Hide' button in dialog") {
onDialog {
dialogContainer.assertIsDisplayed()
okButton.clickWithAssertion()
}
}
step("Assert token: '$tokenTitle' is not displayed") {
onMainScreen { assertTokenDoesNotExist(tokenTitle) }
}
}
}
@AllureId("3627")
@DisplayName("Main: hide token via Manage tokens")
@Test
fun hideTokenViaManageTokensTest() {
val tokenTitle = "Tether"
val networkTitle = "ETHEREUM"
val scenarioState = "USDT"
val accountName = "Main account"
setupHooks(
additionalAfterSection = {
resetWireMockScenarioState(USER_TOKENS_API_SCENARIO)
}
).run {
step("Set WireMock scenario: '$USER_TOKENS_API_SCENARIO' to state: '$scenarioState'") {
setWireMockScenarioState(USER_TOKENS_API_SCENARIO, scenarioState)
}
step("Open 'Main Screen'") {
openMainScreen()
}
step("Synchronize addresses") {
synchronizeAddresses()
}
step("Open wallet details") {
waitForIdle()
onMainScreenTopBar { moreButton.clickWithAssertion() }
}
step("Open 'Wallet settings' screen") {
onDetailsScreen { walletNameButton.performClick() }
}
step("Click on account: '$accountName'") {
onWalletSettingsScreen { accountItem(accountName).performClick() }
}
step("Click on 'Manage tokens' button") {
onAccountDetails { manageTokensButton.performClick() }
}
step("Click on token: '$tokenTitle'") {
onManageTokensScreen { tokenItem(tokenTitle).performClick() }
}
step("Assert switch is on") {
onManageTokensScreen { networkSwitch(networkTitle).assertIsOn() }
}
step("Click on '$networkTitle' switch") {
onManageTokensScreen { networkSwitch(networkTitle).performClick() }
}
step("Click 'Hide' button in dialog") {
onDialog {
dialogContainer.assertIsDisplayed()
hideButton.clickWithAssertion()
}
}
step("Assert switch is off") {
onManageTokensScreen { networkSwitch(networkTitle).assertIsOff() }
}
step("Click on 'Save' button") {
onManageTokensScreen { saveButton.performClick() }
}
step("Click on 'Account details' screen 'Back' button") {
waitForIdle()
onAccountDetails { topAppBarBackButton.performClick() }
}
step("Click on 'Wallet settings' screen 'Back' button") {
waitForIdle()
onWalletSettingsScreen { topAppBarBackButton.performClick() }
}
step("Click on 'Details' screen 'Back' button") {
waitForIdle()
onDetailsScreen { topAppBarBackButton.performClick() }
}
step("Assert token: '$tokenTitle' is not displayed") {
onMainScreen { assertTokenDoesNotExist(tokenTitle) }
}
}
}
@AllureId("3626")
@DisplayName("Main: hide main coin via manage tokens")
@Test
fun hideMainCoinViaManageTokensTest() {
val tokenTitle = "POL (ex-MATIC)"
val networkTitle = "POLYGON"
val polygonTitle = "Polygon"
val accountName = "Main account"
setupHooks().run {
step("Open 'Main Screen'") {
openMainScreen()
}
step("Synchronize addresses") {
synchronizeAddresses()
}
step("Open wallet details") {
waitForIdle()
onMainScreenTopBar { moreButton.clickWithAssertion() }
}
step("Open 'Wallet settings' screen") {
onDetailsScreen { walletNameButton.performClick() }
}
step("Click on account: '$accountName'") {
onWalletSettingsScreen { accountItem(accountName).performClick() }
}
step("Click on 'Manage tokens' button") {
onAccountDetails { manageTokensButton.performClick() }
}
step("Click on token: '$tokenTitle'") {
onManageTokensScreen { tokenItem(tokenTitle).performClick() }
}
step("Assert switch is on") {
onManageTokensScreen { networkSwitch(networkTitle).assertIsOn() }
}
step("Click on '$networkTitle' switch") {
onManageTokensScreen { networkSwitch(networkTitle).performClick() }
}
step("Click 'Hide' button in dialog") {
onDialog {
dialogContainer.assertIsDisplayed()
hideButton.clickWithAssertion()
}
}
step("Assert switch is off") {
onManageTokensScreen { networkSwitch(networkTitle).assertIsOff() }
}
step("Click on 'Save' button") {
onManageTokensScreen { saveButton.performClick() }
}
step("Click on 'Account details' screen 'Back' button") {
waitForIdle()
onAccountDetails { topAppBarBackButton.performClick() }
}
step("Click on 'Wallet settings' screen 'Back' button") {
waitForIdle()
onWalletSettingsScreen { topAppBarBackButton.performClick() }
}
step("Click on 'Details' screen 'Back' button") {
waitForIdle()
onDetailsScreen { topAppBarBackButton.performClick() }
}
step("Assert token: '$polygonTitle' is not displayed") {
onMainScreen { assertTokenDoesNotExist(polygonTitle) }
}
}
}
@AllureId("3610")
@DisplayName("Main: check 'Unable to hide token' warning")
@Test
fun checkUnableToHideTokenWarningTest() {
val tokenTitle = "Ethereum"
val tokenSymbol = "ETH"
val scenarioState = "USDT"
setupHooks(
additionalAfterSection = {
resetWireMockScenarioState(USER_TOKENS_API_SCENARIO)
}
).run {
step("Set WireMock scenario: '$USER_TOKENS_API_SCENARIO' to state: '$scenarioState'") {
setWireMockScenarioState(USER_TOKENS_API_SCENARIO, scenarioState)
}
step("Open 'Main Screen'") {
openMainScreen()
}
step("Synchronize addresses") {
synchronizeAddresses()
}
step("Long click on token with name: '$tokenTitle'") {
waitForIdle()
onMainScreen {
tokenWithTitleAndAddress(tokenTitle).performTouchInput {
longClick(
position = center,
durationMillis = 1000L
)
}
}
}
step("Click on 'Hide token' button") {
onTokenActionsBottomSheet { hideTokenButton.performClick() }
}
step("Assert 'Unable to hide $tokenTitle' alert title is displayed") {
onUnableToHideDialog {
unableToHideTokenTitle(tokenName = tokenTitle).assertIsDisplayed()
}
}
step("Assert 'Unable to hide $tokenTitle' alert message is displayed") {
onUnableToHideDialog {
unableToHideTokenMessage(
tokenName = tokenTitle,
tokenSymbol = tokenSymbol,
networkName = tokenTitle
).assertIsDisplayed()
}
}
step("Click on 'Ok' button") {
onUnableToHideDialog {
okButton.performClick()
}
}
step("Press 'Back' button") {
device.uiDevice.pressBack()
}
step("Assert token: '$tokenTitle' is displayed") {
onMainScreen { tokenWithTitleAndAddress(tokenTitle).assertIsDisplayed() }
}
step("Click on token: '$tokenTitle'") {
onMainScreen { tokenWithTitleAndAddress(tokenTitle).performClick() }
}
step("Assert 'Token details screen' open") {
onTokenDetailsScreen { screenContainer.assertIsDisplayed() }
}
step("Click 'More' button") {
onTokenDetailsTopBar { moreButton.clickWithAssertion() }
}
step("Click 'Hide token' button") {
onPopUpMenu {
popUpContainer.assertIsDisplayed()
hideTokenButton.clickWithAssertion()
}
}
step("Assert 'Unable to hide $tokenSymbol' alert title is displayed") {
onUnableToHideDialog {
unableToHideTokenTitle(tokenName = tokenSymbol).assertIsDisplayed()
}
}
step("Assert 'Unable to hide $tokenTitle' alert message is displayed") {
onUnableToHideDialog {
unableToHideTokenMessage(
tokenName = tokenTitle,
tokenSymbol = tokenSymbol,
networkName = tokenTitle
).assertIsDisplayed()
}
}
step("Click on 'Ok' button") {
onUnableToHideDialog {
okButton.performClick()
}
}
step("Click 'Back' button") {
onTokenDetailsTopBar { backButton.clickWithAssertion() }
}
step("Assert token: '$tokenTitle' is displayed") {
onMainScreen { tokenWithTitleAndAddress(tokenTitle).assertIsDisplayed() }
}
}
}
}

View file

@ -0,0 +1,114 @@
package com.tangem.tests.main
import com.tangem.common.BaseTestCase
import com.tangem.common.constants.TestConstants.USER_TOKENS_API_SCENARIO
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.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 MainScreenTest : BaseTestCase() {
@AllureId("66")
@DisplayName("Main: check 'Organize tokens' button with multiple tokens no accounts")
@Test
fun checkOrganizeTokensButtonWithMultipleTokensNoAccountsTest() {
setupHooks().run {
step("Open 'Main Screen'") {
openMainScreen()
}
step("Synchronize addresses") {
synchronizeAddresses()
}
step("Assert 'Organize tokens' button is displayed") {
onMainScreen { organizeTokensButton().assertIsDisplayed() }
}
}
}
@AllureId("8748")
@DisplayName("Main: check 'Organize tokens' button with single token no accounts")
@Test
fun checkOrganizeTokensButtonWithSingleTokenNoAccountsTest() {
val scenarioState = "Cardano"
setupHooks(
additionalAfterSection = {
resetWireMockScenarioState(USER_TOKENS_API_SCENARIO)
}
).run {
step("Set WireMock scenario: '$USER_TOKENS_API_SCENARIO' to state: '$scenarioState'") {
setWireMockScenarioState(USER_TOKENS_API_SCENARIO, scenarioState)
}
step("Open 'Main Screen'") {
openMainScreen()
}
step("Synchronize addresses") {
synchronizeAddresses()
}
step("Assert 'Organize tokens' button is not displayed") {
onMainScreen { organizeTokensButtonNode.assertIsNotDisplayed()}
}
}
}
@AllureId("8749")
@DisplayName("Main: check 'Organize tokens' button with single token two accounts")
@Test
fun checkOrganizeTokensButtonWithSingleTokenMultiAccountsTest() {
val scenarioState = "TwoAccountsSingleTokenEach"
setupHooks(
additionalAfterSection = {
resetWireMockScenarioState(USER_TOKENS_API_SCENARIO)
}
).run {
step("Set WireMock scenario: '$USER_TOKENS_API_SCENARIO' to state: '$scenarioState'") {
setWireMockScenarioState(USER_TOKENS_API_SCENARIO, scenarioState)
}
step("Open 'Main Screen'") {
openMainScreen()
}
step("Assert 'Organize tokens' button is not displayed") {
onMainScreen { organizeTokensButtonNode.assertIsNotDisplayed()}
}
}
}
@AllureId("8750")
@DisplayName("Main: check 'Organize tokens' button with multiple tokens two accounts")
@Test
fun checkOrganizeTokensButtonWithMultipleTokensMultiAccountsTest() {
val scenarioState = "TwoAccountsMixed"
setupHooks(
additionalAfterSection = {
resetWireMockScenarioState(USER_TOKENS_API_SCENARIO)
}
).run {
step("Set WireMock scenario: '$USER_TOKENS_API_SCENARIO' to state: '$scenarioState'") {
setWireMockScenarioState(USER_TOKENS_API_SCENARIO, scenarioState)
}
step("Open 'Main Screen'") {
openMainScreen()
}
step("Assert 'Organize tokens' button is not displayed") {
onMainScreen { organizeTokensButtonNode.assertIsDisplayed()}
}
}
}
}

View file

@ -0,0 +1,51 @@
package com.tangem.tests.main
import com.tangem.common.BaseTestCase
import com.tangem.common.constants.TestConstants.USER_TOKENS_API_SCENARIO
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.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 TokenListTest : BaseTestCase() {
@AllureId("180")
@DisplayName("Token list: hide token by long tap")
@Test
fun checkCustomDerivationIconOnTokenAndNetworkTest() {
val networkTitle = "Ethereum"
val customTokenTitle = "Myria"
val scenarioState = "CustomDerivation"
setupHooks(
additionalAfterSection = {
resetWireMockScenarioState(USER_TOKENS_API_SCENARIO)
}
).run {
step("Set WireMock scenario: '$USER_TOKENS_API_SCENARIO' to state: '$scenarioState'") {
setWireMockScenarioState(USER_TOKENS_API_SCENARIO, scenarioState)
}
step("Open 'Main Screen'") {
openMainScreen()
}
step("Synchronize addresses") {
synchronizeAddresses()
}
step("Assert token: '$networkTitle' is displayed") {
onMainScreen { tokenWithTitleAndAddress(networkTitle).assertIsDisplayed() }
}
step("Assert token with custom derivation icon: '$customTokenTitle' is displayed") {
onMainScreen { tokenWithCustomDerivationIcon(customTokenTitle).assertIsDisplayed() }
}
}
}
}

View file

@ -0,0 +1,52 @@
package com.tangem.tests.main
import com.tangem.common.BaseTestCase
import com.tangem.common.constants.TestConstants.USER_TOKENS_API_SCENARIO
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.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 WarningsTest : BaseTestCase() {
@AllureId("184")
@DisplayName("Token list: hide token by long tap")
@Test
fun checkUnavailableNetworksWarningTest() {
val scenarioState = "MissingDerivation"
val networkCount = 1
setupHooks(
additionalAfterSection = {
resetWireMockScenarioState(USER_TOKENS_API_SCENARIO)
}
).run {
step("Set WireMock scenario: '$USER_TOKENS_API_SCENARIO' to state: '$scenarioState'") {
setWireMockScenarioState(USER_TOKENS_API_SCENARIO, scenarioState)
}
step("Open 'Main Screen'") {
openMainScreen()
}
step("Synchronize addresses") {
synchronizeAddresses(isBalanceAvailable = false)
}
step("Assert 'Missing addresses' notification icon is displayed") {
onMainScreen { missingAddressNotificationIcon.assertIsDisplayed() }
}
step("Assert 'Missing addresses' notification title is displayed") {
onMainScreen { missingAddressNotificationTitle.assertIsDisplayed() }
}
step("Assert 'Missing addresses' notification message is displayed") {
onMainScreen { missingAddressNotificationMessage(networkCount).assertIsDisplayed() }
}
}
}
}

View file

@ -23,7 +23,7 @@ class SendAmountScreenTest : BaseTestCase() {
val manualSendAmount = "1"
val clipboardSendAmount = "0.5"
val invalidAmount = "2"
val errorText = getResourceString(R.string.send_validation_amount_exceeds_balance)
val errorText = getResourceString(R.string.common_insufficient_balance)
val context = device.context
setupHooks().run {

View file

@ -17,7 +17,6 @@ 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
@ -33,7 +32,6 @@ class StellarWarningsTest : BaseTestCase() {
getResourceString(R.string.send_notification_invalid_reserve_amount_title, reserveAmount)
private val warningMessage = getResourceString(R.string.send_notification_invalid_reserve_amount_text)
@Ignore("TODO: [REDACTED_JIRA]")
@AllureId("4287")
@DisplayName("Warnings: check warning, when sending less than reserve")
@Test
@ -87,7 +85,6 @@ class StellarWarningsTest : BaseTestCase() {
}
}
@Ignore("TODO: [REDACTED_JIRA]")
@AllureId("4286")
@DisplayName("Warnings: check warning when sending amount equal to reserve")
@Test
@ -142,7 +139,6 @@ class StellarWarningsTest : BaseTestCase() {
}
}
@Ignore("TODO: [REDACTED_JIRA]")
@AllureId("4288")
@DisplayName("Warnings: check warning when sending greater than reserve")
@Test