Updated on 2026-08-14

This commit is contained in:
Tangem 2025-09-09 15:46:25 +03:00
parent 551e2a60bb
commit 700357c26b
44 changed files with 683 additions and 292 deletions

View file

@ -19,6 +19,8 @@ import com.tangem.core.configtoggle.feature.MutableFeatureTogglesManager
import com.tangem.datasource.api.common.config.managers.ApiConfigsManager
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys
import com.tangem.domain.promo.PromoRepository
import com.tangem.domain.promo.models.PromoId
import com.tangem.tap.MainActivity
import dagger.hilt.android.testing.HiltAndroidRule
import kotlinx.coroutines.runBlocking
@ -51,6 +53,9 @@ abstract class BaseTestCase : TestCase(
@Inject
lateinit var featureTogglesManager: FeatureTogglesManager
@Inject
lateinit var promoRepository: PromoRepository
private val hiltRule = HiltAndroidRule(this)
private val apiEnvironmentRule = ApiEnvironmentRule()
private val permissionRule = GrantPermissionRule.grant(
@ -91,6 +96,7 @@ abstract class BaseTestCase : TestCase(
value = false
)
}
promoRepository.setNeverToShowWalletPromo(PromoId.Sepa)
}
apiEnvironmentRule.setup(apiConfigsManager)
ActivityScenario.launch(MainActivity::class.java)

View file

@ -3,5 +3,7 @@ package com.tangem.common.constants
object TestConstants {
const val TOTAL_BALANCE = "$3,299.18"
const val RECIPIENT_ADDRESS = "0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0"
const val WAIT_UNTIL_TIMEOUT = 20_000L
}

View file

@ -1,29 +1,31 @@
package com.tangem.steps
package com.tangem.scenarios
import com.tangem.common.BaseTestCase
import com.tangem.common.extensions.clickWithAssertion
import com.tangem.domain.models.scan.ProductType
import com.tangem.screens.onDisclaimerScreen
import com.tangem.screens.onMainScreen
import com.tangem.screens.onMarketsTooltipScreen
import com.tangem.screens.onStoriesScreen
import com.tangem.screens.*
import com.tangem.tap.domain.sdk.mocks.MockProvider
import io.qameta.allure.kotlin.Allure.step
fun BaseTestCase.openMainScreen(productType: ProductType? = null) {
fun BaseTestCase.openMainScreen(productType: ProductType? = null, alreadyActivatedDialogIsShown : Boolean = false) {
if (productType != null) {
MockProvider.setMocks(productType)
}
step("Click on 'Accept' button") {
onDisclaimerScreen { acceptButton.clickWithAssertion() }
}
step("Click on 'Accept' button") {
step("Click on 'Scan' button") {
onStoriesScreen { scanButton.clickWithAssertion() }
}
step("Assert main screen is displayed") {
if (alreadyActivatedDialogIsShown) {
step("Click on 'This is my wallet' button") {
AlreadyUsedWalletDialogPageObject { thisIsMyWalletButton.click() }
}
}
step("Assert 'Main' screen is displayed") {
onMainScreen { screenContainer.assertIsDisplayed() }
}
step("Assert main screen is displayed") {
step("Click on 'Market Tooltip' screen") {
onMarketsTooltipScreen { contentContainer.clickWithAssertion() }
}
}

View file

@ -0,0 +1,26 @@
package com.tangem.scenarios
import android.content.Intent
import android.content.Intent.*
import android.net.Uri
import androidx.test.core.app.ApplicationProvider
import io.github.kakaocup.kakao.intent.KIntent
fun openAppByDeepLink(deepLinkUri: String?) {
val deeplinkScheme = "tangem://wc?uri="
val context = ApplicationProvider.getApplicationContext<android.content.Context>()
val intent = Intent(ACTION_VIEW, Uri.parse(deeplinkScheme + deepLinkUri)).apply {
addFlags(FLAG_ACTIVITY_NEW_TASK)
}
context.startActivity(intent)
}
fun checkSendEMailIntentCalled() {
val expectedIntent = KIntent {
hasAction(ACTION_CHOOSER)
hasExtra(EXTRA_TITLE, "Send mail...")
hasExtraWithKey(EXTRA_INTENT)
}
expectedIntent.intended()
}

View file

@ -0,0 +1,58 @@
package com.tangem.scenarios
import com.tangem.common.BaseTestCase
import com.tangem.screens.AlreadyUsedWalletDialogPageObject
import com.tangem.screens.ScanWarningDialogPageObject
import com.tangem.screens.onFailedTransactionDialog
import io.qameta.allure.kotlin.Allure.step
fun BaseTestCase.checkFailedTransactionDialog() {
step("Assert failed transaction dialog title is displayed") {
onFailedTransactionDialog { title.assertIsDisplayed() }
}
step("Assert failed transaction dialog text is displayed") {
onFailedTransactionDialog { text.assertIsDisplayed() }
}
step("Assert 'Cancel' button is displayed") {
onFailedTransactionDialog { cancelButton.assertIsDisplayed() }
}
step("Assert 'Support' button is displayed") {
onFailedTransactionDialog { supportButton.assertIsDisplayed() }
}
}
fun checkScanWarningDialog() {
step("Assert 'Scan warning' dialog title is displayed") {
ScanWarningDialogPageObject { warningTitle.isDisplayed() }
}
step("Assert warning dialog message is displayed") {
ScanWarningDialogPageObject { warningMessage.isDisplayed() }
}
step("Assert 'Cancel' button is displayed") {
ScanWarningDialogPageObject { cancelButton.isDisplayed() }
}
step("Assert 'How to scan' button is displayed") {
ScanWarningDialogPageObject { howToScanButton.isDisplayed() }
}
step("Assert 'Request support' button is displayed") {
ScanWarningDialogPageObject { requestSupportButton.isDisplayed() }
}
}
fun checkAlreadyUsedWalletDialog() {
step("Assert 'Already used Wallet' dialog title is displayed") {
AlreadyUsedWalletDialogPageObject { title.isDisplayed() }
}
step("Assert dialog message is displayed") {
AlreadyUsedWalletDialogPageObject { message.isDisplayed() }
}
step("Assert 'This is my wallet' button is displayed") {
AlreadyUsedWalletDialogPageObject { message.isDisplayed() }
}
step("Assert 'Cancel' button is displayed") {
AlreadyUsedWalletDialogPageObject { cancelButton.isDisplayed() }
}
step("Assert 'Request support' button is displayed") {
AlreadyUsedWalletDialogPageObject { requestSupportButton.isDisplayed() }
}
}

View file

@ -1,41 +0,0 @@
package com.tangem.scenarios
import androidx.compose.ui.test.junit4.ComposeTestRule
import com.kaspersky.kaspresso.testcases.api.scenario.Scenario
import com.kaspersky.kaspresso.testcases.core.testcontext.TestContext
import com.tangem.common.extensions.clickWithAssertion
import com.tangem.domain.models.scan.ProductType
import com.tangem.screens.*
import com.tangem.tap.domain.sdk.mocks.MockProvider
import io.github.kakaocup.compose.node.element.ComposeScreen
class OpenMainScreenScenario(
private val testRule: ComposeTestRule,
private val productType: ProductType? = null,
) : Scenario() {
override val steps: TestContext<Unit>.() -> Unit = {
if (productType != null) {
MockProvider.setMocks(productType)
}
ComposeScreen.onComposeScreen<DisclaimerPageObject>(testRule) {
step("Click on \"Accept\" button") {
acceptButton.clickWithAssertion()
}
}
ComposeScreen.onComposeScreen<StoriesPageObject>(testRule) {
step("Click on \"Scan\" button") {
scanButton.clickWithAssertion()
}
}
ComposeScreen.onComposeScreen<MainScreenPageObject>(testRule) {
step("Make sure wallet screen is visible") {
assertIsDisplayed()
}
}
ComposeScreen.onComposeScreen<MarketsTooltipPageObject>(testRule) {
step("Close Markets tooltip"){
contentContainer.performClick()
}
}
}
}

View file

@ -1,4 +1,4 @@
package com.tangem.steps
package com.tangem.scenarios
import com.tangem.common.BaseTestCase
import com.tangem.screens.onWalletConnectBottomSheet

View file

@ -0,0 +1,32 @@
package com.tangem.screens
import com.kaspersky.kaspresso.screens.KScreen
import com.tangem.wallet.R
import io.github.kakaocup.kakao.text.KTextView
import io.github.kakaocup.kakao.text.KButton
object AlreadyUsedWalletDialogPageObject : KScreen<AlreadyUsedWalletDialogPageObject>() {
override val layoutId: Int? = null
override val viewClass: Class<*>? = null
val title = KTextView {
withText(R.string.security_alert_title)
}
val message = KTextView {
withText(R.string.wallet_been_activated_message)
}
val cancelButton = KButton {
withText(R.string.common_cancel)
}
val requestSupportButton = KButton {
withText(R.string.alert_button_request_support)
}
val thisIsMyWalletButton = KButton {
withText(R.string.this_is_my_wallet_title)
}
}

View file

@ -4,7 +4,7 @@ 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.DialogTestTags
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
@ -14,7 +14,7 @@ class DialogPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<DialogPageObject>(semanticsProvider = semanticsProvider) {
val dialogContainer: KNode = child {
hasTestTag(DialogTestTags.DIALOG_CONTAINER)
hasTestTag(BaseDialogTestTags.CONTAINER)
}
val cancelButton: KNode = child {

View file

@ -0,0 +1,44 @@
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
import com.tangem.common.ui.R as CommonUIR
class FailedTransactionDialogPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<FailedTransactionDialogPageObject>(semanticsProvider = semanticsProvider) {
val dialogContainer: KNode = child {
hasTestTag(BaseDialogTestTags.CONTAINER)
}
val title: KNode = child {
hasTestTag(BaseDialogTestTags.TITLE)
hasText(getResourceString(CommonUIR.string.send_alert_transaction_failed_title))
useUnmergedTree = true
}
val text: KNode = child {
hasTestTag(BaseDialogTestTags.TEXT)
useUnmergedTree = true
}
val cancelButton: KNode = child {
hasTestTag(BaseButtonTestTags.BUTTON)
hasText(getResourceString(R.string.common_cancel))
}
val supportButton: KNode = child {
hasTestTag(BaseButtonTestTags.BUTTON)
hasText(getResourceString(R.string.common_support))
}
}
internal fun BaseTestCase.onFailedTransactionDialog(function: FailedTransactionDialogPageObject.() -> Unit) =
onComposeScreen(composeTestRule, function)

View file

@ -39,7 +39,7 @@ class MainScreenPageObject(semanticsProvider: SemanticsNodeInteractionsProvider)
hasTestTag(MainScreenTestTags.SCREEN_CONTAINER)
}
val synchronizeAddressesButton: KNode = child {
val synchronizeAddressesButton: KNode = lazyList.child {
hasText(getResourceString(R.string.common_generate_addresses))
}

View file

@ -0,0 +1,36 @@
package com.tangem.screens
import com.kaspersky.kaspresso.screens.KScreen
import com.tangem.wallet.R
import io.github.kakaocup.kakao.text.KTextView
import io.github.kakaocup.kakao.text.KButton
object ScanWarningDialogPageObject : KScreen<ScanWarningDialogPageObject>() {
override val layoutId: Int? = null
override val viewClass: Class<*>? = null
val warningTitle = KTextView {
withText(R.string.common_warning)
}
val warningMessage = KTextView {
withText(R.string.alert_troubleshooting_scan_card_title)
}
val tryAgainButton = KButton {
withId(R.id.try_again_button)
}
val howToScanButton = KButton {
withId(R.id.how_to_scan_button)
}
val requestSupportButton = KButton {
withId(R.id.request_support_button)
}
val cancelButton = KButton {
withId(R.id.cancel_button)
}
}

View file

@ -0,0 +1,30 @@
package com.tangem.screens
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
import com.tangem.common.BaseTestCase
import com.tangem.core.ui.test.BaseButtonTestTags
import com.tangem.core.ui.test.SendAddressScreenTestTags
import com.tangem.features.send.v2.impl.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
class SendAddressPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<SendAddressPageObject>(semanticsProvider = semanticsProvider) {
val addressTextField: KNode = child {
hasTestTag(SendAddressScreenTestTags.ADDRESS_TEXT_FIELD)
useUnmergedTree = true
}
val nextButton: KNode = child {
hasTestTag(BaseButtonTestTags.TEXT)
hasText(getResourceString(R.string.common_next))
useUnmergedTree = true
}
}
internal fun BaseTestCase.onSendAddressScreen(function: SendAddressPageObject.() -> Unit) =
onComposeScreen(composeTestRule, function)

View file

@ -0,0 +1,30 @@
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.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 io.github.kakaocup.kakao.common.utilities.getResourceString
class SendConfirmPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<SendConfirmPageObject>(semanticsProvider = semanticsProvider) {
val title: KNode = child {
hasTestTag(TopAppBarTestTags.TITLE)
useUnmergedTree = true
}
val sendButton: KNode = child {
hasTestTag(BaseButtonTestTags.TEXT)
hasText(getResourceString(R.string.common_send))
useUnmergedTree = true
}
}
internal fun BaseTestCase.onSendConfirmScreen(function: SendConfirmPageObject.() -> Unit) =
onComposeScreen(composeTestRule, function)

View file

@ -3,7 +3,7 @@ package com.tangem.screens
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
import com.tangem.common.BaseTestCase
import com.tangem.core.ui.test.BaseButtonTestTags
import com.tangem.core.ui.test.StakingSendScreenTestTags
import com.tangem.core.ui.test.SendScreenTestTags
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
@ -12,11 +12,11 @@ import io.github.kakaocup.kakao.common.utilities.getResourceString
import com.tangem.features.send.v2.impl.R as SendR
import androidx.compose.ui.test.hasTestTag as withTestTag
class StakingSendPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<StakingSendPageObject>(semanticsProvider = semanticsProvider) {
class SendPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<SendPageObject>(semanticsProvider = semanticsProvider) {
val screenContainer: KNode = child {
hasTestTag(StakingSendScreenTestTags.SCREEN_CONTAINER)
hasTestTag(SendScreenTestTags.SCREEN_CONTAINER)
}
val title: KNode = child {
@ -25,44 +25,44 @@ class StakingSendPageObject(semanticsProvider: SemanticsNodeInteractionsProvider
}
val amountContainerTitle: KNode = child {
hasTestTag(StakingSendScreenTestTags.AMOUNT_CONTAINER_TITLE)
hasTestTag(SendScreenTestTags.AMOUNT_CONTAINER_TITLE)
useUnmergedTree = true
}
val amountContainerText: KNode = child {
hasTestTag(StakingSendScreenTestTags.AMOUNT_CONTAINER_TEXT)
hasTestTag(SendScreenTestTags.AMOUNT_CONTAINER_TEXT)
useUnmergedTree = true
}
val amountInputTextField: KNode = child {
hasTestTag(StakingSendScreenTestTags.INPUT_TEXT_FIELD)
hasTestTag(SendScreenTestTags.INPUT_TEXT_FIELD)
useUnmergedTree = true
}
val secondaryAmount: KNode = child {
hasTestTag(StakingSendScreenTestTags.SECONDARY_AMOUNT)
hasTestTag(SendScreenTestTags.SECONDARY_AMOUNT)
useUnmergedTree = true
}
val currencyButton: KNode = child {
hasTestTag(StakingSendScreenTestTags.CURRENCY_BUTTON)
hasAnyChild(withTestTag(StakingSendScreenTestTags.CURRENCY_ICON))
hasTestTag(SendScreenTestTags.CURRENCY_BUTTON)
hasAnyChild(withTestTag(SendScreenTestTags.CURRENCY_ICON))
useUnmergedTree = true
}
val fiatButton: KNode = child {
hasTestTag(StakingSendScreenTestTags.CURRENCY_BUTTON)
hasAnyChild(withTestTag(StakingSendScreenTestTags.FIAT_ICON))
hasTestTag(SendScreenTestTags.CURRENCY_BUTTON)
hasAnyChild(withTestTag(SendScreenTestTags.FIAT_ICON))
useUnmergedTree = true
}
val maxButton: KNode = child {
hasTestTag(StakingSendScreenTestTags.MAX_BUTTON)
hasTestTag(SendScreenTestTags.MAX_BUTTON)
useUnmergedTree = true
}
val previousButton: KNode = child {
hasTestTag(StakingSendScreenTestTags.PREVIOUS_BUTTON)
hasTestTag(SendScreenTestTags.PREVIOUS_BUTTON)
useUnmergedTree = true
}
@ -74,5 +74,5 @@ class StakingSendPageObject(semanticsProvider: SemanticsNodeInteractionsProvider
}
internal fun BaseTestCase.onStakingSendScreen(function: StakingSendPageObject.() -> Unit) =
internal fun BaseTestCase.onSendScreen(function: SendPageObject.() -> 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.R
import com.tangem.core.ui.test.BaseAmountBlockTestTags
import com.tangem.core.ui.test.BaseButtonTestTags
import com.tangem.core.ui.test.StakingSendDetailsScreenTestTags
import com.tangem.core.ui.test.TopAppBarTestTags
@ -11,8 +12,8 @@ import io.github.kakaocup.compose.node.element.ComposeScreen.Companion.onCompose
import io.github.kakaocup.compose.node.element.KNode
import io.github.kakaocup.kakao.common.utilities.getResourceString
class StakingSendDetailsPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<StakingSendDetailsPageObject>(semanticsProvider = semanticsProvider) {
class StakingConfirmPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<StakingConfirmPageObject>(semanticsProvider = semanticsProvider) {
val title: KNode = child {
hasTestTag(TopAppBarTestTags.TITLE)
@ -20,12 +21,12 @@ class StakingSendDetailsPageObject(semanticsProvider: SemanticsNodeInteractionsP
}
val primaryAmount: KNode = child {
hasTestTag(StakingSendDetailsScreenTestTags.PRIMARY_AMOUNT)
hasTestTag(BaseAmountBlockTestTags.PRIMARY_AMOUNT)
useUnmergedTree = true
}
val secondaryAmount: KNode = child {
hasTestTag(StakingSendDetailsScreenTestTags.SECONDARY_AMOUNT)
hasTestTag(BaseAmountBlockTestTags.SECONDARY_AMOUNT)
useUnmergedTree = true
}
@ -47,5 +48,5 @@ class StakingSendDetailsPageObject(semanticsProvider: SemanticsNodeInteractionsP
}
internal fun BaseTestCase.onStakingSendDetailsScreen(function: StakingSendDetailsPageObject.() -> Unit) =
internal fun BaseTestCase.onStakingConfirmScreen(function: StakingConfirmPageObject.() -> Unit) =
onComposeScreen(composeTestRule, function)

View file

@ -111,6 +111,12 @@ class TokenDetailsPageObject(semanticsProvider: SemanticsNodeInteractionsProvide
hasText(getResourceString(R.string.common_buy))
}
@OptIn(ExperimentalTestApi::class)
val sendButton: LazyListItemNode = horizontalActionChips.childWith<LazyListItemNode> {
hasTestTag(TokenDetailsScreenTestTags.ACTION_BUTTON)
hasText(getResourceString(R.string.common_send))
}
}
internal fun BaseTestCase.onTokenDetailsScreen(function: TokenDetailsPageObject.() -> Unit) =

View file

@ -1,15 +0,0 @@
package com.tangem.steps
import android.content.Intent
import android.net.Uri
import androidx.test.core.app.ApplicationProvider
fun openAppByDeepLink(deepLinkUri: String?) {
val deeplinkScheme = "tangem://wc?uri="
val context = ApplicationProvider.getApplicationContext<android.content.Context>()
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(deeplinkScheme + deepLinkUri)).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
context.startActivity(intent)
}

View file

@ -6,8 +6,9 @@ import com.tangem.common.constants.TestConstants.WAIT_UNTIL_TIMEOUT
import com.tangem.common.extensions.clickWithAssertion
import com.tangem.common.utils.resetWireMockScenarioState
import com.tangem.common.utils.setWireMockScenarioState
import com.tangem.scenarios.OpenMainScreenScenario
import com.tangem.screens.*
import com.tangem.scenarios.openMainScreen
import com.tangem.scenarios.synchronizeAddresses
import dagger.hilt.android.testing.HiltAndroidTest
import io.qameta.allure.kotlin.AllureId
import io.qameta.allure.kotlin.junit4.DisplayName
@ -36,13 +37,10 @@ class BuyTokenTest : BaseTestCase() {
setWireMockScenarioState(scenarioName, "Error")
}
step("Open 'Main Screen'") {
scenario(OpenMainScreenScenario(composeTestRule))
openMainScreen()
}
step("Click on 'Synchronize addresses' button") {
onMainScreen { synchronizeAddressesButton.clickWithAssertion() }
}
step("Assert wallet balance = $balance") {
onMainScreen { walletBalance().assertTextContains(balance) }
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Click on 'Buy' button") {
onMainScreen { buyButton.clickWithAssertion() }
@ -84,13 +82,10 @@ class BuyTokenTest : BaseTestCase() {
}
step("Open 'Main Screen'") {
scenario(OpenMainScreenScenario(composeTestRule))
openMainScreen()
}
step("Click on 'Synchronize addresses' button") {
onMainScreen { synchronizeAddressesButton.clickWithAssertion() }
}
step("Assert wallet balance = '$balance'") {
onMainScreen { walletBalance().assertTextContains(balance) }
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Click on 'Buy' button") {
onMainScreen { buyButton.clickWithAssertion() }
@ -175,13 +170,10 @@ class BuyTokenTest : BaseTestCase() {
}
step("Open 'Main Screen'") {
scenario(OpenMainScreenScenario(composeTestRule))
openMainScreen()
}
step("Click on 'Synchronize addresses' button") {
onMainScreen { synchronizeAddressesButton.clickWithAssertion() }
}
step("Assert wallet balance = '$balance'") {
onMainScreen { walletBalance().assertTextContains(balance) }
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Click on 'Buy' button") {
onMainScreen { buyButton.clickWithAssertion() }
@ -250,13 +242,10 @@ class BuyTokenTest : BaseTestCase() {
}
step("Open 'Main Screen'") {
scenario(OpenMainScreenScenario(composeTestRule))
openMainScreen()
}
step("Click on 'Synchronize addresses' button") {
onMainScreen { synchronizeAddressesButton.clickWithAssertion() }
}
step("Assert wallet balance = '$balance'") {
onMainScreen { walletBalance().assertTextContains(balance) }
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Click on 'Buy' button") {
onMainScreen { buyButton.clickWithAssertion() }
@ -339,13 +328,10 @@ class BuyTokenTest : BaseTestCase() {
}
step("Open 'Main Screen'") {
scenario(OpenMainScreenScenario(composeTestRule))
openMainScreen()
}
step("Click on 'Synchronize addresses' button") {
onMainScreen { synchronizeAddressesButton.clickWithAssertion() }
}
step("Assert wallet balance = '$balance'") {
onMainScreen { walletBalance().assertTextContains(balance) }
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Click on 'Buy' button") {
onMainScreen { buyButton.clickWithAssertion() }
@ -437,13 +423,10 @@ class BuyTokenTest : BaseTestCase() {
}
step("Open 'Main Screen'") {
scenario(OpenMainScreenScenario(composeTestRule))
openMainScreen()
}
step("Click on 'Synchronize addresses' button") {
onMainScreen { synchronizeAddressesButton.clickWithAssertion() }
}
step("Assert wallet balance = '$balance'") {
onMainScreen { walletBalance().assertTextContains(balance) }
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Click on 'Buy' button") {
onMainScreen { buyButton.clickWithAssertion() }

View file

@ -3,7 +3,7 @@ package com.tangem.tests
import com.tangem.common.BaseTestCase
import com.tangem.common.extensions.clickWithAssertion
import com.tangem.domain.models.scan.ProductType
import com.tangem.scenarios.OpenMainScreenScenario
import com.tangem.scenarios.openMainScreen
import com.tangem.screens.onDetailsScreen
import com.tangem.screens.onReferralProgramScreen
import com.tangem.screens.onTopBar
@ -19,7 +19,9 @@ class DetailsTest : BaseTestCase() {
@Test
fun walletWithoutBackupDetailsTest() =
setupHooks().run {
scenario(OpenMainScreenScenario(composeTestRule))
step("Open 'Main Screen'") {
openMainScreen()
}
onTopBar {
step("Open wallet details") {
moreButton.clickWithAssertion()
@ -67,7 +69,9 @@ class DetailsTest : BaseTestCase() {
// @Test
fun wallet2DetailsTest() =
setupHooks().run {
scenario(OpenMainScreenScenario(composeTestRule, ProductType.Wallet2))
step("Open 'Main Screen'") {
openMainScreen(productType = ProductType.Wallet2, alreadyActivatedDialogIsShown = true)
}
onTopBar {
step("Open wallet details") {
moreButton.clickWithAssertion()
@ -115,7 +119,9 @@ class DetailsTest : BaseTestCase() {
@Test
fun noteDetailsTest() =
setupHooks().run {
scenario(OpenMainScreenScenario(composeTestRule, ProductType.Note))
step("Open 'Main Screen'") {
openMainScreen(ProductType.Note)
}
onTopBar {
step("Open wallet details") {
moreButton.clickWithAssertion()
@ -162,7 +168,9 @@ class DetailsTest : BaseTestCase() {
@Test
fun validateReferralProgramScreenTest() =
setupHooks().run {
scenario(OpenMainScreenScenario(composeTestRule))
step("Open 'Main Screen'") {
openMainScreen()
}
step("Open wallet details") {
onTopBar { moreButton.clickWithAssertion() }
}

View file

@ -0,0 +1,176 @@
package com.tangem.tests
import androidx.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiThread
import com.tangem.common.BaseTestCase
import com.tangem.common.constants.TestConstants.RECIPIENT_ADDRESS
import com.tangem.common.constants.TestConstants.TOTAL_BALANCE
import com.tangem.common.core.TangemSdkError
import com.tangem.common.extensions.clickWithAssertion
import com.tangem.domain.models.scan.ProductType
import com.tangem.domain.redux.StateDialog
import com.tangem.scenarios.*
import com.tangem.screens.*
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.domain.sdk.mocks.MockProvider
import com.tangem.tap.store
import dagger.hilt.android.testing.HiltAndroidTest
import io.qameta.allure.kotlin.Allure
import io.qameta.allure.kotlin.AllureId
import io.qameta.allure.kotlin.junit4.DisplayName
import org.junit.Ignore
import org.junit.Test
@HiltAndroidTest
class FeedbackTest : BaseTestCase() {
@AllureId("894")
@DisplayName("Send feedback: from details")
@Test
fun sendFeedbackFromDetailsTest() {
setupHooks(
additionalAfterSection = {
device.uiDevice.pressBack()
}
).run {
step("Open 'Main Screen'") {
openMainScreen()
}
step("Click 'More' button on TopBar") {
onTopBar { moreButton.clickWithAssertion() }
}
step("Click 'Contact support' button") {
onDetailsScreen { contactSupportButton.clickWithAssertion() }
}
step("Check 'Contact support' intent is called") {
checkSendEMailIntentCalled()
}
}
}
@AllureId("893")
@DisplayName("Send feedback: failed transaction")
@Test
fun sendFeedbackFromFailedTransactionTest() {
val balance = TOTAL_BALANCE
val tokenName = "Polygon"
val recipientAddress = RECIPIENT_ADDRESS
val sendAmount = "1"
setupHooks(
additionalAfterSection = {
device.uiDevice.pressBack()
}
).run {
step("Open 'Main Screen'") {
openMainScreen()
}
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Click on token with name: '$tokenName'") {
onMainScreen { tokenWithTitleAndAddress(tokenName).clickWithAssertion() }
}
step("Click 'Send' button") {
onTokenDetailsScreen { sendButton.performClick() }
}
step("Type '$sendAmount' in input text field") {
onSendScreen {
amountInputTextField.performClick()
amountInputTextField.performTextReplacement(sendAmount)
}
}
step("Assert input text field has value: '$sendAmount'") {
onSendScreen { amountInputTextField.assertTextContains(value = sendAmount, substring = true) }
}
step("Click 'Next' button") {
onSendScreen { nextButton.clickWithAssertion() }
}
step("Enter address") {
onSendAddressScreen { addressTextField.performTextReplacement(recipientAddress) }
}
step("Click 'Next' button") {
onSendAddressScreen { nextButton.clickWithAssertion() }
}
step("Click 'Send' button") {
onSendConfirmScreen { sendButton.clickWithAssertion() }
}
step("Check 'Failed transaction' dialog") {
checkFailedTransactionDialog()
}
step("Click on 'Support' button") {
onFailedTransactionDialog { supportButton.performClick() }
}
step("Check 'Contact support' intent is called") {
checkSendEMailIntentCalled()
}
}
}
@AllureId("3985")
@DisplayName("Send feedback: from 'Warning' dialog after card scan")
@Test
fun sendFeedbackFromScanScreenTest() {
setupHooks(
additionalAfterSection = {
device.uiDevice.pressBack()
MockProvider.resetEmulateError()
}
).run {
Allure.step("Click on 'Accept' button") {
onDisclaimerScreen { acceptButton.clickWithAssertion() }
}
step("Set scanning error") {
MockProvider.setEmulateError(TangemSdkError.TagLost())
}
step("Click on 'Scan' button") {
onStoriesScreen { scanButton.performClick() }
}
step("Force show 'Scan warning' dialog"){
runOnUiThread {
val scanFailsState = StateDialog.ScanFailsDialog(source = StateDialog.ScanFailsSource.MAIN)
store.dispatch(GlobalAction.ShowDialog(scanFailsState))
}
}
step("Check 'Scan warning' dialog") {
checkScanWarningDialog()
}
step("Click on 'Request support' button") {
ScanWarningDialogPageObject { requestSupportButton.click() }
}
step("Check 'Contact support' intent is called") {
checkSendEMailIntentCalled()
}
}
}
@AllureId("3986")
@DisplayName("Send feedback: from scan already used wallet alert dialog")
@Ignore("TODO On CI Already used wallet doesn't displayed")
@Test
fun sendFeedbackAfterScanAlreadyUsedWalletTest() {
setupHooks(
additionalAfterSection = {
device.uiDevice.pressBack()
}
).run {
step("Set mocks for Wallet2") {
MockProvider.setMocks(ProductType.Wallet2)
}
step("Click on 'Accept' button") {
onDisclaimerScreen { acceptButton.clickWithAssertion() }
}
step("Click on 'Scan' button") {
onStoriesScreen { scanButton.clickWithAssertion() }
}
step("Check 'Already used Wallet' dialog") {
checkAlreadyUsedWalletDialog()
}
step("Click on 'Request support' button") {
AlreadyUsedWalletDialogPageObject { requestSupportButton.click() }
}
step("Check 'Contact support' intent is called") {
checkSendEMailIntentCalled()
}
}
}
}

View file

@ -3,8 +3,9 @@ package com.tangem.tests
import com.tangem.common.BaseTestCase
import com.tangem.common.constants.TestConstants.TOTAL_BALANCE
import com.tangem.common.extensions.clickWithAssertion
import com.tangem.scenarios.OpenMainScreenScenario
import com.tangem.screens.*
import com.tangem.scenarios.openMainScreen
import com.tangem.scenarios.synchronizeAddresses
import dagger.hilt.android.testing.HiltAndroidTest
import io.qameta.allure.kotlin.AllureId
import io.qameta.allure.kotlin.junit4.DisplayName
@ -21,13 +22,10 @@ class HideTokenTest : BaseTestCase() {
val balance = TOTAL_BALANCE
setupHooks().run {
step("Open 'Main Screen'") {
scenario(OpenMainScreenScenario(composeTestRule))
openMainScreen()
}
step("Click on 'Synchronize addresses' button" ) {
onMainScreen { synchronizeAddressesButton.clickWithAssertion() }
}
step("Assert wallet balance = $balance") {
onMainScreen { walletBalance().assertTextContains(balance) }
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Click on token with name: '$tokenTitle'") {
onMainScreen { tokenWithTitleAndAddress(tokenTitle).clickWithAssertion() }

View file

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

View file

@ -5,9 +5,10 @@ import com.tangem.common.BaseTestCase
import com.tangem.common.constants.TestConstants.TOTAL_BALANCE
import com.tangem.common.extensions.clickWithAssertion
import com.tangem.common.extensions.swipeUp
import com.tangem.scenarios.OpenMainScreenScenario
import com.tangem.screens.onMainScreen
import com.tangem.screens.onOrganizeTokensScreen
import com.tangem.scenarios.openMainScreen
import com.tangem.scenarios.synchronizeAddresses
import dagger.hilt.android.testing.HiltAndroidTest
import io.qameta.allure.kotlin.AllureId
import io.qameta.allure.kotlin.junit4.DisplayName
@ -23,8 +24,9 @@ class OrganizeTokensTest : BaseTestCase() {
setupHooks().run {
val tokenTitle = "Ethereum"
val tokenNetwork = "Ethereum network"
step("Open 'Main Screen'") {
scenario(OpenMainScreenScenario(composeTestRule))
openMainScreen()
}
step("Click on 'Synchronize addresses' button" ) {
onMainScreen { synchronizeAddressesButton.clickWithAssertion() }
@ -90,14 +92,12 @@ class OrganizeTokensTest : BaseTestCase() {
val ethereumTitle = "Ethereum"
val bitcoinTitle = "Bitcoin"
val balance = TOTAL_BALANCE
step("Open 'Main Screen'") {
scenario(OpenMainScreenScenario(composeTestRule))
openMainScreen()
}
step("Click on 'Synchronize addresses' button" ) {
onMainScreen { synchronizeAddressesButton.clickWithAssertion() }
}
step("Assert wallet balance = '$balance'") {
onMainScreen { walletBalance().assertTextContains(balance) }
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Check positions of tokens on 'Main Screen'") {
onMainScreen {
@ -129,8 +129,9 @@ class OrganizeTokensTest : BaseTestCase() {
setupHooks().run {
val ethereumTitle = "Ethereum"
val bitcoinTitle = "Bitcoin"
step("Open 'Main Screen'") {
scenario(OpenMainScreenScenario(composeTestRule))
openMainScreen()
}
step("Click on 'Synchronize addresses' button" ) {
onMainScreen { synchronizeAddressesButton.clickWithAssertion() }
@ -178,14 +179,12 @@ class OrganizeTokensTest : BaseTestCase() {
val polygonTitle = "Polygon"
val polExMaticTitle = "POL (ex-MATIC)"
val balance = TOTAL_BALANCE
step("Open 'Main Screen'") {
scenario(OpenMainScreenScenario(composeTestRule))
openMainScreen()
}
step("Click on 'Synchronize addresses' button" ) {
onMainScreen { synchronizeAddressesButton.clickWithAssertion() }
}
step("Assert wallet balance = '$balance'") {
onMainScreen { walletBalance().assertTextContains(balance) }
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Check positions of tokens on 'Main Screen'") {
onMainScreen {

View file

@ -5,8 +5,9 @@ import com.tangem.common.constants.TestConstants.TOTAL_BALANCE
import com.tangem.common.extensions.clickWithAssertion
import com.tangem.common.utils.resetWireMockScenarioState
import com.tangem.common.utils.setWireMockScenarioState
import com.tangem.scenarios.OpenMainScreenScenario
import com.tangem.screens.*
import com.tangem.scenarios.openMainScreen
import com.tangem.scenarios.synchronizeAddresses
import dagger.hilt.android.testing.HiltAndroidTest
import io.qameta.allure.kotlin.AllureId
import io.qameta.allure.kotlin.junit4.DisplayName
@ -20,7 +21,7 @@ class StakingTest : BaseTestCase() {
@Test
fun validateStakingBlockTest() {
val tokenTitle = "POL (ex-MATIC)"
val balance = TOTAL_BALANCE
val balance = "$3,299.37"
val scenarioName = "staking_eth_pol_balances_android"
val scenarioState = "Staked"
@ -35,13 +36,13 @@ class StakingTest : BaseTestCase() {
}
step("Open 'Main Screen'") {
scenario(OpenMainScreenScenario(composeTestRule))
openMainScreen()
}
step("Click on 'Synchronize addresses' button") {
onMainScreen { synchronizeAddressesButton.clickWithAssertion() }
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Assert wallet balance = $balance") {
onMainScreen { walletBalance().assertTextContains(balance) }
step("Assert 'Organize tokens' button is displayed") {
onMainScreen { organizeTokensButton().assertIsDisplayed() }
}
step("Click on token with name: '$tokenTitle'") {
onMainScreen { tokenWithTitleAndAddress(tokenTitle).clickWithAssertion() }
@ -75,7 +76,7 @@ class StakingTest : BaseTestCase() {
@Test
fun validateStakingMoreScreensTest() {
val tokenTitle = "POL (ex-MATIC)"
val balance = TOTAL_BALANCE
val balance = "$3,299.37"
val scenarioName = "staking_eth_pol_balances_android"
val scenarioState = "Staked"
val stakingAmount = "1"
@ -91,13 +92,13 @@ class StakingTest : BaseTestCase() {
}
step("Open 'Main Screen'") {
scenario(OpenMainScreenScenario(composeTestRule))
openMainScreen()
}
step("Click on 'Synchronize addresses' button") {
onMainScreen { synchronizeAddressesButton.clickWithAssertion() }
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Assert wallet balance = $balance") {
onMainScreen { walletBalance().assertTextContains(balance) }
step("Assert 'Organize tokens' button is displayed") {
onMainScreen { organizeTokensButton().assertIsDisplayed() }
}
step("Click on token with name: '$tokenTitle'") {
onMainScreen { tokenWithTitleAndAddress(tokenTitle).clickWithAssertion() }
@ -151,73 +152,73 @@ class StakingTest : BaseTestCase() {
onStakingDetailsScreen { stakeMoreButton.performClick() }
}
step("Assert 'Send' screen is displayed") {
onStakingSendScreen { screenContainer.assertIsDisplayed() }
onSendScreen { screenContainer.assertIsDisplayed() }
}
step("Assert 'Send' screen title is displayed") {
onStakingSendScreen { title.assertIsDisplayed() }
onSendScreen { title.assertIsDisplayed() }
}
step("Assert amount container title is displayed") {
onStakingSendScreen { amountContainerTitle.assertIsDisplayed() }
onSendScreen { amountContainerTitle.assertIsDisplayed() }
}
step("Assert amount container text is displayed") {
onStakingSendScreen { amountContainerText.assertIsDisplayed() }
onSendScreen { amountContainerText.assertIsDisplayed() }
}
step("Assert input text field is displayed") {
onStakingSendScreen { amountInputTextField.assertIsDisplayed() }
onSendScreen { amountInputTextField.assertIsDisplayed() }
}
step("Assert secondary amount is displayed") {
onStakingSendScreen { secondaryAmount.assertIsDisplayed() }
onSendScreen { secondaryAmount.assertIsDisplayed() }
}
step("Type '$stakingAmount' in input text field") {
onStakingSendScreen {
onSendScreen {
amountInputTextField.performClick()
amountInputTextField.performTextReplacement(stakingAmount)
}
}
step("Assert input text field has value: '$stakingAmount'") {
onStakingSendScreen { amountInputTextField.assertTextContains(value = stakingAmount, substring = true) }
onSendScreen { amountInputTextField.assertTextContains(value = stakingAmount, substring = true) }
}
step("Assert currency button is displayed") {
onStakingSendScreen { currencyButton.assertIsDisplayed() }
onSendScreen { currencyButton.assertIsDisplayed() }
}
step("Assert fiat button is displayed") {
onStakingSendScreen { fiatButton.assertIsDisplayed() }
onSendScreen { fiatButton.assertIsDisplayed() }
}
step("Assert currency button is displayed") {
onStakingSendScreen { currencyButton.assertIsDisplayed() }
onSendScreen { currencyButton.assertIsDisplayed() }
}
step("Assert fiat button is displayed") {
onStakingSendScreen { fiatButton.assertIsDisplayed() }
onSendScreen { fiatButton.assertIsDisplayed() }
}
step("Assert 'Max' button is displayed") {
onStakingSendScreen { maxButton.assertIsDisplayed() }
onSendScreen { maxButton.assertIsDisplayed() }
}
step("Assert previous button is displayed") {
onStakingSendScreen { previousButton.assertIsDisplayed() }
onSendScreen { previousButton.assertIsDisplayed() }
}
step("Assert 'Next' button is displayed") {
onStakingSendScreen { nextButton.assertIsDisplayed() }
onSendScreen { nextButton.assertIsDisplayed() }
}
step("Click on 'Next' button") {
onStakingSendScreen { nextButton.performClick() }
onSendScreen { nextButton.performClick() }
}
step("Assert 'Send details' screen title is displayed") {
onStakingSendDetailsScreen { title.assertIsDisplayed() }
onStakingConfirmScreen { title.assertIsDisplayed() }
}
step("Assert primary amount is displayed") {
onStakingSendDetailsScreen { primaryAmount.assertIsDisplayed() }
onStakingConfirmScreen { primaryAmount.assertIsDisplayed() }
}
step("Assert secondary amount is displayed") {
onStakingSendDetailsScreen { secondaryAmount.assertIsDisplayed() }
onStakingConfirmScreen { secondaryAmount.assertIsDisplayed() }
}
step("Assert 'Validator' block is displayed") {
onStakingSendDetailsScreen { validatorBlock.assertIsDisplayed() }
onStakingConfirmScreen { validatorBlock.assertIsDisplayed() }
}
step("Assert 'Network Fee' block is displayed") {
onStakingSendDetailsScreen { networkFeeBlock.assertIsDisplayed() }
onStakingConfirmScreen { networkFeeBlock.assertIsDisplayed() }
}
step("Assert 'Stake' button is displayed") {
onStakingSendDetailsScreen { stakeButton.assertIsDisplayed() }
onStakingConfirmScreen { stakeButton.assertIsDisplayed() }
}
}
}
@ -243,13 +244,13 @@ class StakingTest : BaseTestCase() {
}
step("Open 'Main Screen'") {
scenario(OpenMainScreenScenario(composeTestRule))
openMainScreen()
}
step("Click on 'Synchronize addresses' button") {
onMainScreen { synchronizeAddressesButton.clickWithAssertion() }
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Assert wallet balance = $balance") {
onMainScreen { walletBalance().assertTextContains(balance) }
step("Assert 'Organize tokens' button is displayed") {
onMainScreen { organizeTokensButton().assertIsDisplayed() }
}
step("Click on token with name: '$tokenTitle'") {
onMainScreen { tokenWithTitleAndAddress(tokenTitle).clickWithAssertion() }
@ -306,73 +307,73 @@ class StakingTest : BaseTestCase() {
onStakingDetailsScreen { stakeButton.performClick() }
}
step("Assert 'Send' screen is displayed") {
onStakingSendScreen { screenContainer.assertIsDisplayed() }
onSendScreen { screenContainer.assertIsDisplayed() }
}
step("Assert 'Send' screen title is displayed") {
onStakingSendScreen { title.assertIsDisplayed() }
onSendScreen { title.assertIsDisplayed() }
}
step("Assert amount container title is displayed") {
onStakingSendScreen { amountContainerTitle.assertIsDisplayed() }
onSendScreen { amountContainerTitle.assertIsDisplayed() }
}
step("Assert amount container text is displayed") {
onStakingSendScreen { amountContainerText.assertIsDisplayed() }
onSendScreen { amountContainerText.assertIsDisplayed() }
}
step("Assert input text field is displayed") {
onStakingSendScreen { amountInputTextField.assertIsDisplayed() }
onSendScreen { amountInputTextField.assertIsDisplayed() }
}
step("Assert secondary amount is displayed") {
onStakingSendScreen { secondaryAmount.assertIsDisplayed() }
onSendScreen { secondaryAmount.assertIsDisplayed() }
}
step("Type '$stakingAmount' in input text field") {
onStakingSendScreen {
onSendScreen {
amountInputTextField.performClick()
amountInputTextField.performTextReplacement(stakingAmount)
}
}
step("Assert input text field has value: '$stakingAmount'") {
onStakingSendScreen { amountInputTextField.assertTextContains(value = stakingAmount, substring = true) }
onSendScreen { amountInputTextField.assertTextContains(value = stakingAmount, substring = true) }
}
step("Assert currency button is displayed") {
onStakingSendScreen { currencyButton.assertIsDisplayed() }
onSendScreen { currencyButton.assertIsDisplayed() }
}
step("Assert fiat button is displayed") {
onStakingSendScreen { fiatButton.assertIsDisplayed() }
onSendScreen { fiatButton.assertIsDisplayed() }
}
step("Assert currency button is displayed") {
onStakingSendScreen { currencyButton.assertIsDisplayed() }
onSendScreen { currencyButton.assertIsDisplayed() }
}
step("Assert fiat button is displayed") {
onStakingSendScreen { fiatButton.assertIsDisplayed() }
onSendScreen { fiatButton.assertIsDisplayed() }
}
step("Assert 'Max' button is displayed") {
onStakingSendScreen { maxButton.assertIsDisplayed() }
onSendScreen { maxButton.assertIsDisplayed() }
}
step("Assert previous button is displayed") {
onStakingSendScreen { previousButton.assertIsDisplayed() }
onSendScreen { previousButton.assertIsDisplayed() }
}
step("Assert 'Next' button is displayed") {
onStakingSendScreen { nextButton.assertIsDisplayed() }
onSendScreen { nextButton.assertIsDisplayed() }
}
step("Click on 'Next' button") {
onStakingSendScreen { nextButton.performClick() }
onSendScreen { nextButton.performClick() }
}
step("Assert 'Send details' screen title is displayed") {
onStakingSendDetailsScreen { title.assertIsDisplayed() }
onStakingConfirmScreen { title.assertIsDisplayed() }
}
step("Assert primary amount is displayed") {
onStakingSendDetailsScreen { primaryAmount.assertIsDisplayed() }
onStakingConfirmScreen { primaryAmount.assertIsDisplayed() }
}
step("Assert secondary amount is displayed") {
onStakingSendDetailsScreen { secondaryAmount.assertIsDisplayed() }
onStakingConfirmScreen { secondaryAmount.assertIsDisplayed() }
}
step("Assert 'Validator' block is displayed") {
onStakingSendDetailsScreen { validatorBlock.assertIsDisplayed() }
onStakingConfirmScreen { validatorBlock.assertIsDisplayed() }
}
step("Assert 'Network Fee' block is displayed") {
onStakingSendDetailsScreen { networkFeeBlock.assertIsDisplayed() }
onStakingConfirmScreen { networkFeeBlock.assertIsDisplayed() }
}
step("Assert 'Stake' button is displayed") {
onStakingSendDetailsScreen { stakeButton.assertIsDisplayed() }
onStakingConfirmScreen { stakeButton.assertIsDisplayed() }
}
}
}

View file

@ -9,8 +9,9 @@ import com.tangem.common.constants.TestConstants.WAIT_UNTIL_TIMEOUT
import com.tangem.common.extensions.clickWithAssertion
import com.tangem.datasource.api.common.config.ApiConfig
import com.tangem.datasource.api.common.config.ApiEnvironment
import com.tangem.scenarios.OpenMainScreenScenario
import com.tangem.screens.*
import com.tangem.scenarios.openMainScreen
import com.tangem.scenarios.synchronizeAddresses
import dagger.hilt.android.testing.HiltAndroidTest
import io.qameta.allure.kotlin.AllureId
import io.qameta.allure.kotlin.junit4.DisplayName
@ -32,13 +33,10 @@ class SwapTokenTest : BaseTestCase() {
val balance = TOTAL_BALANCE
step("Open 'Main Screen'") {
scenario(OpenMainScreenScenario(composeTestRule))
openMainScreen()
}
step("Click on 'Synchronize addresses' button") {
onMainScreen { synchronizeAddressesButton.clickWithAssertion() }
}
step("Assert wallet balance = $balance") {
onMainScreen { walletBalance().assertTextContains(balance) }
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Click on token with name: '$tokenTitle'") {
onMainScreen { tokenWithTitleAndAddress(tokenTitle).clickWithAssertion() }
@ -111,13 +109,10 @@ class SwapTokenTest : BaseTestCase() {
val balance = TOTAL_BALANCE
step("Open 'Main Screen'") {
scenario(OpenMainScreenScenario(composeTestRule))
openMainScreen()
}
step("Click on 'Synchronize addresses' button") {
onMainScreen { synchronizeAddressesButton.clickWithAssertion() }
}
step("Assert wallet balance = $balance") {
onMainScreen { walletBalance().assertTextContains(balance) }
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Click on token with name: '$tokenTitle'") {
onMainScreen { tokenWithTitleAndAddress(tokenTitle).clickWithAssertion() }
@ -149,7 +144,7 @@ class SwapTokenTest : BaseTestCase() {
@ApiEnv(
ApiEnvConfig(ApiConfig.ID.Express, ApiEnvironment.PROD)
)
@AllureId("3546")
@AllureId("3547")
@DisplayName("Swap: change network fee")
@Test
fun changeNetworkFeeTest() {
@ -159,13 +154,10 @@ class SwapTokenTest : BaseTestCase() {
val balance = TOTAL_BALANCE
step("Open 'Main Screen'") {
scenario(OpenMainScreenScenario(composeTestRule))
openMainScreen()
}
step("Click on 'Synchronize addresses' button") {
onMainScreen { synchronizeAddressesButton.clickWithAssertion() }
}
step("Assert wallet balance = $balance") {
onMainScreen { walletBalance().assertTextContains(balance) }
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Click on token with name: '$tokenTitle'") {
onMainScreen { tokenWithTitleAndAddress(tokenTitle).clickWithAssertion() }

View file

@ -5,9 +5,8 @@ import com.tangem.common.constants.TestConstants.TOTAL_BALANCE
import com.tangem.common.extensions.clickWithAssertion
import com.tangem.common.extensions.swipeUp
import com.tangem.common.utils.getWcUri
import com.tangem.scenarios.OpenMainScreenScenario
import com.tangem.screens.*
import com.tangem.steps.*
import com.tangem.scenarios.*
import dagger.hilt.android.testing.HiltAndroidTest
import io.qameta.allure.kotlin.AllureId
import io.qameta.allure.kotlin.junit4.DisplayName
@ -147,7 +146,7 @@ class WalletConnectTest : BaseTestCase() {
openAppByDeepLink(deepLinkUri)
}
step("Open 'Main Screen'") {
scenario(OpenMainScreenScenario(composeTestRule))
openMainScreen()
}
step("Check 'Wallet Connect' bottom sheet") {
checkWalletConnectBottomSheet()

View file

@ -26,7 +26,7 @@ import com.tangem.core.ui.format.bigdecimal.fiat
import com.tangem.core.ui.format.bigdecimal.format
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.test.StakingSendDetailsScreenTestTags
import com.tangem.core.ui.test.BaseAmountBlockTestTags
import java.math.BigDecimal
@Composable
@ -66,7 +66,7 @@ fun AmountBlock(amountState: AmountState, isClickDisabled: Boolean, isEditingDis
modifier = Modifier
.fillMaxWidth()
.padding(top = TangemTheme.dimens.spacing24)
.testTag(StakingSendDetailsScreenTestTags.PRIMARY_AMOUNT),
.testTag(BaseAmountBlockTestTags.PRIMARY_AMOUNT),
)
Text(
text = secondAmount,
@ -76,7 +76,7 @@ fun AmountBlock(amountState: AmountState, isClickDisabled: Boolean, isEditingDis
modifier = Modifier
.fillMaxWidth()
.padding(top = TangemTheme.dimens.spacing8)
.testTag(StakingSendDetailsScreenTestTags.SECONDARY_AMOUNT),
.testTag(BaseAmountBlockTestTags.SECONDARY_AMOUNT),
)
}
}

View file

@ -23,7 +23,7 @@ import com.tangem.core.ui.components.currency.icon.CurrencyIcon
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.test.StakingSendScreenTestTags
import com.tangem.core.ui.test.SendScreenTestTags
import kotlinx.collections.immutable.PersistentList
private const val AMOUNT_BUTTONS_KEY = "amountButtonsKey"
@ -80,7 +80,7 @@ internal fun LazyListScope.buttons(
vertical = TangemTheme.dimens.spacing10,
horizontal = TangemTheme.dimens.spacing34,
)
.testTag(StakingSendScreenTestTags.MAX_BUTTON),
.testTag(SendScreenTestTags.MAX_BUTTON),
)
}
}
@ -94,7 +94,7 @@ private fun AmountCurrencyButton(button: AmountSegmentedButtonsConfig, isSegment
.padding(
horizontal = TangemTheme.dimens.spacing10,
)
.testTag(StakingSendScreenTestTags.CURRENCY_BUTTON),
.testTag(SendScreenTestTags.CURRENCY_BUTTON),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
) {
@ -106,13 +106,13 @@ private fun AmountCurrencyButton(button: AmountSegmentedButtonsConfig, isSegment
url = button.iconUrl,
size = TangemTheme.dimens.size18,
isGrayscale = !isSegmentedButtonsEnabled,
modifier = iconModifier.testTag(StakingSendScreenTestTags.FIAT_ICON),
modifier = iconModifier.testTag(SendScreenTestTags.FIAT_ICON),
)
} else if (button.iconState != null) {
CurrencyIcon(
state = button.iconState,
shouldDisplayNetwork = false,
modifier = iconModifier.testTag(StakingSendScreenTestTags.CURRENCY_ICON),
modifier = iconModifier.testTag(SendScreenTestTags.CURRENCY_ICON),
)
}
Text(

View file

@ -29,7 +29,7 @@ import com.tangem.core.ui.format.bigdecimal.crypto
import com.tangem.core.ui.format.bigdecimal.fiat
import com.tangem.core.ui.format.bigdecimal.format
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.test.StakingSendScreenTestTags
import com.tangem.core.ui.test.SendScreenTestTags
import com.tangem.core.ui.utils.rememberDecimalFormat
import kotlinx.coroutines.delay
@ -119,7 +119,7 @@ private fun AmountSecondary(amountField: AmountFieldModel, appCurrencyCode: Stri
modifier = Modifier
.align(TopCenter)
.padding(bottom = TangemTheme.dimens.spacing32)
.testTag(StakingSendScreenTestTags.SECONDARY_AMOUNT),
.testTag(SendScreenTestTags.SECONDARY_AMOUNT),
)
AmountFieldError(
isError = amountField.isError,

View file

@ -29,7 +29,7 @@ import com.tangem.core.ui.extensions.orMaskWithStars
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.test.StakingSendScreenTestTags
import com.tangem.core.ui.test.SendScreenTestTags
private const val AMOUNT_FIELD_KEY = "amountFieldKey"
@ -54,7 +54,7 @@ internal fun LazyListScope.amountField(
color = TangemTheme.colors.text.tertiary,
modifier = Modifier
.padding(top = TangemTheme.dimens.spacing14)
.testTag(StakingSendScreenTestTags.AMOUNT_CONTAINER_TITLE),
.testTag(SendScreenTestTags.AMOUNT_CONTAINER_TITLE),
)
val balance = amountState.availableBalance.orMaskWithStars(isBalanceHidden).resolveReference()
@ -69,7 +69,7 @@ internal fun LazyListScope.amountField(
textAlign = TextAlign.Center,
modifier = Modifier
.padding(top = TangemTheme.dimens.spacing2)
.testTag(StakingSendScreenTestTags.AMOUNT_CONTAINER_TEXT),
.testTag(SendScreenTestTags.AMOUNT_CONTAINER_TEXT),
)
}
CurrencyIcon(

View file

@ -36,7 +36,7 @@ import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.utils.singleEvent
import com.tangem.core.ui.test.StakingSendScreenTestTags
import com.tangem.core.ui.test.SendScreenTestTags
@Composable
fun NavigationButtonsBlock(
@ -149,7 +149,7 @@ private fun PreviousButton(prevButton: NavigationButton?) {
.background(TangemTheme.colors.button.secondary)
.clickable(onClick = button.onClick)
.padding(TangemTheme.dimens.spacing12)
.testTag(StakingSendScreenTestTags.PREVIOUS_BUTTON),
.testTag(SendScreenTestTags.PREVIOUS_BUTTON),
)
}
}

View file

@ -30,7 +30,7 @@ import com.tangem.core.ui.components.fields.SimpleDialogTextField
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.test.DialogTestTags
import com.tangem.core.ui.test.BaseDialogTestTags
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
@ -219,13 +219,14 @@ private fun TangemDialog(
color = TangemTheme.colors.background.primary,
)
.padding(vertical = TangemTheme.dimens.spacing24)
.testTag(DialogTestTags.DIALOG_CONTAINER),
.testTag(BaseDialogTestTags.CONTAINER),
) {
if (title != null) {
Text(
modifier = Modifier
.padding(horizontal = TangemTheme.dimens.spacing24)
.fillMaxWidth(),
.fillMaxWidth()
.testTag(BaseDialogTestTags.TITLE),
text = title,
style = when (type) {
is DialogType.Message -> TangemTheme.typography.h2
@ -262,7 +263,8 @@ private fun DialogContent(type: DialogType, modifier: Modifier = Modifier) {
Text(
modifier = Modifier
.padding(horizontal = TangemTheme.dimens.spacing24)
.fillMaxWidth(),
.fillMaxWidth()
.testTag(BaseDialogTestTags.TEXT),
text = type.message,
style = TangemTheme.typography.body2,
color = TangemTheme.colors.text.secondary,

View file

@ -24,7 +24,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import com.tangem.core.ui.components.fields.visualtransformations.AmountVisualTransformation
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.test.StakingSendScreenTestTags
import com.tangem.core.ui.test.SendScreenTestTags
import com.tangem.core.ui.utils.*
import java.math.BigDecimal
import java.text.DecimalFormat
@ -106,7 +106,7 @@ fun AmountTextField(
visualTransformation = visualTransformation,
modifier = Modifier
.background(backgroundColor)
.testTag(StakingSendScreenTestTags.INPUT_TEXT_FIELD),
.testTag(SendScreenTestTags.INPUT_TEXT_FIELD),
)
}
}

View file

@ -17,6 +17,7 @@ import androidx.compose.ui.Alignment.Companion.CenterEnd
import androidx.compose.ui.Alignment.Companion.CenterVertically
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
@ -32,6 +33,7 @@ import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.test.SendAddressScreenTestTags
import com.tangem.core.ui.utils.DEFAULT_ANIMATION_DURATION
import kotlinx.coroutines.delay
@ -92,6 +94,7 @@ fun InputRowRecipient(
text = it.resolveReference(),
style = TangemTheme.typography.subtitle2,
color = color,
modifier = Modifier.testTag(SendAddressScreenTestTags.ADDRESS_TEXT_FIELD_TITLE),
)
}
Box(
@ -115,7 +118,8 @@ fun InputRowRecipient(
modifier = Modifier
.padding(start = TangemTheme.dimens.spacing12)
.weight(1f)
.align(CenterVertically),
.align(CenterVertically)
.testTag(SendAddressScreenTestTags.ADDRESS_TEXT_FIELD),
)
CrossIcon(
onClick = onPasteClick,

View file

@ -0,0 +1,6 @@
package com.tangem.core.ui.test
object BaseAmountBlockTestTags {
const val PRIMARY_AMOUNT = "STAKING_SEND_DETAILS_SCREEN_PRIMARY_AMOUNT"
const val SECONDARY_AMOUNT = "TAKING_SEND_DETAILS_SCREEN_SECONDARY_AMOUNT"
}

View file

@ -0,0 +1,7 @@
package com.tangem.core.ui.test
object BaseDialogTestTags {
const val CONTAINER = "BASE_DIALOG_CONTAINER"
const val TITLE = "BASE_DIALOG_TITLE"
const val TEXT = "BASE_DIALOG_TEXT"
}

View file

@ -1,5 +0,0 @@
package com.tangem.core.ui.test
object DialogTestTags {
const val DIALOG_CONTAINER = "DIALOG_CONTAINER"
}

View file

@ -0,0 +1,6 @@
package com.tangem.core.ui.test
object SendAddressScreenTestTags {
const val ADDRESS_TEXT_FIELD_TITLE = "SEND_ADDRESS_TEXT_FIELD_TITLE"
const val ADDRESS_TEXT_FIELD = "SEND_ADDRESS_TEXT_FIELD"
}

View file

@ -0,0 +1,16 @@
package com.tangem.core.ui.test
object SendScreenTestTags {
const val SCREEN_CONTAINER = "SEND_SCREEN_CONTAINER"
const val AMOUNT_CONTAINER_TITLE = "SEND_SCREEN_AMOUNT_CONTAINER_TITLE"
const val AMOUNT_CONTAINER_TEXT = "SEND_SCREEN_AMOUNT_CONTAINER_TEXT"
const val INPUT_TEXT_FIELD = "SEND_SCREEN_INPUT_TEXT_FIELD"
const val SECONDARY_AMOUNT = "SEND_SCREEN_SECONDARY_AMOUNT"
const val CURRENCY_BUTTON = "SEND_SCREEN_CURRENCY_BUTTON"
const val FIAT_ICON = "SEND_SCREEN_FIAT_ICON"
const val CURRENCY_ICON = "SEND_SCREEN_CURRENCY_ICON"
const val MAX_BUTTON = "END_SCREEN_MAX_BUTTON"
const val PREVIOUS_BUTTON = "SEND_SCREEN_PREVIOUS_BUTTON"
}

View file

@ -1,10 +1,6 @@
package com.tangem.core.ui.test
object StakingSendDetailsScreenTestTags {
const val PRIMARY_AMOUNT = "STAKING_SEND_DETAILS_SCREEN_PRIMARY_AMOUNT"
const val SECONDARY_AMOUNT = "TAKING_SEND_DETAILS_SCREEN_SECONDARY_AMOUNT"
const val VALIDATOR_BLOCK = "TAKING_SEND_DETAILS_SCREEN_VALIDATOR_BLOCK"
const val NETWORK_FEE_BLOCK = "TAKING_SEND_DETAILS_SCREEN_NETWORK_FEE_BLOCK"
const val VALIDATOR_BLOCK = "STAKING_SEND_DETAILS_SCREEN_VALIDATOR_BLOCK"
const val NETWORK_FEE_BLOCK = "STAKING_SEND_DETAILS_SCREEN_NETWORK_FEE_BLOCK"
}

View file

@ -1,16 +0,0 @@
package com.tangem.core.ui.test
object StakingSendScreenTestTags {
const val SCREEN_CONTAINER = "STAKING_SEND_SCREEN_CONTAINER"
const val AMOUNT_CONTAINER_TITLE = "STAKING_SEND_SCREEN_AMOUNT_CONTAINER_TITLE"
const val AMOUNT_CONTAINER_TEXT = "STAKING_SEND_SCREEN_AMOUNT_CONTAINER_TEXT"
const val INPUT_TEXT_FIELD = "STAKING_SEND_SCREEN_INPUT_TEXT_FIELD"
const val SECONDARY_AMOUNT = "STAKING_SEND_SCREEN_SECONDARY_AMOUNT"
const val CURRENCY_BUTTON = "STAKING_SEND_SCREEN_CURRENCY_BUTTON"
const val FIAT_ICON = "STAKING_SEND_SCREEN_FIAT_ICON"
const val CURRENCY_ICON = "STAKING_SEND_SCREEN_CURRENCY_ICON"
const val MAX_BUTTON = "STAKING_SEND_SCREEN_MAX_BUTTON"
const val PREVIOUS_BUTTON = "STAKING_SEND_SCREEN_PREVIOUS_BUTTON"
}

View file

@ -21,7 +21,7 @@ import com.tangem.core.ui.components.appbar.AppBarWithBackButtonAndIcon
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.test.StakingSendScreenTestTags
import com.tangem.core.ui.test.SendScreenTestTags
import com.tangem.features.staking.impl.R
import com.tangem.features.staking.impl.presentation.state.StakingStates
import com.tangem.features.staking.impl.presentation.state.StakingStep
@ -47,7 +47,7 @@ internal fun StakingScreen(uiState: StakingUiState) {
.fillMaxSize()
.imePadding()
.systemBarsPadding()
.testTag(StakingSendScreenTestTags.SCREEN_CONTAINER),
.testTag(SendScreenTestTags.SCREEN_CONTAINER),
horizontalAlignment = Alignment.CenterHorizontally,
) {
StakingAppBar(

@ -1 +1 @@
Subproject commit 794a8187e6d248ca3c21661df199a34ffeb0037a
Subproject commit 4c0c522992e9ae84c42eeb45564a56b84fe337ef