Updated on 2026-08-14

This commit is contained in:
Tangem 2026-04-21 13:10:18 +04:00
parent c846d8c276
commit d30f231520
19 changed files with 613 additions and 32 deletions

View file

@ -43,6 +43,7 @@ object TestConstants {
const val ALLURE_LABEL_VALUE = "Kaspresso"
const val USER_TOKENS_API_SCENARIO = "user_tokens_api"
const val REFERRAL_API_SCENARIO = "referral_api"
const val QUOTES_API_SCENARIO = "quotes_api"
const val SEED_PHRASE_12 = "they cram join fantasy unfair observe true theory buffalo bus exchange walk"

View file

@ -0,0 +1,102 @@
package com.tangem.scenarios
import com.tangem.common.BaseTestCase
import com.tangem.common.extensions.clickWithAssertion
import com.tangem.screens.accounts.onAccountDetailsScreen
import com.tangem.screens.accounts.onArchivedAccountsScreen
import com.tangem.screens.onDetailsScreen
import com.tangem.screens.onDialog
import com.tangem.screens.onMainScreenTopBar
import com.tangem.screens.onWalletSettingsScreen
import io.qameta.allure.kotlin.Allure.step
fun BaseTestCase.openWalletSettingsScreen() {
step("Open 'Wallet details' screen") {
onMainScreenTopBar { moreButton.clickWithAssertion() }
}
step("Open 'Wallet settings' screen") {
onDetailsScreen { walletNameButton.clickWithAssertion() }
}
}
fun BaseTestCase.openAccountDetails(accountName: String) {
step("Click on account: '$accountName'") {
onWalletSettingsScreen { accountItem(accountName).clickWithAssertion() }
}
step("Assert 'Account details' screen is displayed") {
onAccountDetailsScreen { screenContainer.assertIsDisplayed() }
}
}
fun BaseTestCase.archiveAccount() {
step("Assert 'Archive' button is displayed") {
onAccountDetailsScreen { archiveAccountButton.assertIsDisplayed() }
}
step("Click on 'Archive' button") {
onAccountDetailsScreen { archiveAccountButton.clickWithAssertion() }
}
step("Confirm archivation in dialog") {
onDialog { archiveButton.clickWithAssertion() }
}
}
fun BaseTestCase.assertArchiveConfirmationDialog() {
step("Assert confirmation dialog is displayed") {
onDialog { dialogContainer.assertIsDisplayed() }
}
step("Assert confirmation dialog has 'Cancel' button") {
onDialog { cancelButton.assertIsDisplayed() }
}
step("Assert confirmation dialog has 'Archive' button") {
onDialog { archiveButton.assertIsDisplayed() }
}
}
fun BaseTestCase.assertErrorDialog(expectedTitle: String, expectedMessage: String) {
step("Assert error dialog is displayed") {
onDialog { dialogContainer.assertIsDisplayed() }
}
step("Assert error dialog has proper title") {
onDialog {
title.assertTextContains(expectedTitle)
}
}
step("Assert error dialog has explanatory text") {
onDialog {
text.assertTextContains(expectedMessage)
}
}
step("Assert error dialog has 'OK' button") {
onDialog { okButton.assertIsDisplayed() }
}
}
fun BaseTestCase.dismissErrorDialog() {
step("Dismiss error dialog by clicking 'Ok' button") {
onDialog { okButton.clickWithAssertion() }
}
}
fun BaseTestCase.openArchivedAccountsScreen() {
step("Click on 'Archived accounts' button") {
onWalletSettingsScreen { openArchivedAccountsButton.clickWithAssertion() }
}
}
fun BaseTestCase.assertArchivedAccountIsDisplayed(accountName: String) {
step("Assert archived account with name '$accountName' is displayed") {
onArchivedAccountsScreen {
findArchivedAccountItemByName(accountName)
.container.assertIsDisplayed()
}
}
}
fun BaseTestCase.restoreArchivedAccount(accountName: String) {
step("Restore account with name '$accountName'") {
onArchivedAccountsScreen {
findArchivedAccountItemByName(accountName)
.restoreButton.clickWithAssertion()
}
}
}

View file

@ -40,6 +40,11 @@ class DialogPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
hasText(getResourceString(R.string.common_confirm))
}
val archiveButton: KNode = child {
hasTestTag(BaseButtonTestTags.BUTTON)
hasText(getResourceString(R.string.account_details_archive_action))
}
val continueButton: KNode = child {
hasTestTag(BaseButtonTestTags.BUTTON)
hasText(getResourceString(R.string.common_continue))

View file

@ -38,6 +38,18 @@ class WalletSettingsPageObject(semanticsProvider: SemanticsNodeInteractionsProvi
hasText(getResourceString(R.string.settings_forget_wallet))
}
val accountsListContainer: KNode = walletSettingsItem.child {
hasTestTag(WalletSettingsScreenTestTags.ACCOUNTS_CONTAINER)
}
val addAccountButton: KNode = walletSettingsItem.child {
hasText(getResourceString(R.string.account_form_create_button))
}
val openArchivedAccountsButton: KNode = walletSettingsItem.child {
hasText(getResourceString(R.string.account_archived_accounts))
}
fun accountItem(accountName: String): KNode = walletSettingsItem.child {
hasTestTag(WalletSettingsScreenTestTags.USER_ACCOUNT_ITEM)
hasAnyDescendant(withText(accountName))

View file

@ -1,8 +1,8 @@
package com.tangem.screens
package com.tangem.screens.accounts
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
import com.tangem.common.BaseTestCase
import com.tangem.core.ui.test.AccountDetailsScreenTestTags
import com.tangem.core.ui.test.accounts.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
@ -11,6 +11,10 @@ import io.github.kakaocup.compose.node.element.KNode
class AccountDetailsPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<AccountDetailsPageObject>(semanticsProvider = semanticsProvider) {
val screenContainer: KNode = child {
hasTestTag(AccountDetailsScreenTestTags.ACCOUNT_DETAILS_CONTAINER)
}
val topAppBarBackButton: KNode = child {
hasTestTag(TopAppBarTestTags.CLOSE_BUTTON)
}
@ -18,7 +22,16 @@ class AccountDetailsPageObject(semanticsProvider: SemanticsNodeInteractionsProvi
val manageTokensButton: KNode = child {
hasTestTag(AccountDetailsScreenTestTags.MANAGE_TOKENS_BUTTON)
}
val archiveAccountButton: KNode = child {
hasTestTag(AccountDetailsScreenTestTags.ARCHIVE_ACCOUNT_BUTTON)
}
val editAccountButton: KNode = child {
hasTestTag(AccountDetailsScreenTestTags.EDIT_ACCOUNT_BUTTON)
}
}
internal fun BaseTestCase.onAccountDetails(function: AccountDetailsPageObject.() -> Unit) =
internal fun BaseTestCase.onAccountDetailsScreen(function: AccountDetailsPageObject.() -> Unit) =
onComposeScreen(composeTestRule, function)

View file

@ -0,0 +1,70 @@
package com.tangem.screens.accounts
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
import com.tangem.common.BaseTestCase
import com.tangem.core.ui.R
import com.tangem.core.ui.test.TopAppBarTestTags
import com.tangem.core.ui.test.accounts.AccountRowTestTags
import com.tangem.core.ui.test.accounts.ArchivedAccountsScreenTestTags
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 ArchivedAccountsPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<ArchivedAccountsPageObject>(semanticsProvider = semanticsProvider) {
val screenContainer: KNode = child {
hasTestTag(ArchivedAccountsScreenTestTags.ARCHIVED_ACCOUNTS_SCREEN_CONTAINER)
}
val topAppBarBackButton: KNode = child {
hasTestTag(TopAppBarTestTags.CLOSE_BUTTON)
}
val topAppBarTitle: KNode = child {
hasTestTag(TopAppBarTestTags.TITLE)
hasText(getResourceString(R.string.account_archived_accounts))
useUnmergedTree = true
}
/**
* Returns a composite handle for a single archived account row, scoped by account name.
* All sub-elements (icon, title, tokens, networks, restore button) are children of this row.
*/
fun findArchivedAccountItemByName(accountName: String): ArchivedAccountRow {
val container: KNode = child {
hasTestTag(ArchivedAccountsScreenTestTags.ARCHIVED_ACCOUNT_ITEM)
hasAnyDescendant(withText(accountName))
useUnmergedTree = true
}
return ArchivedAccountRow(container)
}
class ArchivedAccountRow(val container: KNode) {
val icon: KNode = container.child {
hasTestTag(AccountRowTestTags.ICON)
useUnmergedTree = true
}
val title: KNode = container.child {
hasTestTag(AccountRowTestTags.TITLE)
useUnmergedTree = true
}
val subtitle: KNode = container.child {
hasTestTag(AccountRowTestTags.SUBTITLE)
useUnmergedTree = true
}
val restoreButton: KNode = container.child {
hasTestTag(ArchivedAccountsScreenTestTags.RESTORE_BUTTON)
useUnmergedTree = true
}
}
}
internal fun BaseTestCase.onArchivedAccountsScreen(function: ArchivedAccountsPageObject.() -> Unit) =
onComposeScreen(composeTestRule, function)

View file

@ -0,0 +1,253 @@
package com.tangem.tests.accounts
import com.tangem.common.BaseTestCase
import com.tangem.common.constants.TestConstants.REFERRAL_API_SCENARIO
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.core.ui.R
import com.tangem.scenarios.*
import com.tangem.screens.accounts.onAccountDetailsScreen
import com.tangem.screens.accounts.onArchivedAccountsScreen
import com.tangem.screens.onDialog
import com.tangem.screens.onWalletSettingsScreen
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 AccountArchivationsTest : BaseTestCase() {
private val userTokensScenario = USER_TOKENS_API_SCENARIO
private val referralScenario = REFERRAL_API_SCENARIO
@Test
@AllureId("5979")
@DisplayName("Accounts: Verify main account archivation button not available")
fun mainAccountArchivationAttemptTest() {
val mainAccountName = "Main account"
setupHooks().run {
step("Open 'Main Screen'") { openMainScreen() }
step("Synchronize addresses") { synchronizeAddresses() }
step("Open wallet settings") { openWalletSettingsScreen() }
step("Open wallet account with name $mainAccountName") { openAccountDetails(mainAccountName) }
step("Assert archive button is NOT displayed") {
onAccountDetailsScreen { archiveAccountButton.assertDoesNotExist() }
}
}
}
@Test
@AllureId("5974")
@DisplayName("Accounts: archive a non-main account")
fun archiveSuccessfullyAccountTest() {
val accountToArchiveName = "Account 2"
val userAccountsState = "TwoAccountsArchivable"
setupHooks(
additionalBeforeSection = {
setWireMockScenarioState(userTokensScenario, userAccountsState)
},
additionalAfterSection = {
resetWireMockScenarioState(userTokensScenario)
},
).run {
step("Open 'Main Screen'") { openMainScreen() }
step("Synchronize addresses") { synchronizeAddresses() }
step("Open wallet settings") { openWalletSettingsScreen() }
step("Open wallet account with name $accountToArchiveName") {
openAccountDetails(accountToArchiveName)
}
step("Assert 'Archive' button is displayed") {
onAccountDetailsScreen { archiveAccountButton.assertIsDisplayed() }
}
step("Click on 'Archive' button") {
onAccountDetailsScreen { archiveAccountButton.clickWithAssertion() }
}
step("Verify 'Archive confirmation' dialog appeared with all elements") {
assertArchiveConfirmationDialog()
}
step("Click 'Archive' in confirmation menu") {
onDialog { archiveButton.clickWithAssertion() }
}
step("Verify app returned to 'Wallet settings' screen") {
onWalletSettingsScreen { addAccountButton.assertIsDisplayed() }
}
step("Verify archived account '$accountToArchiveName' is no longer listed") {
onWalletSettingsScreen {
accountItem(accountToArchiveName).assertDoesNotExist()
}
}
}
}
@Test
@AllureId("6844")
@DisplayName("Accounts: account archivation error on UI")
fun archiveAccountErrorTest() {
val accountToArchiveName = "Account 2"
val userAccountsState = "TwoAccountsArchivable"
val userAccountsErrorState = "AccountsPutError"
setupHooks(
additionalBeforeSection = {
setWireMockScenarioState(userTokensScenario, userAccountsState)
},
additionalAfterSection = {
resetWireMockScenarioState(userTokensScenario)
},
).run {
step("Open 'Main Screen'") { openMainScreen() }
step("Synchronize addresses") { synchronizeAddresses() }
step("Open wallet settings") { openWalletSettingsScreen() }
step("Open wallet account with name $accountToArchiveName") {
openAccountDetails(accountToArchiveName)
}
step("Forcing network error scenario") {
setWireMockScenarioState(userTokensScenario, userAccountsErrorState)
}
step("Attempt to archive the account") { archiveAccount() }
step("Assert error dialog details") {
assertErrorDialog(
expectedTitle = getResourceString(R.string.common_something_went_wrong),
expectedMessage = getResourceString(R.string.account_generic_error_dialog_message),
)
}
}
}
@Test
@AllureId("5981")
@DisplayName("Accounts: archive account with referral program error")
fun archiveAccountReferralErrorTest() {
val accountToArchiveName = "Account 2"
val userAccountsState = "TwoAccountsArchivableAndReferral"
val referralActiveState = "Participating"
setupHooks(
additionalBeforeSection = {
setWireMockScenarioState(userTokensScenario, userAccountsState)
setWireMockScenarioState(referralScenario, referralActiveState)
},
additionalAfterSection = {
resetWireMockScenarioState(userTokensScenario)
resetWireMockScenarioState(referralScenario)
},
).run {
step("Open 'Main Screen'") { openMainScreen() }
step("Synchronize addresses") { synchronizeAddresses() }
step("Open wallet settings") { openWalletSettingsScreen() }
step("Open wallet account with name $accountToArchiveName") {
openAccountDetails(accountToArchiveName)
}
step("Attempt to archive the account") { archiveAccount() }
step("Assert error dialog details") {
assertErrorDialog(
expectedTitle = getResourceString(R.string.account_could_not_archive_referral_program_title),
expectedMessage = getResourceString(R.string.account_could_not_archive_referral_program_message),
)
}
step("Dismiss error dialog") { dismissErrorDialog() }
step("Assert 'Archive' button is still visible after error") {
onAccountDetailsScreen { archiveAccountButton.assertIsDisplayed() }
}
}
}
@Test
@AllureId("5976")
@DisplayName("Accounts: restore an archived account")
fun restoreArchivedAccountTest() {
val archivedAccountName = "Account 3"
val userAccountsInitialState = "TwoAccountsWithArchivedAccounts"
val userAccountsAfterArchivationState = "ReadyToRestore"
setupHooks(
additionalBeforeSection = {
setWireMockScenarioState(userTokensScenario, userAccountsInitialState)
},
additionalAfterSection = {
resetWireMockScenarioState(userTokensScenario)
},
).run {
step("Open 'Main Screen'") { openMainScreen() }
step("Synchronize addresses") { synchronizeAddresses() }
step("Open wallet settings") { openWalletSettingsScreen() }
step("Open 'Archived accounts' screen") { openArchivedAccountsScreen() }
step("Verify archived wallet account with name '$archivedAccountName' is present") {
assertArchivedAccountIsDisplayed(archivedAccountName)
}
step("Switch WireMock to '$userAccountsAfterArchivationState' users scenario state") {
setWireMockScenarioState(userTokensScenario, userAccountsAfterArchivationState)
}
step("Restore account with name '$archivedAccountName'") {
restoreArchivedAccount(archivedAccountName)
}
step("Assert 'Wallet settings' screen is displayed") {
onWalletSettingsScreen { addAccountButton.assertIsDisplayed() }
}
step("Assert restored account '$archivedAccountName' appears in 'Active accounts' list") {
onWalletSettingsScreen { accountItem(archivedAccountName).assertIsDisplayed() }
}
}
}
@Test
@AllureId("7962")
@DisplayName("Accounts: restore archived account error")
fun restoreArchivedAccountErrorTest() {
val archivedAccountName = "Account 3"
val userAccountsInitialState = "TwoAccountsWithArchivedAccounts"
val userAccountsRestorationErrorState = "AccountsPutError"
setupHooks(
additionalBeforeSection = {
setWireMockScenarioState(userTokensScenario, userAccountsInitialState)
},
additionalAfterSection = {
resetWireMockScenarioState(userTokensScenario)
},
).run {
step("Open 'Main Screen'") { openMainScreen() }
step("Synchronize addresses") { synchronizeAddresses() }
step("Open wallet settings") { openWalletSettingsScreen() }
step("Open 'Archived accounts' screen") { openArchivedAccountsScreen() }
step("Verify archived wallet account with name '$archivedAccountName' is present") {
assertArchivedAccountIsDisplayed(archivedAccountName)
}
step("Switch WireMock to '$userAccountsRestorationErrorState' user" +
"accounts scenario state to simulate restoration failure") {
setWireMockScenarioState(userTokensScenario, userAccountsRestorationErrorState)
}
step("Attempt restore account with name '$archivedAccountName'") {
restoreArchivedAccount(archivedAccountName)
}
step("Assert error dialog details") {
assertErrorDialog(
expectedTitle = getResourceString(R.string.common_something_went_wrong),
expectedMessage = getResourceString(R.string.account_generic_error_dialog_message),
)
}
step("Dismiss error dialog") { dismissErrorDialog() }
step("Assert archived account '$archivedAccountName' is still in archived list") {
onArchivedAccountsScreen {
findArchivedAccountItemByName(archivedAccountName)
.container.assertIsDisplayed()
}
}
}
}
}

View file

@ -9,6 +9,7 @@ import com.tangem.common.utils.setWireMockScenarioState
import com.tangem.scenarios.openMainScreen
import com.tangem.scenarios.synchronizeAddresses
import com.tangem.screens.*
import com.tangem.screens.accounts.onAccountDetailsScreen
import dagger.hilt.android.testing.HiltAndroidTest
import io.qameta.allure.kotlin.AllureId
import io.qameta.allure.kotlin.junit4.DisplayName
@ -93,7 +94,7 @@ class HideTokenTest : BaseTestCase() {
onWalletSettingsScreen { accountItem(accountName).performClick() }
}
step("Click on 'Manage tokens' button") {
onAccountDetails { manageTokensButton.performClick() }
onAccountDetailsScreen { manageTokensButton.performClick() }
}
step("Click on token: '$tokenTitle'") {
onManageTokensScreen { tokenItem(tokenTitle).performClick() }
@ -118,7 +119,7 @@ class HideTokenTest : BaseTestCase() {
}
step("Click on 'Account details' screen 'Back' button") {
waitForIdle()
onAccountDetails { topAppBarBackButton.performClick() }
onAccountDetailsScreen { topAppBarBackButton.performClick() }
}
step("Click on 'Wallet settings' screen 'Back' button") {
waitForIdle()
@ -162,7 +163,7 @@ class HideTokenTest : BaseTestCase() {
onWalletSettingsScreen { accountItem(accountName).performClick() }
}
step("Click on 'Manage tokens' button") {
onAccountDetails { manageTokensButton.performClick() }
onAccountDetailsScreen { manageTokensButton.performClick() }
}
step("Click on token: '$tokenTitle'") {
onManageTokensScreen { tokenItem(tokenTitle).performClick() }
@ -187,7 +188,7 @@ class HideTokenTest : BaseTestCase() {
}
step("Click on 'Account details' screen 'Back' button") {
waitForIdle()
onAccountDetails { topAppBarBackButton.performClick() }
onAccountDetailsScreen { topAppBarBackButton.performClick() }
}
step("Click on 'Wallet settings' screen 'Back' button") {
waitForIdle()
@ -308,5 +309,4 @@ class HideTokenTest : BaseTestCase() {
}
}
}
}

View file

@ -24,6 +24,9 @@ import java.util.Date
@Suppress("LargeClass")
object WalletMockContent : MockContent {
private val secp256k1WalletPublicKey =
byteArrayOf(2, -109, 28, -27, -124, -58, -97, -61, 43, -84, 90, -9, -5, 4, 90, 17, 112, -125, -108, 44, 19, -79, -60, -23, 34, -20, -20, 61, 84, 113, 120, -90, -5)
private val primaryCard = PrimaryCard(
cardId = "AC05000000086747",
batchId = "AC05",
@ -100,7 +103,7 @@ object WalletMockContent : MockContent {
),
wallets = listOf(
CardDTO.Wallet(
publicKey = byteArrayOf(2, -109, 28, -27, -124, -58, -97, -61, 43, -84, 90, -9, -5, 4, 90, 17, 112, -125, -108, 44, 19, -79, -60, -23, 34, -20, -20, 61, 84, 113, 120, -90, -5),
publicKey = secp256k1WalletPublicKey,
chainCode = byteArrayOf(80, 13, -8, -108, -35, 116, -92, 125, -65, -28, 85, 72, -113, 59, 83, 13, 5, -83, -102, 123, 124, -22, 94, 108, -71, 95, 65, -2, 38, 38, -108, 14),
curve = EllipticCurve.Secp256k1,
settings = CardWallet.Settings(isPermanent = false),
@ -117,11 +120,15 @@ object WalletMockContent : MockContent {
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
),
DerivationPath("m/44'/60'/0'/0/1") to ExtendedPublicKey(
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
),
DerivationPath("m/44'/1'/0'/0/0") to ExtendedPublicKey(
publicKey = byteArrayOf(2, -40, 115, -15, 80, 104, 100, -29, 80, 29, 112, -35, -54, 64, -98, 45, 115, 108, 93, 113, -71, 89, 17, 72, 98, 21, 126, 82, -50, 50, -12, -87, -62),
chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41),
),
DerivationPath("m/44'/195'/0'/0/0") to ExtendedPublicKey(
DerivationPath("m/44'/195'/0'/0/0") to ExtendedPublicKey( // Tron Network
publicKey = byteArrayOf(2, -40, 115, -15, 80, 104, 100, -29, 80, 29, 112, -35, -54, 64, -98, 45, 115, 108, 93, 113, -71, 89, 17, 72, 98, 21, 126, 82, -50, 50, -12, -87, -62),
chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41),
),
@ -137,7 +144,7 @@ object WalletMockContent : MockContent {
publicKey = byteArrayOf(2, -40, 115, -15, 80, 104, 100, -29, 80, 29, 112, -35, -54, 64, -98, 45, 115, 108, 93, 113, -71, 89, 17, 72, 98, 21, 126, 82, -50, 50, -12, -87, -62),
chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41),
),
DerivationPath("m/44'/501'/0'") to ExtendedPublicKey(
DerivationPath("m/44'/501'/0'") to ExtendedPublicKey( // Solana
publicKey = byteArrayOf(2, -40, 115, -15, 80, 104, 100, -29, 80, 29, 112, -35, -54, 64, -98, 45, 115, 108, 93, 113, -71, 89, 17, 72, 98, 21, 126, 82, -50, 50, -12, -87, -62),
chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41),
),
@ -151,7 +158,7 @@ object WalletMockContent : MockContent {
),
),
extendedPublicKey = ExtendedPublicKey(
publicKey = byteArrayOf(2, -109, 28, -27, -124, -58, -97, -61, 43, -84, 90, -9, -5, 4, 90, 17, 112, -125, -108, 44, 19, -79, -60, -23, 34, -20, -20, 61, 84, 113, 120, -90, -5),
publicKey = secp256k1WalletPublicKey,
chainCode = byteArrayOf(80, 13, -8, -108, -35, 116, -92, 125, -65, -28, 85, 72, -113, 59, 83, 13, 5, -83, -102, 123, 124, -22, 94, 108, -71, 95, 65, -2, 38, 38, -108, 14),
),
isImported = false,
@ -193,9 +200,7 @@ object WalletMockContent : MockContent {
override val derivationTaskResponse = DerivationTaskResponse(
entries = mapOf(
ByteArrayKey(
byteArrayOf(2, -109, 28, -27, -124, -58, -97, -61, 43, -84, 90, -9, -5, 4, 90, 17, 112, -125, -108, 44, 19, -79, -60, -23, 34, -20, -20, 61, 84, 113, 120, -90, -5),
)
ByteArrayKey(secp256k1WalletPublicKey)
to
ExtendedPublicKeysMap(
mapOf(
@ -220,6 +225,20 @@ object WalletMockContent : MockContent {
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/1") to ExtendedPublicKey( // eth (account 2)
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/3") to ExtendedPublicKey( // eth (account 3)
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/145'/0'/0/0") to ExtendedPublicKey( // bch
publicKey = byteArrayOf(2, 38, -6, 92, -37, -91, -59, -108, -18, -119, -55, 41, 38, -33, 44, 59, 24, -79, -14, -38, -10, -123, 106, 56, 39, 8, 112, 29, -41, 99, 70, -104, -121),
chainCode = byteArrayOf(105, -21, -61, -50, 68, -89, 119, 53, -96, -40, 119, 77, -122, 121, 16, 40, -50, -48, -105, -101, -74, -7, -94, -59, -90, 96, 59, 99, 43, -91, 115, -29),
@ -241,7 +260,14 @@ object WalletMockContent : MockContent {
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/195'/0'/0/0") to ExtendedPublicKey(
DerivationPath("m/44'/195'/0'/0/0") to ExtendedPublicKey( // Tron (account 0)
publicKey = byteArrayOf(2, -40, 115, -15, 80, 104, 100, -29, 80, 29, 112, -35, -54, 64, -98, 45, 115, 108, 93, 113, -71, 89, 17, 72, 98, 21, 126, 82, -50, 50, -12, -87, -62),
chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/195'/1'/0/0") to ExtendedPublicKey( // Tron (account 2)
publicKey = byteArrayOf(2, -40, 115, -15, 80, 104, 100, -29, 80, 29, 112, -35, -54, 64, -98, 45, 115, 108, 93, 113, -71, 89, 17, 72, 98, 21, 126, 82, -50, 50, -12, -87, -62),
chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41),
depth = 0,
@ -269,6 +295,13 @@ object WalletMockContent : MockContent {
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/111111'/1'/0/0") to ExtendedPublicKey( // Kaspa (account 2)
publicKey = byteArrayOf(2, -40, 115, -15, 80, 104, 100, -29, 80, 29, 112, -35, -54, 64, -98, 45, 115, 108, 93, 113, -71, 89, 17, 72, 98, 21, 126, 82, -50, 50, -12, -87, -62),
chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/330'/0'/0/0") to ExtendedPublicKey( // Terra
publicKey = byteArrayOf(2, -40, 115, -15, 80, 104, 100, -29, 80, 29, 112, -35, -54, 64, -98, 45, 115, 108, 93, 113, -71, 89, 17, 72, 98, 21, 126, 82, -50, 50, -12, -87, -62),
chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41),
@ -305,7 +338,14 @@ object WalletMockContent : MockContent {
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/501'/0'") to ExtendedPublicKey( // Solana
DerivationPath("m/44'/501'/0'") to ExtendedPublicKey( // Solana (account 1)
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/501'/1'") to ExtendedPublicKey( // Solana (account 2)
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
@ -386,6 +426,13 @@ object WalletMockContent : MockContent {
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/3") to ExtendedPublicKey( // eth
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
@ -407,7 +454,30 @@ object WalletMockContent : MockContent {
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/111111'/1'/0/0") to ExtendedPublicKey( // Kaspa (account 2)
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6,
77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67,),
chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/818'/0'/0/0") to ExtendedPublicKey( // Vechain
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6,
77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67,),
chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/195'/0'/0/0") to ExtendedPublicKey( // Tron (account 1)
publicKey = byteArrayOf(2, -40, 115, -15, 80, 104, 100, -29, 80, 29, 112, -35, -54, 64, -98, 45, 115, 108, 93, 113, -71, 89, 17, 72, 98, 21, 126, 82, -50, 50, -12, -87, -62),
chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/195'/1'/0/0") to ExtendedPublicKey( // Tron (account 2)
publicKey = byteArrayOf(2, -40, 115, -15, 80, 104, 100, -29, 80, 29, 112, -35, -54, 64, -98, 45, 115, 108, 93, 113, -71, 89, 17, 72, 98, 21, 126, 82, -50, 50, -12, -87, -62),
chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41),
depth = 0,
@ -436,9 +506,16 @@ object WalletMockContent : MockContent {
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/501'/0'") to ExtendedPublicKey( // Solana
publicKey = byteArrayOf(2, -40, 115, -15, 80, 104, 100, -29, 80, 29, 112, -35, -54, 64, -98, 45, 115, 108, 93, 113, -71, 89, 17, 72, 98, 21, 126, 82, -50, 50, -12, -87, -62),
chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41),
DerivationPath("m/44'/501'/0'") to ExtendedPublicKey( // Solana (account 1)
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/501'/1'") to ExtendedPublicKey( // Solana (account 2)
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,

View file

@ -9,6 +9,7 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.common.ui.R
@ -19,6 +20,7 @@ import com.tangem.core.ui.extensions.resourceReference
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.accounts.AccountRowTestTags
/**
* Displays a row representing an account with an icon, title, and subtitle.
@ -54,6 +56,7 @@ fun AccountRow(
name = title,
icon = icon,
size = AccountIconSize.Default,
modifier = Modifier.testTag(AccountRowTestTags.ICON),
)
Column(
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing2),
@ -72,6 +75,7 @@ fun AccountRow(
@Composable
private fun Title(title: TextReference) {
Text(
modifier = Modifier.testTag(AccountRowTestTags.TITLE),
text = title.resolveReference(),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.primary1,
@ -83,6 +87,7 @@ private fun Title(title: TextReference) {
@Composable
private fun Subtitle(subtitle: TextReference) {
Text(
modifier = Modifier.testTag(AccountRowTestTags.SUBTITLE),
color = TangemTheme.colors.text.tertiary,
style = TangemTheme.typography.caption2,
text = subtitle.resolveReference(),

View file

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

View file

@ -2,6 +2,7 @@ package com.tangem.core.ui.test
object WalletSettingsScreenTestTags {
const val SCREEN_CONTAINER = "WALLET_SETTINGS_SCREEN_CONTAINER"
const val ACCOUNTS_CONTAINER = "WALLET_SETTINGS_SCREEN_ACCOUNTS_CONTAINER"
const val SCREEN_ITEM = "WALLET_SETTINGS_SCREEN_ITEM"
const val USER_ACCOUNT_ITEM = "WALLET_SETTINGS_USER_ACCOUNT_ITEM"
}

View file

@ -0,0 +1,9 @@
package com.tangem.core.ui.test.accounts
object AccountDetailsScreenTestTags {
const val ACCOUNT_DETAILS_CONTAINER = "ACCOUNT_DETAILS_SCREEN_CONTAINER"
const val MANAGE_TOKENS_BUTTON = "ACCOUNT_DETAILS_SCREEN_MANAGE_TOKENS_BUTTON"
const val EDIT_ACCOUNT_BUTTON = "ACCOUNT_DETAILS_SCREEN_EDIT_ACCOUNT_BUTTON"
const val ARCHIVE_ACCOUNT_BUTTON = "ACCOUNT_DETAILS_SCREEN_ARCHIVE_ACCOUNT_BUTTON"
}

View file

@ -0,0 +1,10 @@
package com.tangem.core.ui.test.accounts
object AccountInfoEditScreenTestTags {
const val ACCOUNT_DETAILS_CONTAINER = "ACCOUNT_INFO_EDIT_SCREEN_ACCOUNT_DETAILS_CONTAINER"
const val ADD_ACCOUNT_BUTTON = "ACCOUNT_INFO_EDIT_SCREEN_ADD_ACCOUNT_BUTTON"
const val COLOR_OPTION = "ACCOUNT_INFO_EDIT_SCREEN_ACCOUNT_INFO_COLOR_OPTION"
const val TYPE_OPTION = "ACCOUNT_INFO_EDIT_SCREEN_ACCOUNT_INFO_TYPE_OPTION"
const val SELECTED_ICON = "ACCOUNT_INFO_EDIT_SCREEN_SELECTED_ICON"
const val NAME_FIELD = "ACCOUNT_INFO_EDIT_SCREEN_ACCOUNT_INFO_NAME_FIELD"
}

View file

@ -0,0 +1,7 @@
package com.tangem.core.ui.test.accounts
object AccountRowTestTags {
const val ICON = "ACCOUNT_ROW_ICON"
const val TITLE = "ACCOUNT_ROW_TITLE"
const val SUBTITLE = "ACCOUNT_ROW_SUBTITLE"
}

View file

@ -0,0 +1,8 @@
package com.tangem.core.ui.test.accounts
object ArchivedAccountsScreenTestTags {
const val ARCHIVED_ACCOUNTS_SCREEN_CONTAINER = "ARCHIVED_ACCOUNTS_LIST_CONTAINER"
const val ARCHIVED_ACCOUNT_ITEM = "ARCHIVED_ACCOUNTS_LIST_ARCHIVED_ACCOUNT_ITEM"
const val RESTORE_BUTTON = "ARCHIVED_ACCOUNTS_LIST_RESTORE_BUTTON"
}

View file

@ -11,6 +11,7 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
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.datasource.CollectionPreviewParameterProvider
@ -27,6 +28,7 @@ import com.tangem.core.ui.extensions.stringReference
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.accounts.ArchivedAccountsScreenTestTags
import com.tangem.features.account.archived.entity.AccountArchivedUM
import com.tangem.features.account.archived.entity.ArchivedAccountUM
import kotlinx.collections.immutable.toImmutableList
@ -102,7 +104,7 @@ private fun ArchiveAccountError(state: AccountArchivedUM.Error, modifier: Modifi
@Composable
private fun ArchiveAccountContent(state: AccountArchivedUM.Content, modifier: Modifier = Modifier) {
LazyColumn(modifier = modifier) {
LazyColumn(modifier = modifier.testTag(ArchivedAccountsScreenTestTags.ARCHIVED_ACCOUNTS_SCREEN_CONTAINER)) {
itemsIndexed(
items = state.accounts,
key = { index, item -> item.accountId },
@ -127,7 +129,8 @@ private fun ArchivedAccountRow(item: ArchivedAccountUM, modifier: Modifier = Mod
modifier = modifier
.fillMaxWidth()
.clickable(enabled = !item.isLoading, onClick = item.onClick)
.padding(all = TangemTheme.dimens.spacing12),
.padding(all = TangemTheme.dimens.spacing12)
.testTag(ArchivedAccountsScreenTestTags.ARCHIVED_ACCOUNT_ITEM),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
) {
@ -151,6 +154,7 @@ private fun ArchivedAccountRow(item: ArchivedAccountUM, modifier: Modifier = Mod
isLoading = item.isLoading,
onClick = item.onClick,
),
modifier = Modifier.testTag(ArchivedAccountsScreenTestTags.RESTORE_BUTTON),
)
}
}

View file

@ -21,6 +21,7 @@ import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
@ -40,6 +41,7 @@ import com.tangem.core.ui.components.fields.AutoSizeTextField
import com.tangem.core.ui.extensions.*
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.test.accounts.AccountInfoEditScreenTestTags
import com.tangem.core.ui.utils.rememberHideKeyboardNestedScrollConnection
import com.tangem.domain.models.account.CryptoPortfolioIcon
import com.tangem.features.account.createedit.entity.AccountCreateEditUM
@ -128,6 +130,8 @@ private fun AccountSummary(account: Account, isCreateMode: Boolean) {
name = account.name.value,
icon = account.portfolioIcon,
size = AccountIconSize.Large,
modifier = Modifier
.testTag(AccountInfoEditScreenTestTags.SELECTED_ICON),
)
Spacer(modifier = Modifier.height(24.dp))
@ -159,7 +163,9 @@ private fun AccountSummary(account: Account, isCreateMode: Boolean) {
account.onNameChange(newName)
},
textFieldModifier = Modifier.focusRequester(focusRequester),
textFieldModifier = Modifier
.focusRequester(focusRequester)
.testTag(AccountInfoEditScreenTestTags.NAME_FIELD),
)
SpacerH(20.dp)
}

View file

@ -32,7 +32,7 @@ import com.tangem.core.ui.extensions.stringReference
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.AccountDetailsScreenTestTags
import com.tangem.core.ui.test.accounts.AccountDetailsScreenTestTags
import com.tangem.features.account.details.entity.AccountDetailsUM
@Composable
@ -42,7 +42,8 @@ internal fun AccountDetailsContent(state: AccountDetailsUM, modifier: Modifier =
.background(color = TangemTheme.colors.background.secondary)
.fillMaxSize()
.imePadding()
.systemBarsPadding(),
.systemBarsPadding()
.testTag(AccountDetailsScreenTestTags.ACCOUNT_DETAILS_CONTAINER),
horizontalAlignment = Alignment.CenterHorizontally,
) {
AppBarWithBackButton(
@ -95,7 +96,8 @@ private fun ArchiveAccountRow(state: AccountDetailsUM.ArchiveMode.Available) {
.clip(RoundedCornerShape(TangemTheme.dimens.radius12))
.background(TangemTheme.colors.background.primary)
.clickable(enabled = !state.isLoading, onClick = state.onArchiveAccountClick)
.padding(all = TangemTheme.dimens.spacing12),
.padding(all = TangemTheme.dimens.spacing12)
.testTag(AccountDetailsScreenTestTags.ARCHIVE_ACCOUNT_BUTTON),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
) {
@ -160,7 +162,8 @@ private fun AccountRow(state: AccountDetailsUM) {
.clip(RoundedCornerShape(TangemTheme.dimens.radius12))
.background(TangemTheme.colors.background.primary)
.clickable(onClick = state.onAccountEditClick)
.padding(all = TangemTheme.dimens.spacing12),
.padding(all = TangemTheme.dimens.spacing12)
.testTag(AccountDetailsScreenTestTags.EDIT_ACCOUNT_BUTTON),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
) {