Updated on 2026-08-14

This commit is contained in:
Tangem 2025-10-27 16:56:39 +03:00
parent cde13c66d3
commit 52925902c2
12 changed files with 477 additions and 16 deletions

View file

@ -4,11 +4,18 @@ object TestConstants {
const val TOTAL_BALANCE = "$3,299.18"
const val RECIPIENT_ADDRESS = "0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0"
const val ETHEREUM_ADDRESS = "0x9FFd974772bDA94D288240C1B22F367Ce75CcD7f"
const val ETHEREUM_RECIPIENT_ADDRESS = "0x5aa711F440Eb6d4361148bBD89d03464628ace84"
const val ETHEREUM_RECIPIENT_SHORTENED_ADDRESS = "0x5aa711F440Eb6d43...89d03464628ace84"
const val BITCOIN_ADDRESS = "bc1qtg9aa6jcpqtvun0pe0uct7sxm8nq2nsxfmfxm3"
const val CARDANO_ADDRESS =
"addr1q8f9499e58k4hhfd9vhawprxt3xd94x7rmlyp33ee4xkatakcl2zgkrg0p6ceqkndtkw4cumfe9enhdph8yhuswn785srksm9p"
const val SOLANA_RECIPIENT_ADDRESS = "5fcy9woa8Di1QHcce65CsV3XKrxdB2pD4HJx5xx82ipM"
const val POLKADOT_RECIPIENT_ADDRESS = "143TfgFYAFfM86LRzt4UcFNU3KosxCndBCVz2U5HCxpLidKZ"
const val XRP_RECIPIENT_ADDRESS = "rNeY28BPda6jp5N5oESZzd2ZN7eMZy8jNf"
const val ENS_NAME = "louded.eth"
const val ENS_ETHEREUM_RECIPIENT_ADDRESS = "0x0211ff638298adcbdc99c177dc2e95ec69948865"
const val ENS_ETHEREUM_RECIPIENT_SHORTENED_ADDRESS = "0x0211ff63829..."
const val WAIT_UNTIL_TIMEOUT = 20_000L
const val WAIT_UNTIL_TIMEOUT_LONG = 30_000L

View file

@ -9,18 +9,88 @@ 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.core.ui.R as CoreUiR
import androidx.compose.ui.test.hasText as withText
import androidx.compose.ui.test.hasTestTag as withTestTag
class SendAddressPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<SendAddressPageObject>(semanticsProvider = semanticsProvider) {
val addressTextFieldTitle: KNode = child {
hasTestTag(SendAddressScreenTestTags.ADDRESS_TEXT_FIELD_TITLE)
useUnmergedTree = true
}
val addressTextField: KNode = child {
hasTestTag(SendAddressScreenTestTags.ADDRESS_TEXT_FIELD)
useUnmergedTree = true
}
val addressPasteButton: KNode = child {
hasTestTag(SendAddressScreenTestTags.ADDRESS_PASTE_BUTTON)
useUnmergedTree = true
}
val clearTextFieldButton: KNode = child {
hasContentDescription(getResourceString(CoreUiR.string.common_close))
useUnmergedTree = true
}
val resolvedAddress: KNode = child {
hasTestTag(SendAddressScreenTestTags.RESOLVED_ADDRESS)
}
val recentAddressesTitle: KNode = child {
hasText(getResourceString(CoreUiR.string.send_recent_transactions))
useUnmergedTree = true
}
fun destinationTagBlockTitle(isMemoCorrectOrEmpty: Boolean = true): KNode = child {
hasTestTag(SendAddressScreenTestTags.DESTINATION_TAG_TEXT_FIELD_TITLE)
useUnmergedTree = true
if(isMemoCorrectOrEmpty) {
hasText(getResourceString(CoreUiR.string.send_destination_tag_field))
} else {
hasText(getResourceString(CoreUiR.string.send_memo_destination_tag_error))
}
}
val destinationTagTextField: KNode = child {
hasTestTag(SendAddressScreenTestTags.DESTINATION_TAG_TEXT_FIELD)
useUnmergedTree = true
}
val destinationTagBlockText: KNode = child {
hasText(
getResourceString(CoreUiR.string.send_recipient_memo_footer_v2) + "\n" +
getResourceString(CoreUiR.string.send_recipient_memo_footer_v2_highlighted)
)
useUnmergedTree = true
}
val destinationTagBlockCaution: KNode = child {
hasText(getResourceString(CoreUiR.string.send_recipient_memo_footer_v2_highlighted))
}
val destinationTagPasteButton: KNode = child {
hasTestTag(SendAddressScreenTestTags.DESTINATION_TAG_PASTE_BUTTON)
useUnmergedTree = true
}
val clearDestinationTagTextFieldButton: KNode = child {
hasTestTag(SendAddressScreenTestTags.DESTINATION_TAG_CLEAR_TEXT_FIELD_BUTTON)
useUnmergedTree = true
}
val nextButton: KNode = child {
hasTestTag(BaseButtonTestTags.TEXT)
hasText(getResourceString(R.string.common_next))
hasTestTag(BaseButtonTestTags.BUTTON)
hasAnyDescendant(withText(getResourceString(R.string.common_next)))
useUnmergedTree = true
}
fun recentAddressWithText(recipientAddress: String): KNode = child {
hasParent(withTestTag(SendAddressScreenTestTags.RECENT_ADDRESS_TITLE))
hasText(recipientAddress)
useUnmergedTree = true
}

View file

@ -75,6 +75,17 @@ class SendConfirmPageObject(semanticsProvider: SemanticsNodeInteractionsProvider
)
useUnmergedTree = true
}
fun recipientAddress(recipientAddress: String): KNode = child {
hasTestTag(SendConfirmScreenTestTags.RECIPIENT_ADDRESS)
hasText(recipientAddress)
useUnmergedTree = true
}
val blockchainAddress: KNode = child {
hasTestTag(SendConfirmScreenTestTags.BLOCKCHAIN_ADDRESS)
useUnmergedTree = true
}
}
internal fun BaseTestCase.onSendConfirmScreen(function: SendConfirmPageObject.() -> Unit) =

View file

@ -15,7 +15,6 @@ 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.Test
@ -130,7 +129,7 @@ class FeedbackTest : BaseTestCase() {
MockProvider.resetEmulateError()
}
).run {
Allure.step("Click on 'Accept' button") {
step("Click on 'Accept' button") {
onDisclaimerScreen { acceptButton.clickWithAssertion() }
}
step("Set scanning error") {

View file

@ -0,0 +1,341 @@
package com.tangem.tests.send.addressScreen
import com.tangem.common.BaseTestCase
import com.tangem.common.constants.TestConstants.ENS_ETHEREUM_RECIPIENT_ADDRESS
import com.tangem.common.constants.TestConstants.ENS_ETHEREUM_RECIPIENT_SHORTENED_ADDRESS
import com.tangem.common.constants.TestConstants.ENS_NAME
import com.tangem.common.constants.TestConstants.ETHEREUM_ADDRESS
import com.tangem.common.constants.TestConstants.ETHEREUM_RECIPIENT_ADDRESS
import com.tangem.common.constants.TestConstants.ETHEREUM_RECIPIENT_SHORTENED_ADDRESS
import com.tangem.common.constants.TestConstants.XRP_RECIPIENT_ADDRESS
import com.tangem.common.extensions.clickWithAssertion
import com.tangem.common.utils.clearClipboard
import com.tangem.common.utils.resetWireMockScenarioState
import com.tangem.common.utils.setClipboardText
import com.tangem.common.utils.setWireMockScenarioState
import com.tangem.core.ui.R
import com.tangem.scenarios.openMainScreen
import com.tangem.scenarios.synchronizeAddresses
import com.tangem.screens.*
import com.tangem.screens.onMainScreen
import com.tangem.screens.onSendAddressScreen
import com.tangem.screens.onSendScreen
import com.tangem.screens.onTokenDetailsScreen
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.Test
@HiltAndroidTest
class SendAddressScreenTest : BaseTestCase() {
@AllureId("4006")
@DisplayName("Send (address screen): check address history")
@Test
fun sendAddressHistoryTest() {
val tokenName = "Ethereum"
val sendAmount = "1"
val recipientShortenedAddress = ETHEREUM_RECIPIENT_SHORTENED_ADDRESS
val recipientAddress = ETHEREUM_RECIPIENT_ADDRESS
setupHooks().run {
step("Open 'Main Screen'") {
openMainScreen()
}
step("Synchronize addresses") {
synchronizeAddresses()
}
step("Click on token with name: '$tokenName'") {
onMainScreen { tokenWithTitleAndAddress(tokenName).clickWithAssertion() }
}
step("Click on 'Send' button") {
onTokenDetailsScreen { sendButton().performClick() }
}
step("Type '$sendAmount' in input text field") {
onSendScreen {
amountInputTextField.performClick()
amountInputTextField.performTextReplacement(sendAmount)
}
}
step("Click on 'Next' button") {
onSendScreen { nextButton.clickWithAssertion() }
}
step("Click on previous address") {
onSendAddressScreen { recentAddressWithText(recipientShortenedAddress).clickWithAssertion() }
}
step("Assert recipient address is displayed") {
onSendConfirmScreen { recipientAddress(recipientAddress).assertIsDisplayed() }
}
step("Press system 'Back' button") {
device.uiDevice.pressBack()
}
step("Assert address text field contains correct recipient address") {
onSendAddressScreen { addressTextField.assertTextContains(recipientAddress) }
}
step("Assert 'Recent' title is displayed") {
onSendAddressScreen { recentAddressesTitle.assertIsNotDisplayed() }
}
step("Assert 'Next' button is enabled") {
onSendAddressScreen { nextButton.assertIsEnabled() }
}
step("Click on 'Cross' button") {
onSendAddressScreen { clearTextFieldButton.clickWithAssertion() }
}
step("Assert recipient text field is empty") {
onSendAddressScreen { addressTextField.assertTextEquals("") }
}
step("Assert 'Recent' title is displayed") {
onSendAddressScreen { recentAddressesTitle.assertIsDisplayed() }
}
step("Assert 'Next' button is disabled") {
onSendAddressScreen { nextButton.assertIsNotEnabled() }
}
}
}
@AllureId("4004")
@DisplayName("Send (address screen): check destination tag")
@Test
fun sendDestinationTagTest() {
val tokenName = "XRP Ledger"
val sendAmount = "1"
val correctMemo = "123"
val invalidMemo = "hz"
val xrpRecipientAddress = XRP_RECIPIENT_ADDRESS
val userTokensScenarioName = "user_tokens_api"
val userTokensScenarioState = "XRP"
val context = device.context
setupHooks(
additionalAfterSection = {
resetWireMockScenarioState(userTokensScenarioName)
}
).run {
step("Set WireMock scenario: '$userTokensScenarioName' to state: '$userTokensScenarioState'") {
setWireMockScenarioState(scenarioName = userTokensScenarioName, state = userTokensScenarioState)
}
step("Open 'Main Screen'") {
openMainScreen()
}
step("Synchronize addresses") {
synchronizeAddresses()
}
step("Click on token with name: '$tokenName'") {
onMainScreen { tokenWithTitleAndAddress(tokenName).performClick() }
}
step("Click on 'Send' button") {
onTokenDetailsScreen { sendButton().performClick() }
}
step("Type '$sendAmount' in input text field") {
onSendScreen {
amountInputTextField.performClick()
amountInputTextField.performTextReplacement(sendAmount)
}
}
step("Click on 'Next' button") {
onSendScreen { nextButton.clickWithAssertion() }
}
step("Set clipboard text") {
setClipboardText(context, correctMemo)
}
step("Assert 'Destination Tag' title is displayed") {
onSendAddressScreen { destinationTagBlockTitle().assertIsDisplayed() }
}
step("Assert 'Destination Tag' text is displayed") {
onSendAddressScreen { destinationTagBlockText.assertIsDisplayed() }
}
step("CLick on 'Paste' button") {
onSendAddressScreen { destinationTagPasteButton.clickWithAssertion() }
}
step("Assert 'Next' button is disabled") {
onSendAddressScreen { nextButton.assertIsNotEnabled() }
}
step("Type address in input text field") {
onSendAddressScreen { addressTextField.performTextReplacement(xrpRecipientAddress) }
}
step("Assert 'Next' button is enabled") {
onSendAddressScreen { nextButton.assertIsEnabled() }
}
step("Click on 'Clear text field button'") {
onSendAddressScreen { clearDestinationTagTextFieldButton.clickWithAssertion() }
}
step("Type invalid memo in input text field") {
onSendAddressScreen { destinationTagTextField.performTextReplacement(invalidMemo) }
}
step("Assert 'Invalid memo' title is displayed") {
onSendAddressScreen { destinationTagBlockTitle(isMemoCorrectOrEmpty = false).assertIsDisplayed() }
}
step("Assert 'Next' button is disabled") {
onSendAddressScreen { nextButton.assertIsNotEnabled() }
}
}
}
@AllureId("4543")
@DisplayName("Send (address screen): check address field")
@Test
fun sendAddressFieldTest() {
val tokenName = "Ethereum"
val sendAmount = "1"
val recipientAddress = ETHEREUM_RECIPIENT_ADDRESS
val invalidAddress = "s"
val walletAddress = ETHEREUM_ADDRESS
val context = device.context
val recipient = getResourceString(R.string.send_recipient)
val notAValidAddress = getResourceString(R.string.send_recipient_address_error)
val sameAsWalletAddress = getResourceString(R.string.send_error_address_same_as_wallet)
setupHooks(
additionalAfterSection = {
clearClipboard()
}
).run {
step("Open 'Main Screen'") {
openMainScreen()
}
step("Synchronize addresses") {
synchronizeAddresses()
}
step("Click on token with name: '$tokenName'") {
onMainScreen { tokenWithTitleAndAddress(tokenName).clickWithAssertion() }
}
step("Click on 'Send' button") {
onTokenDetailsScreen { sendButton().performClick() }
}
step("Type '$sendAmount' in input text field") {
onSendScreen {
amountInputTextField.performClick()
amountInputTextField.performTextReplacement(sendAmount)
}
}
step("Click on 'Next' button") {
onSendScreen { nextButton.clickWithAssertion() }
}
step("Set clipboard text") {
setClipboardText(context, recipientAddress)
}
step("Click on 'Paste' button") {
onSendAddressScreen { addressPasteButton.clickWithAssertion() }
}
step("Assert address text field contains correct recipient address") {
onSendAddressScreen { addressTextField.assertTextContains(recipientAddress) }
}
step("Assert address text field title is displayed") {
onSendAddressScreen { addressTextFieldTitle.assertTextContains(recipient) }
}
step("Assert 'Next' button is enabled") {
onSendAddressScreen { nextButton.assertIsEnabled() }
}
step("Set clipboard text") {
setClipboardText(context, invalidAddress)
}
step("Click on 'Cross' button") {
onSendAddressScreen { clearTextFieldButton.clickWithAssertion() }
}
step("Click on 'Paste' button") {
onSendAddressScreen { addressPasteButton.clickWithAssertion() }
}
step("Assert address text field contains invalid address") {
onSendAddressScreen { addressTextField.assertTextContains(invalidAddress) }
}
step("Assert invalid address text field title is displayed") {
onSendAddressScreen { addressTextFieldTitle.assertTextContains(notAValidAddress) }
}
step("Assert 'Next' button is disabled") {
onSendAddressScreen { nextButton.assertIsNotEnabled() }
}
step("Set clipboard text") {
setClipboardText(context, walletAddress)
}
step("Click on 'Cross' button") {
onSendAddressScreen { clearTextFieldButton.clickWithAssertion() }
}
step("Click on 'Paste' button") {
onSendAddressScreen { addressPasteButton.clickWithAssertion() }
}
step("Assert address text field contains invalid address") {
onSendAddressScreen { addressTextField.assertTextContains(walletAddress) }
}
step("Assert 'Address is the same as wallet address' error title is displayed") {
onSendAddressScreen { addressTextFieldTitle.assertTextContains(sameAsWalletAddress) }
}
step("Assert 'Next' button is disabled") {
onSendAddressScreen { nextButton.assertIsNotEnabled() }
}
}
}
@AllureId("4004")
@DisplayName("Send (address screen): check ENS name")
@Test
fun sendEnsNameTest() {
val tokenName = "Ethereum"
val sendAmount = "1"
val ensName = ENS_NAME
val invalidEnsName = "l"
val ensAddress = ENS_ETHEREUM_RECIPIENT_ADDRESS
val ensShortenedAddress = ENS_ETHEREUM_RECIPIENT_SHORTENED_ADDRESS
val scenarioName = "eth_call_api"
val scenarioState = "EnsName"
val notAValidAddress = getResourceString(R.string.send_recipient_address_error)
setupHooks(
additionalAfterSection = {
resetWireMockScenarioState(scenarioName)
}
).run {
step("Open 'Main Screen'") {
openMainScreen()
}
step("Synchronize addresses") {
synchronizeAddresses()
}
step("Click on token with name: '$tokenName'") {
onMainScreen { tokenWithTitleAndAddress(tokenName).performClick() }
}
step("Click on 'Send' button") {
onTokenDetailsScreen { sendButton().performClick() }
}
step("Set WireMock scenario: '$scenarioName' to state: '$scenarioState'") {
setWireMockScenarioState(scenarioName = scenarioName, state = scenarioState)
}
step("Type '$sendAmount' in input text field") {
onSendScreen {
amountInputTextField.performClick()
amountInputTextField.performTextReplacement(sendAmount)
}
}
step("Click on 'Next' button") {
onSendScreen { nextButton.clickWithAssertion() }
}
step("Type ENS name: '$ensName' in text field") {
onSendAddressScreen { addressTextField.performTextReplacement(ensName) }
}
step("Assert ENS address displayed") {
onSendAddressScreen { resolvedAddress.assertTextContains(ensAddress, substring = true) }
}
step("Click on 'Next' button") {
onSendAddressScreen { nextButton.clickWithAssertion() }
}
step("Assert recipient address is displayed") {
onSendConfirmScreen { recipientAddress(ensName).assertIsDisplayed() }
}
step("Assert blockchain address is displayed") {
onSendConfirmScreen { blockchainAddress.assertTextContains(ensShortenedAddress, substring = true) }
}
step("Click on recipient address") {
onSendConfirmScreen { recipientAddress(ensName).performClick() }
}
step("Click on 'Cross' button") {
onSendAddressScreen { clearTextFieldButton.clickWithAssertion() }
}
step("Type invalid ENS name: '$invalidEnsName' in text field") {
onSendAddressScreen { addressTextField.performTextReplacement(invalidEnsName) }
}
step("Assert invalid address error title is displayed") {
onSendAddressScreen { addressTextFieldTitle.assertTextContains(notAValidAddress) }
}
}
}
}

View file

@ -59,7 +59,7 @@ class SolanaWarningsTest : BaseTestCase() {
onMainScreen { tokenWithTitleAndAddress(tokenName).clickWithAssertion() }
}
step("Click on 'Send' button") {
onTokenDetailsScreen { sendButton.performClick() }
onTokenDetailsScreen { sendButton().performClick() }
}
step("Type '$amountToLeaveLessThanRent' in input text field") {
onSendScreen {
@ -112,7 +112,7 @@ class SolanaWarningsTest : BaseTestCase() {
onMainScreen { tokenWithTitleAndAddress(tokenName).clickWithAssertion() }
}
step("Click on 'Send' button") {
onTokenDetailsScreen { sendButton.performClick() }
onTokenDetailsScreen { sendButton().performClick() }
}
step("Type '$amountToLeaveGreaterThanRent' in input text field") {
onSendScreen {
@ -166,7 +166,7 @@ class SolanaWarningsTest : BaseTestCase() {
onMainScreen { tokenWithTitleAndAddress(tokenName).clickWithAssertion() }
}
step("Click on 'Send' button") {
onTokenDetailsScreen { sendButton.performClick() }
onTokenDetailsScreen { sendButton().performClick() }
}
step("Type '$amountToLeaveRentOnly' in input text field") {
onSendScreen {
@ -220,7 +220,7 @@ class SolanaWarningsTest : BaseTestCase() {
onMainScreen { tokenWithTitleAndAddress(tokenName).clickWithAssertion() }
}
step("Click on 'Send' button") {
onTokenDetailsScreen { sendButton.performClick() }
onTokenDetailsScreen { sendButton().performClick() }
}
step("Type max amount in input text field") {
onSendScreen {

View file

@ -140,7 +140,9 @@ fun InputRowRecipient(
onClick = onPasteClick,
backgroundColorEnabled = TangemTheme.colors.button.secondary,
textColor = TangemTheme.colors.text.primary1,
modifier = Modifier.padding(start = TangemTheme.dimens.spacing8),
modifier = Modifier
.padding(start = TangemTheme.dimens.spacing8)
.testTag(SendAddressScreenTestTags.ADDRESS_PASTE_BUTTON),
)
}
}
@ -224,6 +226,7 @@ private fun ResolvedAddressRow(isLoading: Boolean, resolvedAddress: String?) {
text = state.address,
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.tertiary,
modifier = Modifier.testTag(SendAddressScreenTestTags.RESOLVED_ADDRESS),
)
}
}

View file

@ -1,6 +1,17 @@
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"
const val ADDRESS_TEXT_FIELD_TITLE = "SEND_ADDRESS_SCREEN_TEXT_FIELD_TITLE"
const val ADDRESS_TEXT_FIELD = "SEND_ADDRESS_SCREEN_TEXT_FIELD"
const val ADDRESS_PASTE_BUTTON = "SEND_ADDRESS_SCREEN_ADDRESS_PASTE_BUTTON"
const val RESOLVED_ADDRESS = "SEND_ADDRESS_SCREEN_RESOLVED_ADDRESS"
const val RECENT_ADDRESS_TITLE = "SEND_ADDRESS_SCREEN_RECENT_ADDRESS_TITLE"
const val RECENT_ADDRESS_TEXT = "SEND_ADDRESS_SCREEN_RECENT_ADDRESS_TEXT"
const val RECENT_ADDRESS_ICON = "SEND_ADDRESS_SCREEN_RECENT_ADDRESS_ICON"
const val DESTINATION_TAG_TEXT_FIELD_TITLE = "SEND_ADDRESS_SCREEN_DESTINATION_TAG_TEXT_FIELD_TITLE"
const val DESTINATION_TAG_TEXT_FIELD = "SEND_ADDRESS_SCREEN_DESTINATION_TAG_TEXT_FIELD"
const val DESTINATION_TAG_PASTE_BUTTON = "SEND_ADDRESS_SCREEN_DESTINATION_TAG_PASTE_BUTTON"
const val DESTINATION_TAG_CLEAR_TEXT_FIELD_BUTTON = "SEND_ADDRESS_SCREEN_DESTINATION_TAG_CLEAR_TEXT_FIELD_BUTTON"
}

View file

@ -2,4 +2,7 @@ package com.tangem.core.ui.test
object SendConfirmScreenTestTags {
const val SENDING_TEXT = "SEND_CONFIRM_SCREEN_SENDING_TEXT"
const val RECIPIENT_ADDRESS = "SEND_CONFIRM_SCREEN_RECIPIENT_ADDRESS"
const val BLOCKCHAIN_ADDRESS = "SEND_CONFIRM_SCREEN_BLOCKCHAIN_ADDRESS"
const val RECIPIENT_ADDRESS_ICON = "SEND_CONFIRM_SCREEN_RECIPIENT_ADDRESS_ICON"
}

View file

@ -11,6 +11,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
@ -20,6 +21,7 @@ import com.tangem.core.ui.extensions.resourceReference
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.SendConfirmScreenTestTags
import com.tangem.features.send.v2.impl.R
import com.tangem.features.send.v2.api.subcomponents.destination.entity.DestinationRecipientListUM
import com.tangem.features.send.v2.api.subcomponents.destination.entity.DestinationTextFieldUM
@ -70,6 +72,7 @@ private fun AddressWithMemoBlock(
text = address.value,
style = TangemTheme.typography.body1,
color = TangemTheme.colors.text.primary1,
modifier = Modifier.testTag(SendConfirmScreenTestTags.RECIPIENT_ADDRESS),
)
val blockchainAddress = address.briefBlockchainAddress
if (!blockchainAddress.isNullOrBlank()) {
@ -77,6 +80,7 @@ private fun AddressWithMemoBlock(
text = blockchainAddress,
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.tertiary,
modifier = Modifier.testTag(SendConfirmScreenTestTags.BLOCKCHAIN_ADDRESS),
)
}
}
@ -85,7 +89,8 @@ private fun AddressWithMemoBlock(
modifier = Modifier
.size(TangemTheme.dimens.size36)
.clip(RoundedCornerShape(TangemTheme.dimens.radius18))
.background(TangemTheme.colors.background.tertiary),
.background(TangemTheme.colors.background.tertiary)
.testTag(SendConfirmScreenTestTags.RECIPIENT_ADDRESS_ICON),
)
}

View file

@ -17,6 +17,7 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
@ -36,6 +37,7 @@ import com.tangem.core.ui.extensions.rememberHapticFeedback
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.test.SendAddressScreenTestTags
import com.tangem.domain.models.account.CryptoPortfolioIcon
import com.tangem.features.send.v2.impl.R
import com.tangem.utils.StringsSigns
@ -85,6 +87,7 @@ fun ListItemWithIcon(
}
}
@Suppress("LongMethod")
@Composable
private fun ListItemWithIcon(
title: String,
@ -109,7 +112,8 @@ private fun ListItemWithIcon(
modifier = Modifier
.padding(vertical = 8.dp)
.size(40.dp)
.clip(RoundedCornerShape(20.dp)),
.clip(RoundedCornerShape(20.dp))
.testTag(SendAddressScreenTestTags.RECENT_ADDRESS_ICON),
)
Column(
modifier = Modifier
@ -123,7 +127,7 @@ private fun ListItemWithIcon(
color = TangemTheme.colors.text.primary1,
textAlign = TextAlign.Justify,
ellipsis = TextEllipsis.Middle,
modifier = Modifier,
modifier = Modifier.testTag(SendAddressScreenTestTags.RECENT_ADDRESS_TITLE),
)
Row(verticalAlignment = Alignment.CenterVertically) {
if (subtitleIconRes != null) {
@ -151,6 +155,7 @@ private fun ListItemWithIcon(
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.tertiary,
ellipsis = TextEllipsis.OffsetEnd(offsetEnd = offset),
modifier = Modifier.testTag(SendAddressScreenTestTags.RECENT_ADDRESS_TEXT),
)
if (accountTitleUM != null) {
AccountTitle(

View file

@ -10,6 +10,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment.Companion.CenterEnd
import androidx.compose.ui.Alignment.Companion.CenterVertically
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.components.fields.SimpleTextField
@ -19,6 +20,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.components.containers.FooterContainer
import com.tangem.core.ui.test.SendAddressScreenTestTags
@Suppress("LongMethod", "LongParameterList")
@Composable
@ -61,6 +63,7 @@ internal fun TextFieldWithPaste(
text = title.resolveReference(),
style = labelStyle,
color = color,
modifier = Modifier.testTag(SendAddressScreenTestTags.DESTINATION_TAG_TEXT_FIELD_TITLE),
)
SimpleTextField(
value = value,
@ -71,7 +74,8 @@ internal fun TextFieldWithPaste(
isValuePasted = isValuePasted,
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp),
.padding(top = 8.dp)
.testTag(SendAddressScreenTestTags.DESTINATION_TAG_TEXT_FIELD),
)
}
AnimatedVisibility(
@ -84,6 +88,7 @@ internal fun TextFieldWithPaste(
) {
CrossIcon(
onClick = onPasteClick,
modifier = Modifier.testTag(SendAddressScreenTestTags.DESTINATION_TAG_CLEAR_TEXT_FIELD_BUTTON),
)
}
}
@ -100,7 +105,8 @@ internal fun TextFieldWithPaste(
backgroundColorEnabled = TangemTheme.colors.button.secondary,
textColor = TangemTheme.colors.text.primary1,
modifier = Modifier
.padding(start = TangemTheme.dimens.spacing8),
.padding(start = TangemTheme.dimens.spacing8)
.testTag(SendAddressScreenTestTags.DESTINATION_TAG_PASTE_BUTTON),
)
}
}