Updated on 2026-08-14
This commit is contained in:
commit
8c84593e15
11 changed files with 286 additions and 27 deletions
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.tangem.common.extensions
|
||||||
|
|
||||||
|
import androidx.compose.ui.test.hasTestTag
|
||||||
|
import androidx.compose.ui.test.performClick
|
||||||
|
import com.tangem.common.BaseTestCase
|
||||||
|
import com.tangem.core.ui.test.AppSettingsScreenTestTags
|
||||||
|
import com.tangem.core.ui.test.TokenDetailsTopBarTestTags
|
||||||
|
import com.tangem.core.ui.test.TopAppBarTestTags
|
||||||
|
import com.tangem.core.ui.test.TopNavigationTestTags
|
||||||
|
|
||||||
|
fun BaseTestCase.tapBackButton() {
|
||||||
|
waitForIdle()
|
||||||
|
composeTestRule.onNode(
|
||||||
|
hasTestTag(TopNavigationTestTags.BACK_BUTTON)
|
||||||
|
or hasTestTag(TopAppBarTestTags.CLOSE_BUTTON)
|
||||||
|
or hasTestTag(TokenDetailsTopBarTestTags.BACK_BUTTON)
|
||||||
|
or hasTestTag(AppSettingsScreenTestTags.BACK_BUTTON),
|
||||||
|
useUnmergedTree = true,
|
||||||
|
).performClick()
|
||||||
|
}
|
||||||
|
|
@ -42,6 +42,17 @@ object AddressComparisonHelper {
|
||||||
assertTrue(report, false)
|
assertTrue(report, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun derivationPathForBlockchain(json: String, blockchain: String): String {
|
||||||
|
val array = JSONArray(json)
|
||||||
|
for (i in 0 until array.length()) {
|
||||||
|
val entry = array.getJSONObject(i)
|
||||||
|
if (entry.getString("blockchain").equals(blockchain, ignoreCase = true)) {
|
||||||
|
return entry.getString("derivationPath").trim()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error("No entry with blockchain '$blockchain' found in addresses JSON")
|
||||||
|
}
|
||||||
|
|
||||||
private fun parseAndNormalize(json: String): List<AddressEntry> {
|
private fun parseAndNormalize(json: String): List<AddressEntry> {
|
||||||
val array = JSONArray(json)
|
val array = JSONArray(json)
|
||||||
val entries = mutableListOf<AddressEntry>()
|
val entries = mutableListOf<AddressEntry>()
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package com.tangem.scenarios
|
package com.tangem.scenarios
|
||||||
|
|
||||||
import android.view.KeyEvent
|
|
||||||
import androidx.test.core.app.ApplicationProvider
|
import androidx.test.core.app.ApplicationProvider
|
||||||
import com.tangem.common.BaseTestCase
|
import com.tangem.common.BaseTestCase
|
||||||
import com.tangem.common.constants.TestConstants.WAIT_UNTIL_TIMEOUT_VERY_LONG
|
import com.tangem.common.constants.TestConstants.WAIT_UNTIL_TIMEOUT_VERY_LONG
|
||||||
|
|
@ -57,31 +56,6 @@ fun BaseTestCase.verifyAddresses(seedPhrase: String, apiAddressesJson: String) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private const val TESTER_MENU_MAX_ATTEMPTS = 3
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Presses 'Volume Down' twice to open tester menu.
|
|
||||||
* Retries up to [TESTER_MENU_MAX_ATTEMPTS] times if the menu doesn't appear.
|
|
||||||
*/
|
|
||||||
private fun BaseTestCase.openTesterMenu() {
|
|
||||||
repeat(TESTER_MENU_MAX_ATTEMPTS) { attempt ->
|
|
||||||
waitForIdle()
|
|
||||||
device.uiDevice.pressKeyCode(KeyEvent.KEYCODE_VOLUME_DOWN)
|
|
||||||
device.uiDevice.pressKeyCode(KeyEvent.KEYCODE_VOLUME_DOWN)
|
|
||||||
|
|
||||||
val opened = runCatching {
|
|
||||||
onTesterMenuScreen { addressesInfoButton.assertIsDisplayed() }
|
|
||||||
}.isSuccess
|
|
||||||
|
|
||||||
if (opened) {
|
|
||||||
TangemLogger.i("Tester menu opened on attempt ${attempt + 1}")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
TangemLogger.w("Tester menu not opened on attempt ${attempt + 1}, retrying...")
|
|
||||||
}
|
|
||||||
error("Failed to open tester menu after $TESTER_MENU_MAX_ATTEMPTS attempts")
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Polls [walletManagersStore] until the wallet manager count stops growing for [WALLET_MANAGERS_SETTLE_MS].
|
* Polls [walletManagersStore] until the wallet manager count stops growing for [WALLET_MANAGERS_SETTLE_MS].
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.tangem.scenarios
|
||||||
|
|
||||||
|
import com.tangem.common.BaseTestCase
|
||||||
|
import com.tangem.common.extensions.clickWithAssertion
|
||||||
|
import com.tangem.screens.onDetailsScreen
|
||||||
|
import com.tangem.screens.onMainScreenTopBar
|
||||||
|
import com.tangem.screens.onReferralProgramScreen
|
||||||
|
import com.tangem.screens.onWalletSettingsScreen
|
||||||
|
import io.qameta.allure.kotlin.Allure.step
|
||||||
|
|
||||||
|
fun BaseTestCase.referralTakeParticipate() {
|
||||||
|
step("Open 'Details' screen") {
|
||||||
|
onMainScreenTopBar { moreButton.clickWithAssertion() }
|
||||||
|
}
|
||||||
|
step("Open 'Wallet settings' screen") {
|
||||||
|
onDetailsScreen { walletNameButton.clickWithAssertion() }
|
||||||
|
}
|
||||||
|
step("Open 'Referral program' screen") {
|
||||||
|
onWalletSettingsScreen { referralProgramButton.clickWithAssertion() }
|
||||||
|
}
|
||||||
|
step("Tap 'Participate'") {
|
||||||
|
onReferralProgramScreen { participateButton.clickWithAssertion() }
|
||||||
|
}
|
||||||
|
step("Verify referral code is displayed") {
|
||||||
|
onReferralProgramScreen { personalCodeCard.assertIsDisplayed() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.tangem.scenarios
|
||||||
|
|
||||||
|
import android.view.KeyEvent
|
||||||
|
import com.tangem.common.BaseTestCase
|
||||||
|
import com.tangem.screens.onTesterMenuScreen
|
||||||
|
import com.tangem.utils.logging.TangemLogger
|
||||||
|
|
||||||
|
private const val TESTER_MENU_MAX_ATTEMPTS = 3
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the tester menu by sending two 'Volume Down' key events in a single shell command.
|
||||||
|
* VolumeButtonDoublePressObserver needs two ACTION_DOWN within 300ms; two separate pressKeyCode
|
||||||
|
* calls are too slow, but both events in one `input keyevent` invocation arrive back-to-back within
|
||||||
|
* the window. Retries up to [TESTER_MENU_MAX_ATTEMPTS] times if it doesn't appear.
|
||||||
|
*/
|
||||||
|
fun BaseTestCase.openTesterMenu() {
|
||||||
|
repeat(TESTER_MENU_MAX_ATTEMPTS) { attempt ->
|
||||||
|
waitForIdle()
|
||||||
|
val volumeDown = KeyEvent.KEYCODE_VOLUME_DOWN
|
||||||
|
device.uiDevice.executeShellCommand("input keyevent $volumeDown $volumeDown")
|
||||||
|
|
||||||
|
val opened = runCatching {
|
||||||
|
onTesterMenuScreen { addressesInfoButton.assertIsDisplayed() }
|
||||||
|
}.isSuccess
|
||||||
|
|
||||||
|
if (opened) {
|
||||||
|
TangemLogger.i("Tester menu opened on attempt ${attempt + 1}")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
TangemLogger.w("Tester menu not opened on attempt ${attempt + 1}, retrying...")
|
||||||
|
}
|
||||||
|
error("Failed to open tester menu after $TESTER_MENU_MAX_ATTEMPTS attempts")
|
||||||
|
}
|
||||||
|
|
@ -78,6 +78,11 @@ class ReferralProgramPageObject(semanticsProvider: SemanticsNodeInteractionsProv
|
||||||
hasTestTag(BaseButtonTestTags.TEXT)
|
hasTestTag(BaseButtonTestTags.TEXT)
|
||||||
useUnmergedTree = true
|
useUnmergedTree = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val personalCodeCard: KNode = child {
|
||||||
|
hasTestTag(ReferralProgramScreenTestTags.PERSONAL_CODE_CARD)
|
||||||
|
useUnmergedTree = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun BaseTestCase.onReferralProgramScreen(function: ReferralProgramPageObject.() -> Unit) =
|
internal fun BaseTestCase.onReferralProgramScreen(function: ReferralProgramPageObject.() -> Unit) =
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,178 @@
|
||||||
|
package com.tangem.tests.referral
|
||||||
|
|
||||||
|
import androidx.test.core.app.ApplicationProvider
|
||||||
|
import com.tangem.common.BaseTestCase
|
||||||
|
import com.tangem.common.extensions.clickWithAssertion
|
||||||
|
import com.tangem.common.extensions.tapBackButton
|
||||||
|
import com.tangem.common.utils.AddressComparisonHelper
|
||||||
|
import com.tangem.common.utils.getClipboardText
|
||||||
|
import com.tangem.common.utils.resetWireMockScenarios
|
||||||
|
import com.tangem.common.utils.setWireMockScenarioState
|
||||||
|
import com.tangem.domain.models.scan.ProductType
|
||||||
|
import com.tangem.scenarios.openMainScreen
|
||||||
|
import com.tangem.scenarios.openTesterMenu
|
||||||
|
import com.tangem.scenarios.referralTakeParticipate
|
||||||
|
import com.tangem.scenarios.synchronizeAddresses
|
||||||
|
import com.tangem.screens.onDetailsScreen
|
||||||
|
import com.tangem.screens.onMainScreen
|
||||||
|
import com.tangem.screens.onMainScreenTopBar
|
||||||
|
import com.tangem.screens.onTesterMenuScreen
|
||||||
|
import com.tangem.screens.onWalletSettingsScreen
|
||||||
|
import dagger.hilt.android.testing.HiltAndroidTest
|
||||||
|
import io.qameta.allure.kotlin.AllureId
|
||||||
|
import io.qameta.allure.kotlin.junit4.DisplayName
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
@HiltAndroidTest
|
||||||
|
class ReferralTest : BaseTestCase() {
|
||||||
|
|
||||||
|
@AllureId("3630")
|
||||||
|
@DisplayName("Referral program: Token and Blockchain added on Main screen after participation")
|
||||||
|
@Test
|
||||||
|
fun referralTokenAndBlockchainAddedAfterParticipationTest() {
|
||||||
|
val tokenNetwork = "Tron"
|
||||||
|
val token = "Tether"
|
||||||
|
|
||||||
|
setupHooks(
|
||||||
|
additionalAfterSection = {
|
||||||
|
resetWireMockScenarios()
|
||||||
|
}
|
||||||
|
).run {
|
||||||
|
step("Open 'Main' screen") {
|
||||||
|
openMainScreen()
|
||||||
|
}
|
||||||
|
step("Synchronize addresses") {
|
||||||
|
synchronizeAddresses()
|
||||||
|
}
|
||||||
|
step("Verify network $tokenNetwork and token $token is not displaying") {
|
||||||
|
onMainScreen {
|
||||||
|
assertTokenDoesNotExist(tokenNetwork)
|
||||||
|
assertTokenDoesNotExist(token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
step("Take participate in Referral program") {
|
||||||
|
referralTakeParticipate()
|
||||||
|
}
|
||||||
|
step("Return to the 'Main' screen") {
|
||||||
|
tapBackButton()
|
||||||
|
onWalletSettingsScreen { screenContainer.assertIsDisplayed() }
|
||||||
|
tapBackButton()
|
||||||
|
onDetailsScreen { screenContainer.assertIsDisplayed() }
|
||||||
|
tapBackButton()
|
||||||
|
onMainScreen { screenContainer.assertIsDisplayed() }
|
||||||
|
}
|
||||||
|
step("Verify network $tokenNetwork and token $token is displayed on 'Main' screen") {
|
||||||
|
onMainScreen {
|
||||||
|
tokenWithTitleAndAddress(tokenNetwork)
|
||||||
|
tokenWithTitleAndAddress(token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AllureId("10098")
|
||||||
|
@DisplayName("Referral program: Token added on Main screen after participation")
|
||||||
|
@Test
|
||||||
|
fun referralTokenAddedAfterParticipationTest() {
|
||||||
|
val userWalletScenarioName = "user_tokens_api"
|
||||||
|
val userWalletState = "Tron"
|
||||||
|
val tokenNetwork = "Tron"
|
||||||
|
val token = "Tether"
|
||||||
|
|
||||||
|
setupHooks(
|
||||||
|
additionalAfterSection = {
|
||||||
|
resetWireMockScenarios()
|
||||||
|
}
|
||||||
|
).run {
|
||||||
|
step("Set wiremock scenario: $userWalletScenarioName to state $userWalletState") {
|
||||||
|
setWireMockScenarioState(scenarioName = userWalletScenarioName, state = userWalletState)
|
||||||
|
}
|
||||||
|
step("Open 'Main' screen") {
|
||||||
|
openMainScreen()
|
||||||
|
}
|
||||||
|
step("Synchronize addresses") {
|
||||||
|
synchronizeAddresses()
|
||||||
|
}
|
||||||
|
step("Verify token $token is not displaying") {
|
||||||
|
onMainScreen { assertTokenDoesNotExist(token) }
|
||||||
|
}
|
||||||
|
step("Verify network $tokenNetwork is displaying") {
|
||||||
|
onMainScreen { tokenWithTitleAndAddress(tokenNetwork) }
|
||||||
|
}
|
||||||
|
step("Take participate in Referral program") {
|
||||||
|
referralTakeParticipate()
|
||||||
|
}
|
||||||
|
step("Return to the 'Main' screen") {
|
||||||
|
tapBackButton()
|
||||||
|
onWalletSettingsScreen { screenContainer.assertIsDisplayed() }
|
||||||
|
tapBackButton()
|
||||||
|
onDetailsScreen { screenContainer.assertIsDisplayed() }
|
||||||
|
tapBackButton()
|
||||||
|
onMainScreen { screenContainer.assertIsDisplayed() }
|
||||||
|
}
|
||||||
|
step("Verify $token is displayed on 'Main' screen") {
|
||||||
|
onMainScreen { tokenWithTitleAndAddress(token) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AllureId("3629")
|
||||||
|
@DisplayName("Referral program: Participating unavailable for No-Wallet cards")
|
||||||
|
@Test
|
||||||
|
fun referralUnavailableForNoWalletCardsTest() {
|
||||||
|
setupHooks().run {
|
||||||
|
step("Open 'Main' screen") {
|
||||||
|
openMainScreen(productType = ProductType.Note)
|
||||||
|
}
|
||||||
|
step("Open 'Details' screen") {
|
||||||
|
onMainScreenTopBar { moreButton.clickWithAssertion() }
|
||||||
|
}
|
||||||
|
step("Open 'Wallet settings' screen") {
|
||||||
|
onDetailsScreen { walletNameButton.clickWithAssertion() }
|
||||||
|
}
|
||||||
|
step("Verify 'Referral program' button does not displaying") {
|
||||||
|
onWalletSettingsScreen { referralProgramButton.assertDoesNotExist() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AllureId("3636")
|
||||||
|
@DisplayName("Referral program: Verify wallet derivation")
|
||||||
|
@Test
|
||||||
|
fun referralVerifyWalletDerivationTest() {
|
||||||
|
val tokenNetwork = "Tron"
|
||||||
|
val expectedDerivationPath = "m/44'/195'/0'/0/0"
|
||||||
|
|
||||||
|
setupHooks(
|
||||||
|
additionalAfterSection = {
|
||||||
|
resetWireMockScenarios()
|
||||||
|
}
|
||||||
|
).run {
|
||||||
|
step("Open 'Main' screen") {
|
||||||
|
openMainScreen()
|
||||||
|
}
|
||||||
|
step("Synchronize addresses") {
|
||||||
|
synchronizeAddresses()
|
||||||
|
}
|
||||||
|
step("Take participate in Referral program") {
|
||||||
|
referralTakeParticipate()
|
||||||
|
}
|
||||||
|
step("Open Debug menu") {
|
||||||
|
openTesterMenu()
|
||||||
|
}
|
||||||
|
step("Open 'Addresses info' screen") {
|
||||||
|
onTesterMenuScreen { addressesInfoButton.clickWithAssertion() }
|
||||||
|
}
|
||||||
|
step("Verify $tokenNetwork derivation path is '$expectedDerivationPath'") {
|
||||||
|
onTesterMenuScreen { jsonTab.clickWithAssertion() }
|
||||||
|
onTesterMenuScreen { copyButton.clickWithAssertion() }
|
||||||
|
val addressesJson = getClipboardText(ApplicationProvider.getApplicationContext())
|
||||||
|
?: error("Clipboard is empty after copying addresses")
|
||||||
|
val actualDerivationPath =
|
||||||
|
AddressComparisonHelper.derivationPathForBlockchain(addressesJson, tokenNetwork)
|
||||||
|
assertEquals(expectedDerivationPath, actualDerivationPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,16 +3,18 @@ package com.tangem.core.ui.ds2.button
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.NonRestartableComposable
|
import androidx.compose.runtime.NonRestartableComposable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.testTag
|
||||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||||
import com.tangem.core.ui.res.generated.icons.Icons
|
import com.tangem.core.ui.res.generated.icons.Icons
|
||||||
import com.tangem.core.ui.res.generated.icons.ic_arrow_left_20
|
import com.tangem.core.ui.res.generated.icons.ic_arrow_left_20
|
||||||
import com.tangem.core.ui.res.generated.icons.ic_cross_20
|
import com.tangem.core.ui.res.generated.icons.ic_cross_20
|
||||||
|
import com.tangem.core.ui.test.TopNavigationTestTags
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@NonRestartableComposable
|
@NonRestartableComposable
|
||||||
fun TangemButton.Back(modifier: Modifier = Modifier, onClick: () -> Unit) {
|
fun TangemButton.Back(modifier: Modifier = Modifier, onClick: () -> Unit) {
|
||||||
TangemButton(
|
TangemButton(
|
||||||
modifier = modifier,
|
modifier = modifier.testTag(TopNavigationTestTags.BACK_BUTTON),
|
||||||
variant = TangemButton.Variant.Material,
|
variant = TangemButton.Variant.Material,
|
||||||
iconStart = TangemIconUM.Icon(Icons.ic_arrow_left_20),
|
iconStart = TangemIconUM.Icon(Icons.ic_arrow_left_20),
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
|
|
|
||||||
|
|
@ -5,4 +5,5 @@ object ReferralProgramScreenTestTags {
|
||||||
const val CONDITION_BLOCK = "REFERRAL_PROGRAM_SCREEN_CONDITION_BLOCK"
|
const val CONDITION_BLOCK = "REFERRAL_PROGRAM_SCREEN_CONDITION_BLOCK"
|
||||||
const val INFO_FOR_YOU_TEXT = "REFERRAL_PROGRAM_SCREEN_INFO_FOR_YOU_TEXT"
|
const val INFO_FOR_YOU_TEXT = "REFERRAL_PROGRAM_SCREEN_INFO_FOR_YOU_TEXT"
|
||||||
const val INFO_FOR_YOUR_FRIEND_TEXT = "REFERRAL_PROGRAM_INFO_FOR_YOUR_FRIEND_TEXT"
|
const val INFO_FOR_YOUR_FRIEND_TEXT = "REFERRAL_PROGRAM_INFO_FOR_YOUR_FRIEND_TEXT"
|
||||||
|
const val PERSONAL_CODE_CARD = "REFERRAL_PROGRAM_SCREEN_PERSONAL_CODE_CARD"
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.tangem.core.ui.test
|
||||||
|
|
||||||
|
object TopNavigationTestTags {
|
||||||
|
const val BACK_BUTTON = "TOP_NAVIGATION_BACK_BUTTON"
|
||||||
|
}
|
||||||
|
|
@ -16,6 +16,7 @@ import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||||
import androidx.compose.ui.platform.LocalClipboardManager
|
import androidx.compose.ui.platform.LocalClipboardManager
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||||
|
import androidx.compose.ui.platform.testTag
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.text.AnnotatedString
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
|
@ -41,6 +42,7 @@ import com.tangem.core.ui.res.LocalRedesignEnabled
|
||||||
import com.tangem.core.ui.res.LocalTopSnackbarHostState
|
import com.tangem.core.ui.res.LocalTopSnackbarHostState
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.core.ui.res.TangemThemePreview
|
import com.tangem.core.ui.res.TangemThemePreview
|
||||||
|
import com.tangem.core.ui.test.ReferralProgramScreenTestTags
|
||||||
import com.tangem.feature.referral.domain.models.ExpectedAward
|
import com.tangem.feature.referral.domain.models.ExpectedAward
|
||||||
import com.tangem.feature.referral.domain.models.ExpectedAwards
|
import com.tangem.feature.referral.domain.models.ExpectedAwards
|
||||||
import com.tangem.feature.referral.models.ReferralStateHolder
|
import com.tangem.feature.referral.models.ReferralStateHolder
|
||||||
|
|
@ -261,6 +263,7 @@ private fun ExtraItems(extraItems: List<ExpectedAward>, overallItemsLastIndex: I
|
||||||
private fun PersonalCodeCard(code: String, accountAward: ReferralStateHolder.AccountAward?) {
|
private fun PersonalCodeCard(code: String, accountAward: ReferralStateHolder.AccountAward?) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
.testTag(ReferralProgramScreenTestTags.PERSONAL_CODE_CARD)
|
||||||
.clip(RoundedCornerShape(TangemTheme.dimens.radius12))
|
.clip(RoundedCornerShape(TangemTheme.dimens.radius12))
|
||||||
.background(color = TangemTheme.colors.background.primary)
|
.background(color = TangemTheme.colors.background.primary)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue