Updated on 2026-08-14

This commit is contained in:
Tangem 2026-06-18 13:30:54 +03:00
parent ba3e7e4044
commit 58ac55c4ae
9 changed files with 26 additions and 20 deletions

View file

@ -62,6 +62,9 @@ When the user asks to **port** an iOS test to Android:
### Test class shape
- **Test method names are camelCase and always end with `Test`** (e.g. `groupTokensTest()`,
`renameWalletTest()`). Never use `snake_case` and never the unit-test `GIVEN … WHEN … THEN …`
backtick phrasing — that GWT convention is for JVM unit tests only, not instrumentation tests.
- **Scenario state setup goes in the test body**, not inside the open-the-feature helper. Each test
starts with explicit `step("Set WireMock scenario '$name' to '$state'") { setWireMockScenarioState(name, state) }`
calls, then calls a thin helper (e.g. `openTangemPay()`) that only opens the screen. Mirror the

View file

@ -323,6 +323,7 @@ fun BaseTestCase.switchFeeTokenAndApply(currentFeeToken: String, newFeeToken: St
}
}
step("Click on 'Apply' button") {
waitForIdle()
onSendFeeSelectorBottomSheet { applyButton.performClick() }
}
}

View file

@ -3,7 +3,6 @@ package com.tangem.screens
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
import com.tangem.common.BaseTestCase
import com.tangem.core.ui.R
import com.tangem.core.ui.test.AddFundsBottomSheetTestTags
import com.tangem.core.ui.test.BaseBottomSheetTestTags
import com.tangem.core.ui.test.BuyTokenScreenTestTags
import com.tangem.core.ui.test.MarketsTestTags
@ -38,7 +37,7 @@ class AddFundsBottomSheetPageObject(semanticsProvider: SemanticsNodeInteractions
}
val closeButton: KNode = child {
hasTestTag(AddFundsBottomSheetTestTags.CLOSE_BUTTON)
hasTestTag(BaseBottomSheetTestTags.CLOSE_BUTTON)
useUnmergedTree = true
}

View file

@ -189,6 +189,7 @@ class SwapTokenPageObject(semanticsProvider: SemanticsNodeInteractionsProvider)
val swapFiatAmount: KNode = child {
hasTestTag(SwapTokenScreenTestTags.SWAP_FIAT_AMOUNT)
useUnmergedTree = true
}
val swapSelectTokenIcon: KNode = child {

View file

@ -6,9 +6,9 @@ import com.tangem.common.constants.TestConstants.TANGEM_PAY_ELIGIBILITY_SCENARIO
import com.tangem.common.extensions.assertTextContainsSafe
import com.tangem.common.extensions.clickWithAssertion
import com.tangem.common.extensions.extractText
import com.tangem.common.extensions.pullToRefresh
import com.tangem.common.utils.assertClipboardTextEquals
import com.tangem.common.utils.resetWireMockScenarioState
import com.tangem.common.utils.resetWireMockScenarios
import com.tangem.common.utils.setWireMockScenarioState
import com.tangem.scenarios.*
import com.tangem.screens.tangempay.*
@ -23,7 +23,7 @@ class TangemPayTest : BaseTestCase() {
@AllureId("4549")
@DisplayName("Tangem Pay: change PIN code from card details")
@Test
fun changePin_SetsNewPinCode_FromCardDetails() {
fun changePinSetsNewPinCodeFromCardDetailsTest() {
val newPin = "5217"
val pinSetupScenario = "tangem_pay_pin_setup"
val pinNotSetState = "PinNotSet"
@ -31,6 +31,7 @@ class TangemPayTest : BaseTestCase() {
setupHooks(
additionalBeforeSection = {
resetWireMockScenarios()
setWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO, eligibilityState)
setWireMockScenarioState(pinSetupScenario, pinNotSetState)
},
@ -67,7 +68,7 @@ class TangemPayTest : BaseTestCase() {
@AllureId("4969")
@DisplayName("Tangem Pay: balance updates after transaction on payment account screen")
@Test
fun balanceUpdatesAfterTransaction_OnPaymentAccountScreen() {
fun balanceUpdatesAfterTransactionOnPaymentAccountScreenTest() {
val balanceScenario = "tangem_pay_balance_update"
val initialState = "InitialBalance"
val afterTransactionState = "AfterTransaction"
@ -75,6 +76,7 @@ class TangemPayTest : BaseTestCase() {
setupHooks(
additionalBeforeSection = {
resetWireMockScenarios()
setWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO, eligibilityState)
setWireMockScenarioState(balanceScenario, initialState)
},
@ -90,7 +92,7 @@ class TangemPayTest : BaseTestCase() {
step("Switch WireMock scenario '$balanceScenario' to '$afterTransactionState'") {
setWireMockScenarioState(balanceScenario, afterTransactionState)
}
step("Pull to refresh") { pullToRefresh() }
step("Pull to refresh") { pullToRefreshTangemPay() }
step("Assert updated balance contains '9'") {
onTangemPayMainScreen { balance.assertTextContainsSafe("9", substring = true) }
}
@ -100,7 +102,7 @@ class TangemPayTest : BaseTestCase() {
@AllureId("4970")
@DisplayName("Tangem Pay: new transaction appears after mocked charge")
@Test
fun transactionList_NewTransactionAppears_AfterMockedCharge() {
fun transactionListNewTransactionAppearsAfterMockedChargeTest() {
val historyScenario = "tangem_pay_transaction_history"
val initialState = "InitialEmpty"
val afterTransactionState = "AfterTransaction"
@ -109,6 +111,7 @@ class TangemPayTest : BaseTestCase() {
setupHooks(
additionalBeforeSection = {
resetWireMockScenarios()
setWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO, eligibilityState)
setWireMockScenarioState(historyScenario, initialState)
},
@ -126,7 +129,7 @@ class TangemPayTest : BaseTestCase() {
step("Switch WireMock scenario '$historyScenario' to '$afterTransactionState'") {
setWireMockScenarioState(historyScenario, afterTransactionState)
}
step("Pull to refresh") { pullToRefresh() }
step("Pull to refresh") { pullToRefreshTangemPay() }
step("Assert transaction from '$merchantName' is displayed") {
onTangemPayMainScreen {
transactionRowWithText(merchantName).assertIsDisplayed()
@ -138,12 +141,13 @@ class TangemPayTest : BaseTestCase() {
@AllureId("4974")
@DisplayName("Tangem Pay: reveal and copy card number, expiration and CVC")
@Test
fun revealAndCopyCardDetails_NumberExpirationCVC() {
fun revealAndCopyCardDetailsNumberExpirationCVCTest() {
val context = InstrumentationRegistry.getInstrumentation().targetContext
val eligibilityState = "PaeraCustomer"
setupHooks(
additionalBeforeSection = {
resetWireMockScenarios()
setWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO, eligibilityState)
},
additionalAfterSection = {
@ -200,13 +204,14 @@ class TangemPayTest : BaseTestCase() {
@AllureId("4971")
@DisplayName("Tangem Pay: freeze card via confirmation sheet")
@Test
fun freezeUnfreezeCard_TogglesCardState() {
fun freezeUnfreezeCardTogglesCardStateTest() {
val freezeScenario = "tangem_pay_card_freeze"
val startedState = "Started"
val eligibilityState = "PaeraCustomer"
setupHooks(
additionalBeforeSection = {
resetWireMockScenarios()
setWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO, eligibilityState)
setWireMockScenarioState(freezeScenario, startedState)
},

View file

@ -9,6 +9,7 @@ import com.tangem.common.constants.TestConstants.WAIT_UNTIL_TIMEOUT_VERY_LONG
import com.tangem.common.extensions.assertTextContainsSafe
import com.tangem.common.extensions.clickWithAssertion
import com.tangem.common.utils.resetWireMockScenarioState
import com.tangem.common.utils.resetWireMockScenarios
import com.tangem.common.utils.setWireMockScenarioState
import com.tangem.core.res.R as CoreResR
import com.tangem.scenarios.*
@ -26,7 +27,7 @@ class TangemPayTopUpTest : BaseTestCase() {
@AllureId("4973")
@DisplayName("Tangem Pay: top up swaps Bitcoin to USDC and appends deposit to history")
@Test
fun topUpFromTangemPay_SwapsBitcoinToUSDC_AppendsDepositToHistory() {
fun topUpFromTangemPaySwapsBitcoinToUSDCAppendsDepositToHistoryTest() {
val bitcoinScenario = "bitcoin_utxo"
val expressAssetsScenario = "express_api_assets"
val balanceScenario = "tangem_pay_balance_update"
@ -43,6 +44,7 @@ class TangemPayTopUpTest : BaseTestCase() {
setupHooks(
additionalBeforeSection = {
resetWireMockScenarios()
setWireMockScenarioState(TANGEM_PAY_ELIGIBILITY_SCENARIO, eligibilityState)
setWireMockScenarioState(bitcoinScenario, bitcoinBalanceState)
setWireMockScenarioState(expressAssetsScenario, expressAssetsState)

View file

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

View file

@ -21,7 +21,7 @@ import com.tangem.core.ui.ds.topbar.TangemTopBarType
import com.tangem.core.ui.ds2.button.TangemButton
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemeRedesign
import com.tangem.core.ui.test.AddFundsBottomSheetTestTags
import com.tangem.core.ui.test.BaseBottomSheetTestTags
import com.tangem.features.commonfeatures.api.addfunds.AddFundsComponent
import com.tangem.features.commonfeatures.api.choosetoken.ChooseTokenComponent
import com.tangem.features.commonfeatures.impl.addfunds.model.AddFundsModel
@ -201,7 +201,7 @@ internal class DefaultAddFundsComponent @AssistedInject constructor(
},
endContent = {
TangemButton(
modifier = Modifier.testTag(AddFundsBottomSheetTestTags.CLOSE_BUTTON),
modifier = Modifier.testTag(BaseBottomSheetTestTags.CLOSE_BUTTON),
iconStart = TangemIconUM.Icon(iconRes = CoreR.drawable.ic_close_24),
onClick = onCloseClick,
size = TangemButton.Size.X11,

View file

@ -177,7 +177,7 @@ private fun SimpleTransactionCardEmpty(
style = TangemTheme.typography.body2,
modifier = Modifier
.defaultMinSize(minHeight = TangemTheme.dimens.size20)
.testTag(SwapTokenScreenTestTags.SWAP_FIAT_AMOUNT),
.testTag(SwapTokenScreenTestTags.RECEIVE_FIAT_AMOUNT),
)
}
SecondarySmallButton(
@ -239,7 +239,7 @@ private fun SimpleTransactionCardLoading(modifier: Modifier = Modifier) {
style = TangemTheme.typography.body2,
modifier = Modifier
.defaultMinSize(minHeight = 20.dp, minWidth = 40.dp)
.testTag(SwapTokenScreenTestTags.SWAP_FIAT_AMOUNT),
.testTag(SwapTokenScreenTestTags.RECEIVE_FIAT_AMOUNT),
)
}
SecondarySmallButton(