Updated on 2026-08-14
This commit is contained in:
parent
9b1bf5813f
commit
ef39279cb9
12 changed files with 187 additions and 20 deletions
|
|
@ -0,0 +1,25 @@
|
|||
package com.tangem.common.extensions
|
||||
|
||||
import io.github.kakaocup.compose.node.element.KNode
|
||||
|
||||
fun assertElementDoesNotExist(
|
||||
elementProvider: () -> KNode,
|
||||
elementDescription: String,
|
||||
) {
|
||||
try {
|
||||
elementProvider().assertExists()
|
||||
throw AssertionError("$elementDescription should not exist but was found")
|
||||
} catch (e: AssertionError) {
|
||||
val isNotFoundError = e.message?.let { message ->
|
||||
message.contains("No node found") ||
|
||||
message.contains("scrollable container") ||
|
||||
message.contains("There are no existing nodes") ||
|
||||
message.contains("There are no existing nodes for that selector")
|
||||
} ?: false
|
||||
if (isNotFoundError) {
|
||||
return
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,10 +7,7 @@ import androidx.compose.ui.test.hasAnyAncestor
|
|||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.common.extensions.hasLazyListItemPosition
|
||||
import com.tangem.common.utils.LazyListItemNode
|
||||
import com.tangem.core.ui.test.BaseButtonTestTags
|
||||
import com.tangem.core.ui.test.MainScreenTestTags
|
||||
import com.tangem.core.ui.test.NotificationTestTags
|
||||
import com.tangem.core.ui.test.TokenElementsTestTags
|
||||
import com.tangem.core.ui.test.*
|
||||
import com.tangem.core.ui.utils.LazyListItemPositionSemantics
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import io.github.kakaocup.compose.node.element.ComposeScreen
|
||||
|
|
@ -51,6 +48,45 @@ class MainScreenPageObject(semanticsProvider: SemanticsNodeInteractionsProvider)
|
|||
hasText(getResourceString(R.string.common_buy))
|
||||
}
|
||||
|
||||
val walletNameText: KNode = child {
|
||||
hasTestTag(MainScreenTestTags.CARD_TITLE)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val walletImage: KNode = child {
|
||||
hasTestTag(MainScreenTestTags.CARD_IMAGE)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val marketPriceBlock: KNode = child {
|
||||
hasTestTag(MarketPriceBlockTestTags.BLOCK)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val marketPriceText: KNode = child {
|
||||
hasTestTag(MarketPriceBlockTestTags.TEXT)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val transactionsExplorerIcon: KNode = child {
|
||||
hasTestTag(TransactionHistoryBlockTestTags.EXPLORER_ICON)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val transactionsTitle: KNode = child {
|
||||
hasTestTag(TransactionHistoryBlockTestTags.TITLE_TEXT)
|
||||
hasText(getResourceString(R.string.common_transactions))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
fun transactionsExplorer(): KNode {
|
||||
return child {
|
||||
hasTestTag(TransactionHistoryBlockTestTags.EXPLORER_TEXT)
|
||||
hasText(getResourceString(R.string.common_explorer))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
}
|
||||
|
||||
val notificationContainer: KNode = child {
|
||||
hasTestTag(NotificationTestTags.CONTAINER)
|
||||
useUnmergedTree = true
|
||||
|
|
@ -146,6 +182,14 @@ class MainScreenPageObject(semanticsProvider: SemanticsNodeInteractionsProvider)
|
|||
}
|
||||
}
|
||||
|
||||
fun organizeTokensButtonWithoutLazySearch(): KNode {
|
||||
return child {
|
||||
hasTestTag(MainScreenTestTags.ORGANIZE_TOKENS_BUTTON)
|
||||
hasText(getResourceString(R.string.organize_tokens_title))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
}
|
||||
|
||||
fun tokenNetworkGroupTitle(tokenNetwork: String): KNode {
|
||||
return lazyList.child {
|
||||
hasTestTag(MainScreenTestTags.TOKEN_LIST_ITEM)
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ 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.test.TokenElementsTestTags
|
||||
import com.tangem.core.ui.utils.LazyListItemPositionSemantics
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import io.github.kakaocup.compose.node.element.ComposeScreen
|
||||
|
|
@ -14,10 +14,10 @@ import io.github.kakaocup.compose.node.element.ComposeScreen.Companion.onCompose
|
|||
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
|
||||
import androidx.compose.ui.test.hasAnySibling as withAnySibling
|
||||
import androidx.compose.ui.test.hasTestTag as withTestTag
|
||||
import androidx.compose.ui.test.hasText as withText
|
||||
|
||||
class OrganizeTokensPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
|
||||
ComposeScreen<OrganizeTokensPageObject>(semanticsProvider = semanticsProvider) {
|
||||
|
|
@ -25,10 +25,12 @@ class OrganizeTokensPageObject(semanticsProvider: SemanticsNodeInteractionsProvi
|
|||
// region TopBar
|
||||
val title: KNode = child {
|
||||
hasText(getResourceString(R.string.organize_tokens_title))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
private val topBarGroupButton: KNode = child {
|
||||
hasTestTag(OrganizeTokensScreenTestTags.GROUP_BUTTON)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val groupButton: KNode = topBarGroupButton.child {
|
||||
|
|
@ -100,10 +102,14 @@ class OrganizeTokensPageObject(semanticsProvider: SemanticsNodeInteractionsProvi
|
|||
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))))
|
||||
)
|
||||
hasParent(
|
||||
withTestTag(TokenElementsTestTags.TOKEN_NON_FIAT_BLOCK)
|
||||
.and(
|
||||
withAnySibling(
|
||||
withTestTag(TokenElementsTestTags.TOKEN_TITLE)
|
||||
.and(withAnyChild(withText(tokenTitle)))
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,17 +4,17 @@ 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.core.ui.test.BaseButtonTestTags
|
||||
import com.tangem.common.utils.LazyListItemNode
|
||||
import com.tangem.core.ui.test.BaseButtonTestTags
|
||||
import com.tangem.core.ui.test.NotificationTestTags
|
||||
import com.tangem.core.ui.test.TokenDetailsScreenTestTags
|
||||
import com.tangem.features.tokendetails.impl.R
|
||||
import com.tangem.core.ui.utils.LazyListItemPositionSemantics
|
||||
import com.tangem.features.tokendetails.impl.R
|
||||
import io.github.kakaocup.compose.node.element.ComposeScreen
|
||||
import io.github.kakaocup.compose.node.element.ComposeScreen.Companion.onComposeScreen
|
||||
import io.github.kakaocup.compose.node.element.KNode
|
||||
import io.github.kakaocup.kakao.common.utilities.getResourceString
|
||||
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
|
||||
|
||||
class TokenDetailsPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
|
||||
|
|
@ -156,7 +156,6 @@ class TokenDetailsPageObject(semanticsProvider: SemanticsNodeInteractionsProvide
|
|||
hasText(getResourceString(R.string.common_buy_currency, feeCurrencySymbol))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal fun BaseTestCase.onTokenDetailsScreen(function: TokenDetailsPageObject.() -> Unit) =
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
package com.tangem.steps
|
||||
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.common.extensions.assertElementDoesNotExist
|
||||
import com.tangem.screens.onMainScreen
|
||||
import io.qameta.allure.kotlin.Allure.step
|
||||
|
||||
fun BaseTestCase.checkSingleCurrencyMainScreen(cardBlockchain: String, cardTitle: String) {
|
||||
step("Assert card title equal '$cardTitle'") {
|
||||
onMainScreen { walletNameText.assertTextEquals(cardTitle) }
|
||||
}
|
||||
step("Assert 'Transactions' block is displayed") {
|
||||
onMainScreen { transactionsExplorer().assertExists() }
|
||||
}
|
||||
step("Assert 'Transactions' title is displayer") {
|
||||
onMainScreen { transactionsTitle.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Explorer Icon' is displayed") {
|
||||
onMainScreen { transactionsExplorerIcon.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert card image is displayed") { //TODO: Придумать нормальную проверку / реализовать скриншот-тестинг
|
||||
onMainScreen { walletImage.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Market Price' on single card main screen is displayed") {
|
||||
onMainScreen { marketPriceBlock.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Market Price' title equals $cardBlockchain Market Price") {
|
||||
onMainScreen { marketPriceText.assertTextContains("$cardBlockchain Market Price") }
|
||||
}
|
||||
step("Assert 'Organize tokens' button is not displayed") {
|
||||
onMainScreen {
|
||||
assertElementDoesNotExist({ organizeTokensButtonWithoutLazySearch() }, "Organize tokens button")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package com.tangem.tests
|
||||
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.domain.models.scan.ProductType
|
||||
import com.tangem.scenarios.openMainScreen
|
||||
import com.tangem.steps.checkSingleCurrencyMainScreen
|
||||
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 SingleCurrencyCardsScan : BaseTestCase() {
|
||||
|
||||
@AllureId("868")
|
||||
@DisplayName("Scan: Scanning single-currency cards")
|
||||
@Test
|
||||
fun singleTokenNoteScanTest() {
|
||||
val cardBlockchain = "DOGE"
|
||||
val cardType: ProductType = ProductType.Note
|
||||
|
||||
setupHooks().run {
|
||||
step("Open 'Main Screen' on ${cardType.name} card") {
|
||||
openMainScreen(cardType)
|
||||
}
|
||||
step("Check 'Main' screen for ${cardType.name} $cardBlockchain card") {
|
||||
checkSingleCurrencyMainScreen(cardBlockchain = cardBlockchain, cardTitle = cardType.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.onSizeChanged
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
|
|
@ -20,6 +21,7 @@ import com.tangem.core.ui.components.RectangleShimmer
|
|||
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.MarketPriceBlockTestTags
|
||||
import com.tangem.utils.StringsSigns.DASH_SIGN
|
||||
|
||||
/**
|
||||
|
|
@ -45,7 +47,8 @@ fun MarketPriceBlock(state: MarketPriceBlockState, modifier: Modifier = Modifier
|
|||
.fillMaxWidth()
|
||||
.heightIn(min = TangemTheme.dimens.size72)
|
||||
.padding(all = TangemTheme.dimens.spacing12)
|
||||
.onSizeChanged { rootWidth = it.width },
|
||||
.onSizeChanged { rootWidth = it.width }
|
||||
.testTag(MarketPriceBlockTestTags.BLOCK),
|
||||
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4),
|
||||
horizontalAlignment = Alignment.Start,
|
||||
) {
|
||||
|
|
@ -64,6 +67,7 @@ private fun Title(currencyName: String, modifier: Modifier = Modifier) {
|
|||
text = stringResourceSafe(id = R.string.wallet_marketplace_block_title, currencyName),
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
modifier = Modifier.testTag(MarketPriceBlockTestTags.TEXT),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.tooling.preview.Preview
|
||||
import com.tangem.core.ui.R
|
||||
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.TransactionHistoryBlockTestTags
|
||||
|
||||
/**
|
||||
* Transactions block title
|
||||
|
|
@ -38,10 +40,13 @@ fun TxHistoryTitle(onExploreClick: () -> Unit, modifier: Modifier = Modifier) {
|
|||
text = stringResourceSafe(id = R.string.common_transactions),
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
modifier = Modifier.testTag(TransactionHistoryBlockTestTags.TITLE_TEXT),
|
||||
)
|
||||
|
||||
Row(
|
||||
modifier = Modifier.clickable(onClick = onExploreClick),
|
||||
modifier = Modifier
|
||||
.clickable(onClick = onExploreClick)
|
||||
.testTag(TransactionHistoryBlockTestTags.EXPLORER_ICON),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens.spacing2),
|
||||
) {
|
||||
|
|
@ -55,6 +60,7 @@ fun TxHistoryTitle(onExploreClick: () -> Unit, modifier: Modifier = Modifier) {
|
|||
text = stringResourceSafe(id = R.string.common_explorer),
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
modifier = Modifier.testTag(TransactionHistoryBlockTestTags.EXPLORER_TEXT),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ object MainScreenTestTags {
|
|||
const val WALLET_LIST_ITEM = "MAIN_SCREEN_WALLET_LIST_ITEM"
|
||||
const val ORGANIZE_TOKENS_BUTTON = "MAIN_SCREEN_ORGANIZE_TOKENS_BUTTON"
|
||||
const val MULTI_CURRENCY_ACTION_BUTTON = "MAIN_SCREEN_MULTI_CURRENCY_ACTION_BUTTON"
|
||||
const val CARD_TITLE = "MAIN_SCREEN_CARD_TITLE"
|
||||
const val CARD_IMAGE = "MAIN_SCREEN_CARD_IMAGE"
|
||||
|
||||
const val WALLET_BALANCE = "MAIN_SCREEN_WALLET_BALANCE"
|
||||
const val TOTAL_BALANCE_MENU_ITEM = "MAIN_SCREEN_TOTAL_BALANCE_MENU_ITEM"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
package com.tangem.core.ui.test
|
||||
|
||||
object MarketPriceBlockTestTags {
|
||||
const val BLOCK = "MAIN_SCREEN_MARKET_PRICE_BLOCK"
|
||||
const val TEXT = "MAIN_SCREEN_MARKET_PRICE_TEXT"
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.tangem.core.ui.test
|
||||
|
||||
object TransactionHistoryBlockTestTags {
|
||||
const val TITLE_TEXT = "TRANSACTION_HISTORY_TITLE_TEXT"
|
||||
const val EXPLORER_TEXT = "TRANSACTION_HISTORY_EXPLORER_TEXT"
|
||||
const val EXPLORER_ICON = "TRANSACTION_HISTORY_EXPLORER_ICON"
|
||||
}
|
||||
|
|
@ -261,7 +261,7 @@ private fun MenuItem(text: TextReference, imageVector: ImageVector, onClick: ()
|
|||
private fun TitleText(text: String, modifier: Modifier = Modifier) {
|
||||
Text(
|
||||
text = text,
|
||||
modifier = modifier,
|
||||
modifier = modifier.testTag(MainScreenTestTags.CARD_TITLE),
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
|
|
@ -375,7 +375,9 @@ private fun Image(@DrawableRes id: Int?, modifier: Modifier = Modifier) {
|
|||
Image(
|
||||
painter = painterResource(id = imageRes),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.width(width = TangemTheme.dimens.size120),
|
||||
modifier = Modifier
|
||||
.width(width = TangemTheme.dimens.size120)
|
||||
.testTag(MainScreenTestTags.CARD_IMAGE),
|
||||
contentScale = ContentScale.FillWidth,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue