Updated on 2026-08-14
This commit is contained in:
parent
b0b6081040
commit
e40706d5c6
11 changed files with 428 additions and 24 deletions
|
|
@ -0,0 +1,9 @@
|
|||
package com.tangem.common.extensions
|
||||
|
||||
import androidx.compose.ui.test.SemanticsMatcher
|
||||
import com.tangem.core.ui.utils.LazyListItemPositionSemantics
|
||||
import io.github.kakaocup.compose.node.builder.ViewBuilder
|
||||
|
||||
fun ViewBuilder.hasLazyListItemPosition(position: Int) = apply {
|
||||
addSemanticsMatcher(SemanticsMatcher.expectValue(LazyListItemPositionSemantics, position))
|
||||
}
|
||||
|
|
@ -4,7 +4,9 @@ import androidx.compose.ui.test.ExperimentalTestApi
|
|||
import androidx.compose.ui.test.SemanticsMatcher
|
||||
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.common.extensions.hasLazyListItemPosition
|
||||
import com.tangem.common.utils.LazyListItemNode
|
||||
import com.tangem.core.ui.test.TokenElementsTestTags
|
||||
import com.tangem.core.ui.test.MainScreenTestTags
|
||||
import com.tangem.core.ui.utils.LazyListItemPositionSemantics
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
|
|
@ -14,6 +16,7 @@ import io.github.kakaocup.compose.node.element.KNode
|
|||
import io.github.kakaocup.compose.node.element.lazylist.KLazyListNode
|
||||
import io.github.kakaocup.kakao.common.utilities.getResourceString
|
||||
import androidx.compose.ui.test.hasTestTag as withTestTag
|
||||
import androidx.compose.ui.test.hasText as withText
|
||||
|
||||
class MainScreenPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
|
||||
ComposeScreen<MainScreenPageObject>(semanticsProvider = semanticsProvider) {
|
||||
|
|
@ -45,7 +48,7 @@ class MainScreenPageObject(semanticsProvider: SemanticsNodeInteractionsProvider)
|
|||
hasTestTag(MainScreenTestTags.TOKEN_LIST_ITEM)
|
||||
hasText(tokenTitle)
|
||||
}.child<KNode> {
|
||||
hasTestTag(MainScreenTestTags.TOKEN_FIAT_AMOUNT)
|
||||
hasTestTag(TokenElementsTestTags.TOKEN_FIAT_AMOUNT)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
}
|
||||
|
|
@ -63,6 +66,37 @@ class MainScreenPageObject(semanticsProvider: SemanticsNodeInteractionsProvider)
|
|||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTestApi::class)
|
||||
fun organizeTokensButton(): KNode {
|
||||
return lazyList.childWith<LazyListItemNode> {
|
||||
hasTestTag(MainScreenTestTags.ORGANIZE_TOKENS_BUTTON)
|
||||
}.child<KNode> {
|
||||
hasText(getResourceString(R.string.organize_tokens_title))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
}
|
||||
|
||||
fun tokenNetworkGroupTitle(tokenNetwork: String): KNode {
|
||||
return lazyList.child {
|
||||
hasTestTag(MainScreenTestTags.TOKEN_LIST_ITEM)
|
||||
hasAnyChild(withText(tokenNetwork))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTestApi::class)
|
||||
fun tokenWithTitleAndPosition(tokenTitle: String, index: Int): KNode {
|
||||
return lazyList.childWith<LazyListItemNode> {
|
||||
hasTestTag(MainScreenTestTags.TOKEN_LIST_ITEM)
|
||||
hasText(tokenTitle)
|
||||
hasLazyListItemPosition(index)
|
||||
}.child<KNode> {
|
||||
hasTestTag(TokenElementsTestTags.TOKEN_TITLE)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This assertion is required to properly verify the token's absence in the semantic tree.
|
||||
* Tests will fail if assertIsNotDisplayed() or assertDoesNotExist() are used instead.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,113 @@
|
|||
package com.tangem.screens
|
||||
|
||||
import androidx.compose.ui.test.SemanticsMatcher
|
||||
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.common.extensions.hasLazyListItemPosition
|
||||
import com.tangem.common.utils.LazyListItemNode
|
||||
import com.tangem.core.ui.test.TokenElementsTestTags
|
||||
import com.tangem.core.ui.test.OrganizeTokensScreenTestTags
|
||||
import com.tangem.core.ui.utils.LazyListItemPositionSemantics
|
||||
import com.tangem.feature.wallet.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.compose.node.element.lazylist.KLazyListNode
|
||||
import io.github.kakaocup.kakao.common.utilities.getResourceString
|
||||
import androidx.compose.ui.test.hasText as withText
|
||||
import androidx.compose.ui.test.hasTestTag as withTestTag
|
||||
import androidx.compose.ui.test.hasAnySibling as withAnySibling
|
||||
import androidx.compose.ui.test.hasAnyChild as withAnyChild
|
||||
|
||||
class OrganizeTokensPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
|
||||
ComposeScreen<OrganizeTokensPageObject>(semanticsProvider = semanticsProvider) {
|
||||
|
||||
// region TopBar
|
||||
val title: KNode = child {
|
||||
hasText(getResourceString(R.string.organize_tokens_title))
|
||||
}
|
||||
|
||||
private val topBarGroupButton: KNode = child {
|
||||
hasTestTag(OrganizeTokensScreenTestTags.GROUP_BUTTON)
|
||||
}
|
||||
|
||||
val groupButton: KNode = topBarGroupButton.child {
|
||||
hasText(getResourceString(R.string.organize_tokens_group))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val ungroupButton: KNode = topBarGroupButton.child {
|
||||
hasText(getResourceString(R.string.organize_tokens_ungroup))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val sortByBalanceButton: KNode = child {
|
||||
hasTestTag(OrganizeTokensScreenTestTags.SORT_BY_BALANCE_BUTTON)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
// endregion TopBar
|
||||
|
||||
private val lazyList = KLazyListNode(
|
||||
semanticsProvider = semanticsProvider,
|
||||
viewBuilderAction = { hasTestTag(OrganizeTokensScreenTestTags.TOKENS_LAZY_LIST) },
|
||||
itemTypeBuilder = {
|
||||
itemType(::LazyListItemNode)
|
||||
},
|
||||
positionMatcher = { position ->
|
||||
SemanticsMatcher.expectValue(
|
||||
LazyListItemPositionSemantics,
|
||||
position
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
val applyButton: KNode = child {
|
||||
hasTestTag(OrganizeTokensScreenTestTags.APPLY_BUTTON)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val cancelButton: KNode = child {
|
||||
hasTestTag(OrganizeTokensScreenTestTags.CANCEL_BUTTON)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
fun tokenWithTitle(tokenTitle: String): KNode {
|
||||
return lazyList.child {
|
||||
hasTestTag(OrganizeTokensScreenTestTags.TOKEN_LIST_ITEM)
|
||||
hasAnyDescendant(withText(tokenTitle))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
}
|
||||
|
||||
fun tokenNetworkGroupTitle(tokenNetwork: String): KNode {
|
||||
return lazyList.child {
|
||||
hasTestTag(OrganizeTokensScreenTestTags.GROUP_TITLE_ITEM)
|
||||
hasAnyChild(withText(tokenNetwork))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
}
|
||||
|
||||
fun tokenWithTitleAndPosition(tokenTitle: String, index: Int): KNode {
|
||||
return lazyList.child {
|
||||
hasLazyListItemPosition(index)
|
||||
hasTestTag(OrganizeTokensScreenTestTags.TOKEN_LIST_ITEM)
|
||||
hasAnyDescendant(withText(tokenTitle))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
}
|
||||
|
||||
fun tokenDraggableButton(tokenTitle: String): KNode {
|
||||
return lazyList.child {
|
||||
hasTestTag(OrganizeTokensScreenTestTags.DRAGGABLE_IMAGE)
|
||||
useUnmergedTree = true
|
||||
hasParent(withTestTag(TokenElementsTestTags.TOKEN_NON_FIAT_BLOCK)
|
||||
.and(withAnySibling(withTestTag(TokenElementsTestTags.TOKEN_TITLE)
|
||||
.and(withAnyChild(withText(tokenTitle))))
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun BaseTestCase.onOrganizeTokensScreen(function: OrganizeTokensPageObject.() -> Unit) =
|
||||
onComposeScreen(composeTestRule, function)
|
||||
|
|
@ -0,0 +1,206 @@
|
|||
package com.tangem.tests
|
||||
|
||||
import androidx.compose.ui.test.onAllNodesWithText
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.common.extensions.clickWithAssertion
|
||||
import com.tangem.scenarios.OpenMainScreenScenario
|
||||
import com.tangem.screens.onMainScreen
|
||||
import com.tangem.screens.onOrganizeTokensScreen
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import io.qameta.allure.kotlin.AllureId
|
||||
import io.qameta.allure.kotlin.junit4.DisplayName
|
||||
import org.junit.Test
|
||||
|
||||
@HiltAndroidTest
|
||||
class OrganizeTokensTest : BaseTestCase() {
|
||||
|
||||
@AllureId("2755")
|
||||
@DisplayName("Organize tokens: group tokens")
|
||||
@Test
|
||||
fun groupTokensTest() {
|
||||
setupHooks().run {
|
||||
val tokenTitle = "Ethereum"
|
||||
val tokenNetwork = "Ethereum network"
|
||||
step("Open 'Main Screen'") {
|
||||
scenario(OpenMainScreenScenario(composeTestRule))
|
||||
}
|
||||
step("Click on 'Synchronize addresses' button" ) {
|
||||
onMainScreen { synchronizeAddressesButton.clickWithAssertion() }
|
||||
}
|
||||
step("Click 'Organize tokens' button") {
|
||||
onMainScreen { organizeTokensButton().clickWithAssertion() }
|
||||
}
|
||||
step("Assert 'Organize tokens' screen is opened") {
|
||||
onOrganizeTokensScreen {
|
||||
title.assertIsDisplayed()
|
||||
tokenWithTitle(tokenTitle).assertIsDisplayed()
|
||||
}
|
||||
}
|
||||
step("Click 'Group' button") {
|
||||
onOrganizeTokensScreen { groupButton.clickWithAssertion() }
|
||||
}
|
||||
step("Assert tokens were grouped on 'Organize tokens' screen") {
|
||||
onOrganizeTokensScreen { tokenNetworkGroupTitle(tokenNetwork).assertIsDisplayed() }
|
||||
}
|
||||
step("Click 'Apply' button") {
|
||||
onOrganizeTokensScreen { applyButton.clickWithAssertion() }
|
||||
}
|
||||
step("Assert tokens were grouped on 'Main screen'") {
|
||||
onMainScreen { tokenNetworkGroupTitle(tokenNetwork).assertIsDisplayed() }
|
||||
}
|
||||
step("Click 'Organize tokens' button") {
|
||||
onMainScreen { organizeTokensButton().clickWithAssertion() }
|
||||
}
|
||||
step("Assert 'Organize tokens' screen is opened") {
|
||||
onOrganizeTokensScreen {
|
||||
title.assertIsDisplayed()
|
||||
tokenWithTitle(tokenTitle).assertIsDisplayed()
|
||||
}
|
||||
}
|
||||
step("Click 'Ungroup' button") {
|
||||
onOrganizeTokensScreen { ungroupButton.clickWithAssertion() }
|
||||
}
|
||||
step("Assert tokens were ungrouped on 'Organize tokens' screen") {
|
||||
onOrganizeTokensScreen { tokenNetworkGroupTitle(tokenNetwork).assertIsNotDisplayed() }
|
||||
}
|
||||
step("Click 'Apply' button") {
|
||||
onOrganizeTokensScreen { applyButton.clickWithAssertion() }
|
||||
}
|
||||
step("Assert tokens were ungrouped on 'Main screen'") {
|
||||
onMainScreen { tokenNetworkGroupTitle(tokenNetwork).assertIsNotDisplayed() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AllureId("2752")
|
||||
@DisplayName("Organize tokens: check position of tokens")
|
||||
@Test
|
||||
fun checkPositionOfTokensTest() {
|
||||
setupHooks().run {
|
||||
val ethereumTitle = "Ethereum"
|
||||
val bitcoinTitle = "Bitcoin"
|
||||
step("Open 'Main Screen'") {
|
||||
scenario(OpenMainScreenScenario(composeTestRule))
|
||||
}
|
||||
step("Click on 'Synchronize addresses' button" ) {
|
||||
onMainScreen { synchronizeAddressesButton.clickWithAssertion() }
|
||||
}
|
||||
step("Check positions of tokens on 'Main Screen'") {
|
||||
onMainScreen {
|
||||
tokenWithTitleAndPosition(bitcoinTitle, 0).assertIsDisplayed()
|
||||
tokenWithTitleAndPosition(ethereumTitle, 1).assertIsDisplayed()
|
||||
}
|
||||
}
|
||||
step("Click 'Organize tokens' button") {
|
||||
onMainScreen { organizeTokensButton().clickWithAssertion() }
|
||||
}
|
||||
step("Check positions of tokens on 'Organize tokens' screen") {
|
||||
onOrganizeTokensScreen {
|
||||
tokenWithTitleAndPosition(bitcoinTitle, 1).assertIsDisplayed()
|
||||
tokenWithTitleAndPosition(ethereumTitle, 2).assertIsDisplayed()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AllureId("2753")
|
||||
@DisplayName("Organize tokens: check position of tokens")
|
||||
// toDo: on test build there is not ability to drag element
|
||||
// @Test
|
||||
fun checkCustomTokensOrderTest() {
|
||||
setupHooks().run {
|
||||
val ethereumTitle = "Ethereum"
|
||||
val bitcoinTitle = "Bitcoin"
|
||||
step("Open 'Main Screen'") {
|
||||
scenario(OpenMainScreenScenario(composeTestRule))
|
||||
}
|
||||
step("Click on 'Synchronize addresses' button" ) {
|
||||
onMainScreen { synchronizeAddressesButton.clickWithAssertion() }
|
||||
}
|
||||
step("Check positions of tokens on 'Main Screen'") {
|
||||
onMainScreen {
|
||||
tokenWithTitleAndPosition(bitcoinTitle, 0).assertIsDisplayed()
|
||||
tokenWithTitleAndPosition(ethereumTitle, 1).assertIsDisplayed()
|
||||
}
|
||||
}
|
||||
step("Click 'Organize tokens' button") {
|
||||
onMainScreen { organizeTokensButton().clickWithAssertion() }
|
||||
}
|
||||
step("Drag $bitcoinTitle down on 'Organize tokens' screen") {
|
||||
composeTestRule.waitUntil(timeoutMillis = 100_000) {
|
||||
composeTestRule.onAllNodesWithText("Data loaded").fetchSemanticsNodes().isNotEmpty()
|
||||
}
|
||||
onOrganizeTokensScreen {
|
||||
tokenWithTitleAndPosition(bitcoinTitle, 2).assertIsDisplayed()
|
||||
}
|
||||
}
|
||||
step("Click 'Apply' button") {
|
||||
onOrganizeTokensScreen { applyButton.clickWithAssertion() }
|
||||
}
|
||||
step("Check positions of tokens on 'Main Screen'") {
|
||||
onMainScreen {
|
||||
tokenWithTitleAndPosition(bitcoinTitle, 1).assertIsDisplayed()
|
||||
tokenWithTitleAndPosition(ethereumTitle, 0).assertIsDisplayed()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AllureId("2754")
|
||||
@DisplayName("Organize tokens: sort by balance")
|
||||
@Test
|
||||
fun checkSortByBalanceTest() {
|
||||
setupHooks().run {
|
||||
val ethereumTitle = "Ethereum"
|
||||
val bitcoinTitle = "Bitcoin"
|
||||
val polygonTitle = "Polygon"
|
||||
step("Open 'Main Screen'") {
|
||||
scenario(OpenMainScreenScenario(composeTestRule))
|
||||
}
|
||||
step("Click on 'Synchronize addresses' button" ) {
|
||||
onMainScreen { synchronizeAddressesButton.clickWithAssertion() }
|
||||
}
|
||||
step("Check positions of tokens on 'Main Screen'") {
|
||||
onMainScreen {
|
||||
tokenWithTitleAndPosition(bitcoinTitle, 0).assertIsDisplayed()
|
||||
tokenWithTitleAndPosition(ethereumTitle, 1).assertIsDisplayed()
|
||||
tokenWithTitleAndPosition(polygonTitle, 2).assertIsDisplayed()
|
||||
}
|
||||
}
|
||||
step("Click 'Organize tokens' button") {
|
||||
onMainScreen { organizeTokensButton().clickWithAssertion() }
|
||||
}
|
||||
step("Check positions of tokens on 'Organize tokens' screen") {
|
||||
onOrganizeTokensScreen {
|
||||
tokenWithTitleAndPosition(bitcoinTitle, 1).assertIsDisplayed()
|
||||
tokenWithTitleAndPosition(ethereumTitle, 2).assertIsDisplayed()
|
||||
tokenWithTitleAndPosition(polygonTitle, 3).assertIsDisplayed()
|
||||
}
|
||||
}
|
||||
step("Click 'By Balance' button") {
|
||||
onOrganizeTokensScreen {
|
||||
sortByBalanceButton.clickWithAssertion()
|
||||
}
|
||||
}
|
||||
step("Check positions of tokens by balance on 'Organize tokens' screen") {
|
||||
onOrganizeTokensScreen {
|
||||
tokenWithTitleAndPosition(ethereumTitle, 1).assertIsDisplayed()
|
||||
tokenWithTitleAndPosition(polygonTitle, 2).assertIsDisplayed()
|
||||
tokenWithTitleAndPosition(bitcoinTitle, 3).assertIsDisplayed()
|
||||
}
|
||||
}
|
||||
step("Click 'Apply' button") {
|
||||
onOrganizeTokensScreen { applyButton.clickWithAssertion() }
|
||||
}
|
||||
step("Check positions of tokens by balance on 'Organize tokens' screen") {
|
||||
onMainScreen {
|
||||
tokenWithTitleAndPosition(ethereumTitle, 0).assertIsDisplayed()
|
||||
tokenWithTitleAndPosition(polygonTitle, 1).assertIsDisplayed()
|
||||
tokenWithTitleAndPosition(bitcoinTitle, 2).assertIsDisplayed()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -31,7 +31,7 @@ import com.tangem.core.ui.extensions.stringReference
|
|||
import com.tangem.core.ui.res.TangemColorPalette
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.test.MainScreenTestTags
|
||||
import com.tangem.core.ui.test.TokenElementsTestTags
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import org.burnoutcrew.reorderable.ReorderableLazyListState
|
||||
import java.util.UUID
|
||||
|
|
@ -103,7 +103,7 @@ fun TokenItem(
|
|||
modifier = Modifier
|
||||
.layoutId(layoutId = LayoutId.ICON)
|
||||
.padding(end = TangemTheme.dimens.spacing8)
|
||||
.testTag(MainScreenTestTags.TOKEN_ICON),
|
||||
.testTag(TokenElementsTestTags.TOKEN_ICON),
|
||||
)
|
||||
|
||||
TokenTitle(
|
||||
|
|
@ -112,7 +112,7 @@ fun TokenItem(
|
|||
.layoutId(layoutId = LayoutId.TITLE)
|
||||
.padding(end = TangemTheme.dimens.spacing8)
|
||||
.padding(bottom = betweenRowsMargin)
|
||||
.testTag(MainScreenTestTags.TOKEN_TITLE),
|
||||
.testTag(TokenElementsTestTags.TOKEN_TITLE),
|
||||
)
|
||||
|
||||
TokenFiatAmount(
|
||||
|
|
@ -121,7 +121,7 @@ fun TokenItem(
|
|||
modifier = Modifier
|
||||
.layoutId(layoutId = LayoutId.FIAT_AMOUNT)
|
||||
.padding(bottom = betweenRowsMargin)
|
||||
.testTag(MainScreenTestTags.TOKEN_FIAT_AMOUNT),
|
||||
.testTag(TokenElementsTestTags.TOKEN_FIAT_AMOUNT),
|
||||
)
|
||||
|
||||
TokenPrice(
|
||||
|
|
@ -129,7 +129,7 @@ fun TokenItem(
|
|||
modifier = Modifier
|
||||
.layoutId(layoutId = LayoutId.CRYPTO_PRICE)
|
||||
.padding(end = TangemTheme.dimens.spacing8)
|
||||
.testTag(MainScreenTestTags.TOKEN_PRICE),
|
||||
.testTag(TokenElementsTestTags.TOKEN_PRICE),
|
||||
)
|
||||
|
||||
TokenCryptoAmount(
|
||||
|
|
@ -137,7 +137,7 @@ fun TokenItem(
|
|||
isBalanceHidden = isBalanceHidden,
|
||||
modifier = Modifier
|
||||
.layoutId(layoutId = LayoutId.CRYPTO_AMOUNT)
|
||||
.testTag(MainScreenTestTags.TOKEN_CRYPTO_AMOUNT),
|
||||
.testTag(TokenElementsTestTags.TOKEN_CRYPTO_AMOUNT),
|
||||
)
|
||||
|
||||
NonFiatContentBlock(
|
||||
|
|
@ -145,7 +145,7 @@ fun TokenItem(
|
|||
reorderableTokenListState = reorderableTokenListState,
|
||||
modifier = Modifier
|
||||
.layoutId(layoutId = LayoutId.NON_FIAT_CONTENT)
|
||||
.testTag(MainScreenTestTags.TOKEN_NO_ADDRESS),
|
||||
.testTag(TokenElementsTestTags.TOKEN_NON_FIAT_BLOCK),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,12 +9,14 @@ 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.res.painterResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.test.OrganizeTokensScreenTestTags
|
||||
import org.burnoutcrew.reorderable.ReorderableLazyListState
|
||||
import org.burnoutcrew.reorderable.detectReorder
|
||||
|
||||
|
|
@ -53,7 +55,8 @@ private fun DraggableImage(reorderableTokenListState: ReorderableLazyListState?)
|
|||
} else {
|
||||
Modifier
|
||||
},
|
||||
),
|
||||
)
|
||||
.testTag(OrganizeTokensScreenTestTags.DRAGGABLE_IMAGE),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Icon(
|
||||
|
|
|
|||
|
|
@ -5,12 +5,7 @@ object MainScreenTestTags {
|
|||
const val MORE_BUTTON = "MAIN_SCREEN_MORE_BUTTON"
|
||||
const val TOP_BAR = "MAIN_SCREEN_TOP_BAR"
|
||||
const val TOKEN_LIST_ITEM = "MAIN_SCREEN_TOKEN_LIST_ITEM"
|
||||
const val TOKEN_TITLE = "MAIN_SCREEN_TOKEN_TITLE"
|
||||
const val TOKEN_ICON = "MAIN_SCREEN_TOKEN_ICON"
|
||||
const val TOKEN_PRICE = "MAIN_SCREEN_TOKEN_PRICE"
|
||||
const val TOKEN_FIAT_AMOUNT = "MAIN_SCREEN_TOKEN_FIAT_AMOUNT"
|
||||
const val TOKEN_CRYPTO_AMOUNT = "MAIN_SCREEN_TOKEN_CRYPTO_AMOUNT"
|
||||
const val TOKEN_NO_ADDRESS = "MAIN_SCREEN_TOKEN_NO_ADDRESS"
|
||||
const val WALLET_BALANCE = "MAIN_SCREEN_WALLET_BALANCE"
|
||||
const val WALLET_LIST_ITEM = "MAIN_SCREEN_WALLET_LIST_ITEM"
|
||||
const val ORGANIZE_TOKENS_BUTTON = "MAIN_SCREEN_ORGANIZE_TOKENS_BUTTON"
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.tangem.core.ui.test
|
||||
|
||||
object OrganizeTokensScreenTestTags {
|
||||
// region OrganizeTokensTopBar
|
||||
const val GROUP_BUTTON = "ORGANIZE_TOKENS_GROUP_BUTTON"
|
||||
const val SORT_BY_BALANCE_BUTTON = "SORT_BY_BALANCE_BUTTON"
|
||||
// endregion OrganizeTokensTopBar
|
||||
|
||||
const val TOKENS_LAZY_LIST = "ORGANIZE_TOKENS_TOKENS_LAZY_LIST"
|
||||
const val TOKEN_LIST_ITEM = "ORGANIZE_TOKENS_TOKEN_LIST_ITEM"
|
||||
const val GROUP_TITLE_ITEM = "ORGANIZE_TOKENS_GROUP_TITLE_ITEM"
|
||||
const val DRAGGABLE_IMAGE = "ORGANIZE_TOKENS_DRAGGABLE_IMAGE"
|
||||
|
||||
const val APPLY_BUTTON = "ORGANIZE_TOKENS_APPLY_BUTTON"
|
||||
const val CANCEL_BUTTON = "ORGANIZE_TOKENS_CANCEL_BUTTON"
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.tangem.core.ui.test
|
||||
|
||||
object TokenElementsTestTags {
|
||||
const val TOKEN_TITLE = "TOKEN_TITLE"
|
||||
const val TOKEN_ICON = "TOKEN_ICON"
|
||||
const val TOKEN_PRICE = "TOKEN_PRICE"
|
||||
const val TOKEN_FIAT_AMOUNT = "TOKEN_FIAT_AMOUNT"
|
||||
const val TOKEN_CRYPTO_AMOUNT = "TOKEN_CRYPTO_AMOUNT"
|
||||
const val TOKEN_NON_FIAT_BLOCK = "TOKEN_NON_FIAT_BLOCK"
|
||||
}
|
||||
|
|
@ -20,6 +20,8 @@ import androidx.compose.ui.graphics.Shape
|
|||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
||||
|
|
@ -38,7 +40,9 @@ import com.tangem.core.ui.extensions.stringResourceSafe
|
|||
import com.tangem.core.ui.reordarable.ReorderableItem
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.test.OrganizeTokensScreenTestTags
|
||||
import com.tangem.core.ui.utils.WindowInsetsZero
|
||||
import com.tangem.core.ui.utils.lazyListItemPosition
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
|
||||
|
|
@ -122,7 +126,8 @@ private fun TokenList(
|
|||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopCenter)
|
||||
.reorderable(reorderableListState),
|
||||
.reorderable(reorderableListState)
|
||||
.testTag(OrganizeTokensScreenTestTags.TOKENS_LAZY_LIST),
|
||||
state = reorderableListState.listState,
|
||||
contentPadding = listContentPadding,
|
||||
) {
|
||||
|
|
@ -173,16 +178,18 @@ private fun LazyItemScope.DraggableItem(
|
|||
) { isItemDragging ->
|
||||
isDragging = isItemDragging
|
||||
|
||||
val modifierWithBackground = itemModifier.background(color = TangemTheme.colors.background.primary)
|
||||
val modifierWithBackground = itemModifier
|
||||
.background(color = TangemTheme.colors.background.primary)
|
||||
.semantics { lazyListItemPosition = index }
|
||||
|
||||
when (item) {
|
||||
is DraggableItem.GroupHeader -> DraggableGroupTitleItem(
|
||||
state = item.groupTitle,
|
||||
reorderableTokenListState = reorderableState,
|
||||
modifier = modifierWithBackground,
|
||||
modifier = modifierWithBackground.testTag(OrganizeTokensScreenTestTags.GROUP_TITLE_ITEM),
|
||||
)
|
||||
is DraggableItem.Token -> TokenItem(
|
||||
modifier = modifierWithBackground,
|
||||
modifier = modifierWithBackground.testTag(OrganizeTokensScreenTestTags.TOKEN_LIST_ITEM),
|
||||
state = item.tokenItemState,
|
||||
reorderableTokenListState = reorderableState,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
|
|
@ -201,6 +208,7 @@ private fun LazyItemScope.DraggableItem(
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
private fun TopBar(
|
||||
config: OrganizeTokensState.HeaderConfig,
|
||||
|
|
@ -246,7 +254,9 @@ private fun TopBar(
|
|||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
|
||||
) {
|
||||
RoundedActionButton(
|
||||
modifier = Modifier.weight(1f),
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.testTag(OrganizeTokensScreenTestTags.SORT_BY_BALANCE_BUTTON),
|
||||
config = ActionButtonConfig(
|
||||
text = TextReference.Res(id = R.string.organize_tokens_sort_by_balance),
|
||||
iconResId = R.drawable.ic_sort_24,
|
||||
|
|
@ -257,7 +267,9 @@ private fun TopBar(
|
|||
color = TangemTheme.colors.background.primary,
|
||||
)
|
||||
RoundedActionButton(
|
||||
modifier = Modifier.weight(1f),
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.testTag(OrganizeTokensScreenTestTags.GROUP_BUTTON),
|
||||
config = ActionButtonConfig(
|
||||
text = TextReference.Res(
|
||||
id = if (config.isGrouped) {
|
||||
|
|
@ -286,12 +298,16 @@ private fun Actions(config: OrganizeTokensState.ActionsConfig, modifier: Modifie
|
|||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
SecondaryButton(
|
||||
modifier = Modifier.weight(1f),
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.testTag(OrganizeTokensScreenTestTags.CANCEL_BUTTON),
|
||||
text = stringResourceSafe(id = R.string.common_cancel),
|
||||
onClick = config.onCancelClick,
|
||||
)
|
||||
PrimaryButton(
|
||||
modifier = Modifier.weight(1f),
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.testTag(OrganizeTokensScreenTestTags.APPLY_BUTTON),
|
||||
text = stringResourceSafe(id = R.string.common_apply),
|
||||
onClick = config.onApplyClick,
|
||||
showProgress = config.showApplyProgress,
|
||||
|
|
|
|||
|
|
@ -2,9 +2,11 @@ package com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrenc
|
|||
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import com.tangem.core.ui.components.buttons.actions.ActionButtonConfig
|
||||
import com.tangem.core.ui.components.buttons.actions.RoundedActionButton
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.test.MainScreenTestTags
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
|
||||
private const val ORGANIZE_BUTTON_CONTENT_TYPE = "OrganizeTokensButton"
|
||||
|
|
@ -24,7 +26,7 @@ internal fun LazyListScope.organizeTokensButton(
|
|||
) {
|
||||
item(key = ORGANIZE_BUTTON_CONTENT_TYPE, contentType = ORGANIZE_BUTTON_CONTENT_TYPE) {
|
||||
RoundedActionButton(
|
||||
modifier = modifier,
|
||||
modifier = modifier.testTag(MainScreenTestTags.ORGANIZE_TOKENS_BUTTON),
|
||||
config = ActionButtonConfig(
|
||||
text = resourceReference(id = R.string.organize_tokens_title),
|
||||
iconResId = R.drawable.ic_filter_24,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue