Updated on 2026-08-14

This commit is contained in:
Tangem 2025-10-13 13:02:12 +03:00
commit 3946e4ebca
359 changed files with 8459 additions and 3324 deletions

View file

@ -1,8 +1,8 @@
package com.tangem.common
import android.Manifest
import androidx.compose.ui.test.isRoot
import androidx.compose.ui.test.junit4.createEmptyComposeRule
import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.printToLog
import androidx.test.core.app.ActivityScenario
import androidx.test.espresso.intent.Intents
@ -121,6 +121,8 @@ abstract class BaseTestCase : TestCase(
/**
* Prints the Compose semantics tree to logcat for debugging UI tests.
*
* @param rootIndex Use rootIndex > 0, if you need to print semantics tree for bottom sheet.
* Default: 0.
* @param useUnmergedTree When true, shows unmerged tree with all individual nodes.
* Use for accessing inner elements of compound components.
* Default: false (merged tree - accessibility view).
@ -129,11 +131,13 @@ abstract class BaseTestCase : TestCase(
* Default: Int.MAX_VALUE (unlimited depth).
*/
fun printSemanticTree(
rootIndex: Int = 0,
useUnmergedTree: Boolean = false,
tag: String = "SEMANTIC_TREE",
maxDepth: Int = Int.MAX_VALUE)
{
composeTestRule.onRoot(useUnmergedTree = useUnmergedTree).printToLog(tag, maxDepth)
maxDepth: Int = Int.MAX_VALUE
) {
composeTestRule.onAllNodes(isRoot(), useUnmergedTree = useUnmergedTree)[rootIndex]
.printToLog(tag, maxDepth)
}
fun waitForIdle() = composeTestRule.waitForIdle()

View file

@ -4,6 +4,7 @@ object TestConstants {
const val TOTAL_BALANCE = "$3,299.18"
const val RECIPIENT_ADDRESS = "0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0"
const val BITCOIN_ADDRESS = "bc1qtg9aa6jcpqtvun0pe0uct7sxm8nq2nsxfmfxm3"
const val CARDANO_ADDRESS = "addr1q8f9499e58k4hhfd9vhawprxt3xd94x7rmlyp33ee4xkatakcl2zgkrg0p6ceqkndtkw4cumfe9enhdph8yhuswn785srksm9p"
const val WAIT_UNTIL_TIMEOUT = 20_000L

View file

@ -0,0 +1,38 @@
package com.tangem.common.utils
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import androidx.test.core.app.ApplicationProvider
fun getClipboardText(context: Context): String? {
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
return if (clipboard.hasPrimaryClip()) {
clipboard.primaryClip?.getItemAt(0)?.text?.toString()
} else {
null
}
}
fun setClipboardText(context: Context, text: String?) {
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clip = ClipData.newPlainText("label", text)
clipboard.setPrimaryClip(clip)
}
fun clearClipboard(
context: Context = ApplicationProvider.getApplicationContext()
) {
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
clipboard.clearPrimaryClip()
}
fun assertClipboardTextEquals(
expected: String,
context: Context = ApplicationProvider.getApplicationContext()
) {
val actual = getClipboardText(context)
assert(actual == expected) {
"Clipboard text mismatch.\nExpected: '$expected'\nActual: '$actual'"
}
}

View file

@ -85,4 +85,13 @@ fun BaseTestCase.openDeviceSettingsScreen() {
step("Click on 'Device settings' button") {
onWalletSettingsScreen { deviceSettingsButton.clickWithAssertion() }
}
}
fun BaseTestCase.openWalletConnectScreen() {
step("Click 'More' button on TopBar") {
onTopBar { moreButton.clickWithAssertion() }
}
step("Click on 'Wallet Connect' button") {
onDetailsScreen { walletConnectButton.clickWithAssertion() }
}
}

View file

@ -0,0 +1,124 @@
package com.tangem.scenarios
import com.tangem.common.BaseTestCase
import com.tangem.screens.onSendScreen
import com.tangem.screens.onStakingConfirmScreen
import com.tangem.screens.onStakingDetailsScreen
import io.qameta.allure.kotlin.Allure.step
fun BaseTestCase.checkStakingDetailsScreen(withStaking: Boolean) {
step("Assert 'Title' is displayed") {
onStakingDetailsScreen { stakingTitle.assertIsDisplayed() }
}
step("Assert 'Annual percentage rate' is displayed") {
onStakingDetailsScreen { annualPercentageRate.assertIsDisplayed() }
}
step("Assert 'Available' block is displayed") {
onStakingDetailsScreen { availableBlock.assertIsDisplayed() }
}
step("Assert 'Unbonding Period' block is displayed") {
onStakingDetailsScreen { unbondingPeriodBlock.assertIsDisplayed() }
}
step("Assert 'Reward claiming' block is displayed") {
onStakingDetailsScreen { rewardClaimingBlock.assertIsDisplayed() }
}
step("Assert 'Reward schedule' block is displayed") {
onStakingDetailsScreen { rewardScheduleBlock.assertIsDisplayed() }
}
step("Assert 'ToS' text is displayed") {
onStakingDetailsScreen { toSText.assertIsDisplayed() }
}
if (withStaking) {
step("Assert 'Rewards block' is displayed") {
onStakingDetailsScreen { rewardsBlock.assertIsDisplayed() }
}
step("Assert 'Rewards block' title is displayed") {
onStakingDetailsScreen { rewardsBlockTitle.assertIsDisplayed() }
}
step("Assert 'Rewards block' text is displayed") {
onStakingDetailsScreen { rewardsBlockText.assertIsDisplayed() }
}
step("Assert 'Active staking block' is displayed") {
onStakingDetailsScreen { activeStakingBlock.assertIsDisplayed() }
}
step("Assert 'Your stakes' title is displayed") {
onStakingDetailsScreen { yourStakesTitle.assertIsDisplayed() }
}
step("Assert 'Stake more' button is displayed") {
onStakingDetailsScreen { stakeMoreButton.assertIsDisplayed() }
}
} else {
step("Assert banner image is displayed") {
onStakingDetailsScreen { bannerImage.assertIsDisplayed() }
}
step("Assert banner text is displayed") {
onStakingDetailsScreen { bannerText.assertIsDisplayed() }
}
step("Assert 'Stake' button is displayed") {
onStakingDetailsScreen { stakeButton.assertIsDisplayed() }
}
}
}
fun BaseTestCase.checkStakingScreen(stakingAmount: String) {
step("Assert 'Staking' screen is displayed") {
onSendScreen { screenContainer.assertIsDisplayed() }
}
step("Assert top app bar 'Close' button is displayed") {
onSendScreen { closeButton.assertIsDisplayed() }
}
step("Assert 'Send' screen title is displayed") {
onSendScreen { title.assertIsDisplayed() }
}
step("Assert amount container title is displayed") {
onSendScreen { amountContainerTitle.assertIsDisplayed() }
}
step("Assert input text field is displayed") {
onSendScreen { amountInputTextField.assertIsDisplayed() }
}
step("Assert token name is displayed") {
onSendScreen { tokenName.assertIsDisplayed() }
}
step("Assert primary amount is displayed") {
onSendScreen { primaryAmount.assertIsDisplayed() }
}
step("Assert secondary amount is displayed") {
onSendScreen { secondaryAmount.assertIsDisplayed() }
}
step("Type '$stakingAmount' in input text field") {
onSendScreen {
amountInputTextField.performClick()
amountInputTextField.performTextReplacement(stakingAmount)
}
}
step("Assert input text field has value: '$stakingAmount'") {
onSendScreen { amountInputTextField.assertTextContains(value = stakingAmount, substring = true) }
}
step("Assert 'Max' button is displayed") {
onSendScreen { maxButton.assertIsDisplayed() }
}
step("Assert 'Next' button is displayed") {
onSendScreen { nextButton.assertIsDisplayed() }
}
}
fun BaseTestCase.checkStakingConfirmScreen() {
step("Assert 'Staking confirm' screen title is displayed") {
onStakingConfirmScreen { title.assertIsDisplayed() }
}
step("Assert primary amount is displayed") {
onStakingConfirmScreen { primaryAmount.assertIsDisplayed() }
}
step("Assert secondary amount is displayed") {
onStakingConfirmScreen { secondaryAmount.assertIsDisplayed() }
}
step("Assert 'Validator' block is displayed") {
onStakingConfirmScreen { validatorBlock.assertIsDisplayed() }
}
step("Assert 'Network Fee' block is displayed") {
onStakingConfirmScreen { networkFeeBlock.assertIsDisplayed() }
}
step("Assert 'Stake' button is displayed") {
onStakingConfirmScreen { stakeButton.assertIsDisplayed() }
}
}

View file

@ -7,6 +7,7 @@ import com.tangem.screens.onWalletConnectScreen
import io.qameta.allure.kotlin.Allure.step
fun BaseTestCase.checkWalletConnectBottomSheet() {
waitForIdle()
step("Assert 'Wallet Connect' bottom sheet title is displayed") {
onWalletConnectBottomSheet { title.assertIsDisplayed() }
}
@ -60,34 +61,64 @@ fun BaseTestCase.checkWalletConnectBottomSheet() {
}
}
fun BaseTestCase.checkWalletConnectScreen() {
fun BaseTestCase.checkWalletConnectScreen(withConnections: Boolean) {
waitForIdle()
step("Assert 'Wallet Connect' title is displayed") {
onWalletConnectScreen { title.assertIsDisplayed() }
}
step("Assert 'More' button is displayed") {
onWalletConnectScreen { moreButton.assertIsDisplayed() }
}
step("Assert wallet name is displayed") {
onWalletConnectScreen { walletName.assertIsDisplayed() }
}
step("Assert app icon is displayed") {
onWalletConnectScreen { appIcon.assertIsDisplayed() }
}
step("Assert app name is displayed") {
onWalletConnectScreen { appName.assertIsDisplayed() }
}
step("Assert approve icon is displayed") {
onWalletConnectScreen { approveIcon.assertIsDisplayed() }
}
step("Assert app URL is displayed") {
onWalletConnectScreen { appUrl.assertIsDisplayed() }
}
step("Assert 'New Connection' button is displayed") {
onWalletConnectScreen { newConnectionButton.assertIsDisplayed() }
}
if (withConnections) {
step("Assert 'More' button is displayed") {
onWalletConnectScreen { moreButton.assertIsDisplayed() }
}
step("Assert wallet name is displayed") {
onWalletConnectScreen { walletName.assertIsDisplayed() }
}
step("Assert app icon is displayed") {
onWalletConnectScreen { appIcon.assertIsDisplayed() }
}
step("Assert app name is displayed") {
onWalletConnectScreen { appName.assertIsDisplayed() }
}
step("Assert approve icon is displayed") {
onWalletConnectScreen { approveIcon.assertIsDisplayed() }
}
step("Assert app URL is displayed") {
onWalletConnectScreen { appUrl.assertIsDisplayed() }
}
} else {
step("Assert wallet name is not displayed") {
onWalletConnectScreen { walletName.assertIsNotDisplayed() }
}
step("Assert app icon is not displayed") {
onWalletConnectScreen { appIcon.assertIsNotDisplayed() }
}
step("Assert app name is not displayed") {
onWalletConnectScreen { appName.assertIsNotDisplayed() }
}
step("Assert approve icon is not displayed") {
onWalletConnectScreen { approveIcon.assertIsNotDisplayed() }
}
step("Assert app URL is not displayed") {
onWalletConnectScreen { appUrl.assertIsNotDisplayed() }
}
step("Assert 'Wallet Connect' image is displayed") {
onWalletConnectScreen { walletConnectImage.assertIsDisplayed() }
}
step("Assert 'No session' title is displayed") {
onWalletConnectScreen { noSessionTitle.assertIsDisplayed() }
}
step("Assert 'No session' text is displayed") {
onWalletConnectScreen { noSessionText.assertIsDisplayed() }
}
}
}
fun BaseTestCase.checkWalletConnectDetailsBottomSheet(dAppName: String) {
waitForIdle()
step("Assert connection details title is displayed") {
onWalletConnectDetailsBottomSheet { title.assertIsDisplayed() }
}
@ -128,7 +159,7 @@ fun BaseTestCase.checkWalletConnectDetailsBottomSheet(dAppName: String) {
onWalletConnectDetailsBottomSheet { connectedNetworkIcon.assertIsDisplayed() }
}
step("Assert connected dApp name: '$dAppName'") {
onWalletConnectDetailsBottomSheet { connectedNetworkName.assertTextContains(dAppName) }
onWalletConnectDetailsBottomSheet { appName.assertTextContains(dAppName) }
}
step("Assert connected network symbol is displayed") {
onWalletConnectDetailsBottomSheet { connectedNetworkSymbol.assertIsDisplayed() }

View file

@ -0,0 +1,55 @@
package com.tangem.screens
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.Until
import com.kaspersky.kaspresso.screens.KScreen
object ChromeBrowserPageObject : KScreen<ChromeBrowserPageObject>() {
override val layoutId: Int? = null
override val viewClass: Class<*>? = null
private val device: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
private const val TIMEOUT = 10000L
fun assertChromeIsOpened() {
val chromePackage = "com.android.chrome"
device.wait(Until.hasObject(By.pkg(chromePackage).depth(0)), TIMEOUT)
assert(device.hasObject(By.pkg(chromePackage))) {
"Chrome browser is not opened"
}
}
fun assertUrlContains(expectedUrl: String) {
val urlBar = device.findObject(
By.res("com.android.chrome:id/url_bar")
)
urlBar?.let {
assert(it.text.contains(expectedUrl)) {
"URL doesn't contain expected: $expectedUrl, actual: ${it.text}"
}
}
}
private fun findElementByText(text: String): UiObject2? {
device.wait(Until.hasObject(By.text(text)), TIMEOUT)
return device.findObject(By.text(text))
}
fun assertElementWithTextExists(text: String) {
val element = findElementByText(text)
assert(element != null) { "Element with text '$text' not found" }
}
fun isElementWithTextExists(text: String): Boolean {
return device.wait(Until.hasObject(By.text(text)), TIMEOUT)
}
fun clickOnElementWithText(text: String) {
findElementByText(text)?.click()
?: throw AssertionError("Cannot click - element with text '$text' not found")
}
}

View file

@ -17,6 +17,7 @@ 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
import com.tangem.core.ui.R as CoreUiR
class MainScreenPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<MainScreenPageObject>(semanticsProvider = semanticsProvider) {
@ -200,6 +201,10 @@ class MainScreenPageObject(semanticsProvider: SemanticsNodeInteractionsProvider)
useUnmergedTree = true
}
val snackbarCopiedAddressMessage: KNode = child {
hasText(getResourceString(CoreUiR.string.wallet_notification_address_copied))
}
/**
* Find token list item with title and address
*/

View file

@ -3,20 +3,19 @@ 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.BaseBottomSheetTestTags
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
class BaseBottomSheetPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<BaseBottomSheetPageObject>(semanticsProvider = semanticsProvider) {
class ReceiveAssetsBottomSheetPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<ReceiveAssetsBottomSheetPageObject>(semanticsProvider = semanticsProvider) {
val hideButton: KNode = child {
hasText(getResourceString(R.string.token_details_hide_token))
hasTestTag(BaseBottomSheetTestTags.ACTION_TITLE)
val showQrCodeButton: KNode = child {
hasText(getResourceString(R.string.token_receive_show_qr_code_title))
useUnmergedTree = true
}
}
internal fun BaseTestCase.onBottomSheet(function: BaseBottomSheetPageObject.() -> Unit) =
internal fun BaseTestCase.onReceiveAssetsBottomSheet(function: ReceiveAssetsBottomSheetPageObject.() -> Unit) =
onComposeScreen(composeTestRule, function)

View file

@ -10,7 +10,6 @@ import io.github.kakaocup.compose.node.element.ComposeScreen.Companion.onCompose
import io.github.kakaocup.compose.node.element.KNode
import io.github.kakaocup.kakao.common.utilities.getResourceString
import com.tangem.features.send.v2.impl.R as SendR
import androidx.compose.ui.test.hasTestTag as withTestTag
class SendPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<SendPageObject>(semanticsProvider = semanticsProvider) {
@ -19,6 +18,11 @@ class SendPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
hasTestTag(SendScreenTestTags.SCREEN_CONTAINER)
}
val closeButton: KNode = child {
hasTestTag(TopAppBarTestTags.CLOSE_BUTTON)
useUnmergedTree = true
}
val title: KNode = child {
hasTestTag(TopAppBarTestTags.TITLE)
useUnmergedTree = true
@ -29,13 +33,18 @@ class SendPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
useUnmergedTree = true
}
val amountContainerText: KNode = child {
hasTestTag(SendScreenTestTags.AMOUNT_CONTAINER_TEXT)
val amountInputTextField: KNode = child {
hasTestTag(SendScreenTestTags.INPUT_TEXT_FIELD)
useUnmergedTree = true
}
val amountInputTextField: KNode = child {
hasTestTag(SendScreenTestTags.INPUT_TEXT_FIELD)
val tokenName: KNode = child {
hasTestTag(SendScreenTestTags.TOKEN_NAME)
useUnmergedTree = true
}
val primaryAmount: KNode = child {
hasTestTag(SendScreenTestTags.PRIMARY_AMOUNT)
useUnmergedTree = true
}
@ -44,28 +53,11 @@ class SendPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
useUnmergedTree = true
}
val currencyButton: KNode = child {
hasTestTag(SendScreenTestTags.CURRENCY_BUTTON)
hasAnyChild(withTestTag(SendScreenTestTags.CURRENCY_ICON))
useUnmergedTree = true
}
val fiatButton: KNode = child {
hasTestTag(SendScreenTestTags.CURRENCY_BUTTON)
hasAnyChild(withTestTag(SendScreenTestTags.FIAT_ICON))
useUnmergedTree = true
}
val maxButton: KNode = child {
hasTestTag(SendScreenTestTags.MAX_BUTTON)
useUnmergedTree = true
}
val previousButton: KNode = child {
hasTestTag(SendScreenTestTags.PREVIOUS_BUTTON)
useUnmergedTree = true
}
val nextButton: KNode = child {
hasTestTag(BaseButtonTestTags.TEXT)
hasText(getResourceString(SendR.string.common_next))

View file

@ -71,6 +71,10 @@ class SwapTokenPageObject(semanticsProvider: SemanticsNodeInteractionsProvider)
hasText(getResourceString(R.string.common_swap))
}
fun tokenSymbol(symbol: String): KNode = child {
hasTestTag(SwapTokenScreenTestTags.TOKEN_SYMBOL)
}
}
internal fun BaseTestCase.onSwapTokenScreen(function: SwapTokenPageObject.() -> Unit) =

View file

@ -0,0 +1,75 @@
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.BaseBottomSheetTestTags
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.hasTestTag as withTestTag
import androidx.compose.ui.test.hasText as withText
class TokenActionsBottomSheetPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<TokenActionsBottomSheetPageObject>(semanticsProvider = semanticsProvider) {
val analyticsButton: KNode = child {
hasAnyChild(withText(getResourceString(R.string.common_analytics)))
hasTestTag(BaseBottomSheetTestTags.ACTION_BUTTON)
hasAnyChild(withTestTag(BaseBottomSheetTestTags.ACTION_ICON))
useUnmergedTree = true
}
val copyAddressButton: KNode = child {
hasAnyChild(withText(getResourceString(R.string.common_copy_address)))
hasTestTag(BaseBottomSheetTestTags.ACTION_BUTTON)
hasAnyChild(withTestTag(BaseBottomSheetTestTags.ACTION_ICON))
useUnmergedTree = true
}
val receiveButton: KNode = child {
hasAnyChild(withText(getResourceString(R.string.common_receive)))
hasTestTag(BaseBottomSheetTestTags.ACTION_BUTTON)
hasAnyChild(withTestTag(BaseBottomSheetTestTags.ACTION_ICON))
useUnmergedTree = true
}
val sendButton: KNode = child {
hasAnyChild(withText(getResourceString(R.string.common_send)))
hasTestTag(BaseBottomSheetTestTags.ACTION_BUTTON)
hasAnyChild(withTestTag(BaseBottomSheetTestTags.ACTION_ICON))
useUnmergedTree = true
}
val swapButton: KNode = child {
hasAnyChild(withText(getResourceString(R.string.common_swap)))
hasTestTag(BaseBottomSheetTestTags.ACTION_BUTTON)
hasAnyChild(withTestTag(BaseBottomSheetTestTags.ACTION_ICON))
useUnmergedTree = true
}
val buyButton: KNode = child {
hasAnyChild(withText(getResourceString(R.string.common_buy)))
hasTestTag(BaseBottomSheetTestTags.ACTION_BUTTON)
hasAnyChild(withTestTag(BaseBottomSheetTestTags.ACTION_ICON))
useUnmergedTree = true
}
val sellButton: KNode = child {
hasAnyChild(withText(getResourceString(R.string.common_sell)))
hasTestTag(BaseBottomSheetTestTags.ACTION_BUTTON)
hasAnyChild(withTestTag(BaseBottomSheetTestTags.ACTION_ICON))
useUnmergedTree = true
}
val hideTokenButton: KNode = child {
hasAnyChild(withText(getResourceString(R.string.token_details_hide_token)))
hasTestTag(BaseBottomSheetTestTags.ACTION_BUTTON)
hasAnyChild(withTestTag(BaseBottomSheetTestTags.ACTION_ICON))
useUnmergedTree = true
}
}
internal fun BaseTestCase.onTokenActionsBottomSheet(function: TokenActionsBottomSheetPageObject.() -> Unit) =
onComposeScreen(composeTestRule, function)

View file

@ -0,0 +1,56 @@
package com.tangem.screens
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
import com.tangem.common.BaseTestCase
import com.tangem.core.ui.test.BaseBottomSheetTestTags
import com.tangem.core.ui.test.BaseButtonTestTags
import com.tangem.core.ui.test.TokenReceiveQrCodeBottomSheetTestTags
import com.tangem.wallet.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
class TokenReceiveQrCodeBottomSheetPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<TokenReceiveQrCodeBottomSheetPageObject>(semanticsProvider = semanticsProvider) {
val closeButton: KNode = child {
hasTestTag(BaseBottomSheetTestTags.CLOSE_BUTTON)
useUnmergedTree = true
}
val title: KNode = child {
hasTestTag(TokenReceiveQrCodeBottomSheetTestTags.TITLE)
useUnmergedTree = true
}
val qrCode: KNode = child {
hasTestTag(TokenReceiveQrCodeBottomSheetTestTags.QR_CODE)
useUnmergedTree = true
}
val addressTitle: KNode = child {
hasText(getResourceString(R.string.wc_common_address))
useUnmergedTree = true
}
val address: KNode = child {
hasTestTag(TokenReceiveQrCodeBottomSheetTestTags.ADDRESS)
useUnmergedTree = true
}
val copyButton: KNode = child {
hasTestTag(BaseButtonTestTags.TEXT)
hasText(getResourceString(R.string.common_copy))
useUnmergedTree = true
}
val shareButton: KNode = child {
hasTestTag(BaseButtonTestTags.TEXT)
hasText(getResourceString(R.string.common_share))
useUnmergedTree = true
}
}
internal fun BaseTestCase.onTokenReceiveQrCodeBottomSheet(function: TokenReceiveQrCodeBottomSheetPageObject.() -> Unit) =
onComposeScreen(composeTestRule, function)

View file

@ -0,0 +1,28 @@
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.BaseButtonTestTags
import com.tangem.core.ui.test.TokenReceiveWarningBottomSheetTestTags
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
class TokenReceiveWarningBottomSheetPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<TokenReceiveWarningBottomSheetPageObject>(semanticsProvider = semanticsProvider) {
val bottomSheet: KNode = child {
hasTestTag(TokenReceiveWarningBottomSheetTestTags.BOTTOM_SHEET)
}
val gotItButton: KNode = child {
hasTestTag(BaseButtonTestTags.TEXT)
hasText(getResourceString(R.string.common_got_it))
useUnmergedTree = true
}
}
internal fun BaseTestCase.onTokenReceiveWarningBottomSheet(function: TokenReceiveWarningBottomSheetPageObject.() -> Unit) =
onComposeScreen(composeTestRule, function)

View file

@ -9,13 +9,11 @@ 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 com.tangem.features.walletconnect.impl.R as WalletConnectImplR
class WalletConnectBottomSheetPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<WalletConnectBottomSheetPageObject>(semanticsProvider = semanticsProvider) {
val title: KNode = child {
hasText(getResourceString(WalletConnectImplR.string.wc_wallet_connect))
hasTestTag(WalletConnectBottomSheetTestTags.TITLE)
useUnmergedTree = true
}

View file

@ -53,6 +53,21 @@ class WalletConnectPageObject(semanticsProvider: SemanticsNodeInteractionsProvid
hasText(getResourceString(R.string.wc_new_connection))
useUnmergedTree = true
}
val walletConnectImage: KNode = child {
hasTestTag(WalletConnectScreenTestTags.WALLET_CONNECT_IMAGE)
useUnmergedTree = true
}
val noSessionTitle: KNode = child {
hasText(getResourceString(R.string.wc_no_sessions_title))
useUnmergedTree = true
}
val noSessionText: KNode = child {
hasText(getResourceString(R.string.wc_no_sessions_desc))
useUnmergedTree = true
}
}
internal fun BaseTestCase.onWalletConnectScreen(function: WalletConnectPageObject.() -> Unit) =

View file

@ -0,0 +1,23 @@
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.BaseButtonTestTags
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
class WalletConnectScanQrPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<WalletConnectScanQrPageObject>(semanticsProvider = semanticsProvider) {
val pasteFromClipboardButton: KNode = child {
hasTestTag(BaseButtonTestTags.TEXT)
hasText(getResourceString(R.string.wallet_connect_paste_from_clipboard))
useUnmergedTree = true
}
}
internal fun BaseTestCase.onWalletConnectScanQrScreen(function: WalletConnectScanQrPageObject.() -> Unit) =
onComposeScreen(composeTestRule, function)

View file

@ -1,6 +1,10 @@
package com.tangem.tests
import com.tangem.common.BaseTestCase
import com.tangem.common.annotations.ApiEnv
import com.tangem.common.annotations.ApiEnvConfig
import com.tangem.datasource.api.common.config.ApiConfig
import com.tangem.datasource.api.common.config.ApiEnvironment
import com.tangem.domain.models.scan.ProductType
import com.tangem.scenarios.checkMultiCurrencyMainScreen
import com.tangem.scenarios.checkSingleCurrencyMainScreen
@ -15,6 +19,10 @@ import org.junit.Test
@HiltAndroidTest
class ScanCardTest : BaseTestCase() {
@ApiEnv(
ApiEnvConfig(ApiConfig.ID.TangemTech, ApiEnvironment.PROD),
ApiEnvConfig(ApiConfig.ID.Express, ApiEnvironment.PROD)
)
@AllureId("868")
@DisplayName("Scan: Scanning single-currency cards")
@Test

View file

@ -7,9 +7,8 @@ import com.tangem.common.extensions.clickWithAssertion
import com.tangem.common.extensions.swipeVertical
import com.tangem.common.utils.resetWireMockScenarioState
import com.tangem.common.utils.setWireMockScenarioState
import com.tangem.scenarios.*
import com.tangem.screens.*
import com.tangem.scenarios.openMainScreen
import com.tangem.scenarios.synchronizeAddresses
import dagger.hilt.android.testing.HiltAndroidTest
import io.qameta.allure.kotlin.AllureId
import io.qameta.allure.kotlin.junit4.DisplayName
@ -117,116 +116,20 @@ class StakingTest : BaseTestCase() {
step("Click on 'Staking block'") {
onTokenDetailsScreen { stakingBlock.clickWithAssertion() }
}
step("Assert 'Title' is displayed") {
onStakingDetailsScreen { stakingTitle.assertIsDisplayed() }
}
step("Assert 'Annual percentage rate' is displayed") {
onStakingDetailsScreen { annualPercentageRate.assertIsDisplayed() }
}
step("Assert 'Available' block is displayed") {
onStakingDetailsScreen { availableBlock.assertIsDisplayed() }
}
step("Assert 'Unbonding Period' block is displayed") {
onStakingDetailsScreen { unbondingPeriodBlock.assertIsDisplayed() }
}
step("Assert 'Reward claiming' block is displayed") {
onStakingDetailsScreen { rewardClaimingBlock.assertIsDisplayed() }
}
step("Assert 'Reward schedule' block is displayed") {
onStakingDetailsScreen { rewardScheduleBlock.assertIsDisplayed() }
}
step("Assert 'Rewards block' is displayed") {
onStakingDetailsScreen { rewardsBlock.assertIsDisplayed() }
}
step("Assert 'Rewards block' title is displayed") {
onStakingDetailsScreen { rewardsBlockTitle.assertIsDisplayed() }
}
step("Assert 'Rewards block' text is displayed") {
onStakingDetailsScreen { rewardsBlockText.assertIsDisplayed() }
}
step("Assert 'Active staking block' is displayed") {
onStakingDetailsScreen { activeStakingBlock.assertIsDisplayed() }
}
step("Assert 'Your stakes' title is displayed") {
onStakingDetailsScreen { yourStakesTitle.assertIsDisplayed() }
}
step("Assert 'ToS' text is displayed") {
onStakingDetailsScreen { toSText.assertIsDisplayed() }
}
step("Assert 'Stake more' button is displayed") {
onStakingDetailsScreen { stakeMoreButton.assertIsDisplayed() }
step("Check 'Staking details' screen") {
checkStakingDetailsScreen(withStaking = true)
}
step("Click 'Stake more' button") {
onStakingDetailsScreen { stakeMoreButton.performClick() }
}
step("Assert 'Send' screen is displayed") {
onSendScreen { screenContainer.assertIsDisplayed() }
}
step("Assert 'Send' screen title is displayed") {
onSendScreen { title.assertIsDisplayed() }
}
step("Assert amount container title is displayed") {
onSendScreen { amountContainerTitle.assertIsDisplayed() }
}
step("Assert amount container text is displayed") {
onSendScreen { amountContainerText.assertIsDisplayed() }
}
step("Assert input text field is displayed") {
onSendScreen { amountInputTextField.assertIsDisplayed() }
}
step("Assert secondary amount is displayed") {
onSendScreen { secondaryAmount.assertIsDisplayed() }
}
step("Type '$stakingAmount' in input text field") {
onSendScreen {
amountInputTextField.performClick()
amountInputTextField.performTextReplacement(stakingAmount)
}
}
step("Assert input text field has value: '$stakingAmount'") {
onSendScreen { amountInputTextField.assertTextContains(value = stakingAmount, substring = true) }
}
step("Assert currency button is displayed") {
onSendScreen { currencyButton.assertIsDisplayed() }
}
step("Assert fiat button is displayed") {
onSendScreen { fiatButton.assertIsDisplayed() }
}
step("Assert currency button is displayed") {
onSendScreen { currencyButton.assertIsDisplayed() }
}
step("Assert fiat button is displayed") {
onSendScreen { fiatButton.assertIsDisplayed() }
}
step("Assert 'Max' button is displayed") {
onSendScreen { maxButton.assertIsDisplayed() }
}
step("Assert previous button is displayed") {
onSendScreen { previousButton.assertIsDisplayed() }
}
step("Assert 'Next' button is displayed") {
onSendScreen { nextButton.assertIsDisplayed() }
step("Check 'Staking' screen") {
checkStakingScreen(stakingAmount)
}
step("Click on 'Next' button") {
onSendScreen { nextButton.performClick() }
}
step("Assert 'Send details' screen title is displayed") {
onStakingConfirmScreen { title.assertIsDisplayed() }
}
step("Assert primary amount is displayed") {
onStakingConfirmScreen { primaryAmount.assertIsDisplayed() }
}
step("Assert secondary amount is displayed") {
onStakingConfirmScreen { secondaryAmount.assertIsDisplayed() }
}
step("Assert 'Validator' block is displayed") {
onStakingConfirmScreen { validatorBlock.assertIsDisplayed() }
}
step("Assert 'Network Fee' block is displayed") {
onStakingConfirmScreen { networkFeeBlock.assertIsDisplayed() }
}
step("Assert 'Stake' button is displayed") {
onStakingConfirmScreen { stakeButton.assertIsDisplayed() }
step("Check 'Staking confirm' screen") {
checkStakingConfirmScreen()
}
}
}
@ -284,107 +187,20 @@ class StakingTest : BaseTestCase() {
step("Click on 'Stake' button") {
onTokenDetailsScreen { stakeButton.clickWithAssertion() }
}
step("Assert 'Title' is displayed") {
onStakingDetailsScreen { stakingTitle.assertIsDisplayed() }
}
step("Assert banner image is displayed") {
onStakingDetailsScreen { bannerImage.assertIsDisplayed() }
}
step("Assert banner text is displayed") {
onStakingDetailsScreen { bannerText.assertIsDisplayed() }
}
step("Assert 'Annual percentage rate' is displayed") {
onStakingDetailsScreen { annualPercentageRate.assertIsDisplayed() }
}
step("Assert 'Available' block is displayed") {
onStakingDetailsScreen { availableBlock.assertIsDisplayed() }
}
step("Assert 'Unbonding Period' block is displayed") {
onStakingDetailsScreen { unbondingPeriodBlock.assertIsDisplayed() }
}
step("Assert 'Reward claiming' block is displayed") {
onStakingDetailsScreen { rewardClaimingBlock.assertIsDisplayed() }
}
step("Assert 'Reward schedule' block is displayed") {
onStakingDetailsScreen { rewardScheduleBlock.assertIsDisplayed() }
}
step("Assert 'ToS' text is displayed") {
onStakingDetailsScreen { toSText.assertIsDisplayed() }
}
step("Assert 'Stake' button is displayed") {
onStakingDetailsScreen { stakeButton.assertIsDisplayed() }
step("Check 'Staking details' screen") {
checkStakingDetailsScreen(withStaking = false)
}
step("Click 'Stake' button") {
onStakingDetailsScreen { stakeButton.performClick() }
}
step("Assert 'Send' screen is displayed") {
onSendScreen { screenContainer.assertIsDisplayed() }
}
step("Assert 'Send' screen title is displayed") {
onSendScreen { title.assertIsDisplayed() }
}
step("Assert amount container title is displayed") {
onSendScreen { amountContainerTitle.assertIsDisplayed() }
}
step("Assert amount container text is displayed") {
onSendScreen { amountContainerText.assertIsDisplayed() }
}
step("Assert input text field is displayed") {
onSendScreen { amountInputTextField.assertIsDisplayed() }
}
step("Assert secondary amount is displayed") {
onSendScreen { secondaryAmount.assertIsDisplayed() }
}
step("Type '$stakingAmount' in input text field") {
onSendScreen {
amountInputTextField.performClick()
amountInputTextField.performTextReplacement(stakingAmount)
}
}
step("Assert input text field has value: '$stakingAmount'") {
onSendScreen { amountInputTextField.assertTextContains(value = stakingAmount, substring = true) }
}
step("Assert currency button is displayed") {
onSendScreen { currencyButton.assertIsDisplayed() }
}
step("Assert fiat button is displayed") {
onSendScreen { fiatButton.assertIsDisplayed() }
}
step("Assert currency button is displayed") {
onSendScreen { currencyButton.assertIsDisplayed() }
}
step("Assert fiat button is displayed") {
onSendScreen { fiatButton.assertIsDisplayed() }
}
step("Assert 'Max' button is displayed") {
onSendScreen { maxButton.assertIsDisplayed() }
}
step("Assert previous button is displayed") {
onSendScreen { previousButton.assertIsDisplayed() }
}
step("Assert 'Next' button is displayed") {
onSendScreen { nextButton.assertIsDisplayed() }
step("Check 'Staking' screen") {
checkStakingScreen(stakingAmount)
}
step("Click on 'Next' button") {
onSendScreen { nextButton.performClick() }
}
step("Assert 'Send details' screen title is displayed") {
onStakingConfirmScreen { title.assertIsDisplayed() }
}
step("Assert primary amount is displayed") {
onStakingConfirmScreen { primaryAmount.assertIsDisplayed() }
}
step("Assert secondary amount is displayed") {
onStakingConfirmScreen { secondaryAmount.assertIsDisplayed() }
}
step("Assert 'Validator' block is displayed") {
onStakingConfirmScreen { validatorBlock.assertIsDisplayed() }
}
step("Assert 'Network Fee' block is displayed") {
onStakingConfirmScreen { networkFeeBlock.assertIsDisplayed() }
}
step("Assert 'Stake' button is displayed") {
onStakingConfirmScreen { stakeButton.assertIsDisplayed() }
step("Check 'Staking confirm' screen") {
checkStakingConfirmScreen()
}
}
}

View file

@ -2,12 +2,13 @@ package com.tangem.tests
import com.tangem.common.BaseTestCase
import com.tangem.common.constants.TestConstants.TOTAL_BALANCE
import com.tangem.common.extensions.SwipeDirection
import com.tangem.common.constants.TestConstants.WAIT_UNTIL_TIMEOUT
import com.tangem.common.extensions.clickWithAssertion
import com.tangem.common.extensions.swipeVertical
import com.tangem.common.utils.getWcUri
import com.tangem.common.utils.setClipboardText
import com.tangem.scenarios.*
import com.tangem.screens.*
import com.tangem.wallet.BuildConfig
import dagger.hilt.android.testing.HiltAndroidTest
import io.qameta.allure.kotlin.AllureId
import io.qameta.allure.kotlin.junit4.DisplayName
@ -21,7 +22,7 @@ class WalletConnectTest : BaseTestCase() {
@DisplayName("WC (React App): open session from deeplink on main screen")
@Ignore("TODO [REDACTED_JIRA] React app deeplink doesn't work")
@Test
fun openWalletConnectSessionOnMainScreen() {
fun openWalletConnectSessionOnMainScreenTest() {
val balance = TOTAL_BALANCE
val dAppName = "React App"
val deepLinkUri = getWcUri()
@ -37,19 +38,28 @@ class WalletConnectTest : BaseTestCase() {
openAppByDeepLink(deepLinkUri)
}
step("Check 'Wallet Connect' bottom sheet") {
checkWalletConnectBottomSheet()
flakySafely(WAIT_UNTIL_TIMEOUT) {
checkWalletConnectBottomSheet()
}
}
step("Assert 'Connect' button is enabled") {
onWalletConnectBottomSheet { connectButton.assertIsEnabled() }
}
step("Click on 'Connect' button") {
waitForIdle()
onWalletConnectBottomSheet { connectButton.performClick() }
}
step("Click 'More' button on TopBar") {
onTopBar { moreButton.clickWithAssertion() }
step("Assert 'Connect' button is not displayed") {
waitForIdle()
onWalletConnectBottomSheet { connectButton.assertIsNotDisplayed() }
}
step("Click on 'Wallet Connect' button") {
onDetailsScreen { walletConnectButton.clickWithAssertion() }
step("Open 'Wallet Connect' screen") {
openWalletConnectScreen()
}
step("Check 'Wallet Connect' screen") {
checkWalletConnectScreen()
step("Check 'Wallet Connect' screen with connections") {
flakySafely(WAIT_UNTIL_TIMEOUT) {
checkWalletConnectScreen(withConnections = true)
}
}
step("Click on app icon") {
onWalletConnectScreen { appIcon.performClick() }
@ -57,11 +67,11 @@ class WalletConnectTest : BaseTestCase() {
step("Check 'Wallet Connect' details bottom sheet") {
checkWalletConnectDetailsBottomSheet(dAppName)
}
step("Click on 'Disconnect button' is displayed") {
step("Click on 'Disconnect' button") {
onWalletConnectDetailsBottomSheet { disconnectButton.performClick() }
}
step("Assert connection is not displayed") {
onWalletConnectScreen { appName.assertIsNotDisplayed() }
step("Check 'Wallet Connect' screen without connections") {
checkWalletConnectScreen(withConnections = false)
}
}
}
@ -70,7 +80,7 @@ class WalletConnectTest : BaseTestCase() {
@DisplayName("WC (React App): open session from deeplink not on main screen")
@Ignore("TODO [REDACTED_JIRA] React app deeplink doesn't work")
@Test
fun openWalletConnectSessionNotOnMainScreen() {
fun openWalletConnectSessionNotOnMainScreenTest() {
val balance = TOTAL_BALANCE
val dAppName = "React App"
val deepLinkUri = getWcUri()
@ -82,41 +92,44 @@ class WalletConnectTest : BaseTestCase() {
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Click on 'Buy' button") {
onMainScreen { buyButton.clickWithAssertion() }
step("Open 'Wallet Connect' screen") {
openWalletConnectScreen()
checkWalletConnectScreen(false)
}
step("Create WC session buy deeplink") {
openAppByDeepLink(deepLinkUri)
}
step("Check 'Wallet Connect' bottom sheet") {
checkWalletConnectBottomSheet()
flakySafely(WAIT_UNTIL_TIMEOUT) {
checkWalletConnectBottomSheet()
}
}
step("Click on 'Connect' button") {
waitForIdle()
onWalletConnectBottomSheet { connectButton.performClick() }
}
step("Click 'More' button on TopBar") {
onTopBar { moreButton.clickWithAssertion() }
step("Assert 'Connect' button is not displayed") {
waitForIdle()
onWalletConnectBottomSheet { connectButton.assertIsNotDisplayed() }
}
step("Click on 'Wallet Connect' button") {
onDetailsScreen { walletConnectButton.clickWithAssertion() }
}
step("Assert 'Wallet Connect' bottom sheet is displayed") {
onWalletConnectBottomSheet { connectButton.clickWithAssertion() }
}
step("Check 'Wallet Connect' screen") {
checkWalletConnectScreen()
step("Check 'Wallet Connect' screen with connections") {
flakySafely(WAIT_UNTIL_TIMEOUT) {
checkWalletConnectScreen(withConnections = true)
}
}
step("Click on app icon") {
onWalletConnectScreen { appIcon.performClick() }
}
step("Check 'Wallet Connect' details bottom sheet") {
checkWalletConnectDetailsBottomSheet(dAppName)
flakySafely(WAIT_UNTIL_TIMEOUT) {
checkWalletConnectDetailsBottomSheet(dAppName)
}
}
step("Click on 'Disconnect button' is displayed") {
step("Click on 'Disconnect' button") {
onWalletConnectDetailsBottomSheet { disconnectButton.performClick() }
}
step("Assert connection is not displayed") {
onWalletConnectScreen { appName.assertIsNotDisplayed() }
step("Check 'Wallet Connect' screen without connections") {
checkWalletConnectScreen(withConnections = false)
}
}
}
@ -125,9 +138,10 @@ class WalletConnectTest : BaseTestCase() {
@DisplayName("WC (React App): open session from deeplink ")
@Ignore("TODO [REDACTED_JIRA] React app deeplink doesn't work")
@Test
fun openWalletConnectSession() {
fun openWalletConnectSessionTest() {
val balance = TOTAL_BALANCE
val dAppName = "React App"
val packageName = BuildConfig.APPLICATION_ID
val deepLinkUri = getWcUri()
setupHooks().run {
@ -137,32 +151,28 @@ class WalletConnectTest : BaseTestCase() {
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Open recent apps") {
device.uiDevice.pressRecentApps()
}
step("Stop app by swipe") {
swipeVertical(SwipeDirection.UP, startHeightRatio = 0.8f)
step("Kill app") {
device.apps.kill(packageName)
}
step("Create WC session buy deeplink") {
openAppByDeepLink(deepLinkUri)
}
step("Open 'Main Screen'") {
openMainScreen()
}
step("Check 'Wallet Connect' bottom sheet") {
checkWalletConnectBottomSheet()
flakySafely(WAIT_UNTIL_TIMEOUT) {
checkWalletConnectBottomSheet()
}
}
step("Click on 'Connect' button") {
onWalletConnectBottomSheet { connectButton.performClick() }
}
step("Click 'More' button on TopBar") {
onTopBar { moreButton.clickWithAssertion() }
step("Assert 'Connect' button is not displayed") {
onWalletConnectBottomSheet { connectButton.assertIsNotDisplayed() }
}
step("Click on 'Wallet Connect' button") {
onDetailsScreen { walletConnectButton.clickWithAssertion() }
step("Open 'Wallet Connect' screen") {
openWalletConnectScreen()
}
step("Check 'Wallet Connect' screen") {
checkWalletConnectScreen()
step("Check 'Wallet Connect' screen with connections") {
checkWalletConnectScreen(withConnections = true)
}
step("Click on app icon") {
onWalletConnectScreen { appIcon.performClick() }
@ -170,11 +180,72 @@ class WalletConnectTest : BaseTestCase() {
step("Check 'Wallet Connect' details bottom sheet") {
checkWalletConnectDetailsBottomSheet(dAppName)
}
step("Click on 'Disconnect button' is displayed") {
step("Click on 'Disconnect' button") {
onWalletConnectDetailsBottomSheet { disconnectButton.performClick() }
}
step("Assert connection is not displayed") {
onWalletConnectScreen { appName.assertIsNotDisplayed() }
step("Check 'Wallet Connect' screen without connections") {
checkWalletConnectScreen(withConnections = false)
}
}
}
@AllureId("887")
@DisplayName("WC: open session by 'Paste from clipboard' button")
@Ignore("TODO [REDACTED_JIRA] React app deeplink doesn't work")
@Test
fun openWalletConnectSessionByClipboardLinkTest() {
val balance = TOTAL_BALANCE
val dAppName = "React App"
val context = device.context
val deepLinkUri = getWcUri()
setupHooks().run {
step("Set URI to clipboard") {
setClipboardText(context, deepLinkUri)
}
step("Open 'Main Screen'") {
openMainScreen()
}
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Open 'Wallet Connect' screen") {
openWalletConnectScreen()
}
step("Click 'New connection' button") {
onWalletConnectScreen { newConnectionButton.performClick() }
}
step("CLick 'Paste from clipboard' button") {
onWalletConnectScanQrScreen { pasteFromClipboardButton.clickWithAssertion() }
}
step("Check 'Wallet Connect' bottom sheet") {
waitForIdle()
flakySafely(WAIT_UNTIL_TIMEOUT) {
checkWalletConnectBottomSheet()
}
}
step("Click on 'Connect' button") {
waitForIdle()
onWalletConnectBottomSheet { connectButton.performClick() }
}
step("Assert 'Connect' button is not displayed") {
waitForIdle()
onWalletConnectBottomSheet { connectButton.assertIsNotDisplayed() }
}
step("Check 'Wallet Connect' screen with connections") {
checkWalletConnectScreen(withConnections = true)
}
step("Click on app icon") {
onWalletConnectScreen { appIcon.performClick() }
}
step("Check 'Wallet Connect' details bottom sheet") {
checkWalletConnectDetailsBottomSheet(dAppName)
}
step("Click on 'Disconnect' button") {
onWalletConnectDetailsBottomSheet { disconnectButton.performClick() }
}
step("Check 'Wallet Connect' screen without connections") {
checkWalletConnectScreen(withConnections = false)
}
}
}

View file

@ -0,0 +1,405 @@
package com.tangem.tests.actionButtons
import androidx.compose.ui.test.longClick
import com.tangem.common.BaseTestCase
import com.tangem.common.constants.TestConstants.BITCOIN_ADDRESS
import com.tangem.common.constants.TestConstants.TOTAL_BALANCE
import com.tangem.common.extensions.clickWithAssertion
import com.tangem.common.utils.assertClipboardTextEquals
import com.tangem.common.utils.clearClipboard
import com.tangem.scenarios.openMainScreen
import com.tangem.scenarios.synchronizeAddresses
import com.tangem.screens.*
import com.tangem.screens.onTokenActionsBottomSheet
import com.tangem.screens.onBuyTokenDetailsScreen
import com.tangem.screens.onDialog
import com.tangem.screens.onMainScreen
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 MainScreenActionButtonsTest : BaseTestCase() {
@AllureId("79")
@DisplayName("Action buttons (long tap): validate UI")
@Test
fun actionButtonsValidateLongTapUiTest() {
val tokenTitle = "Ethereum"
val balance = TOTAL_BALANCE
setupHooks().run {
step("Open 'Main Screen'") {
openMainScreen()
}
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Long click on token with name: '$tokenTitle'") {
waitForIdle()
onMainScreen {
tokenWithTitleAndAddress(tokenTitle).performTouchInput {
longClick(
position = center,
durationMillis = 1000L
)
}
}
}
step("Assert 'Analytics' button is displayed") {
onTokenActionsBottomSheet { analyticsButton.assertIsDisplayed() }
}
step("Assert 'Copy address' button is displayed") {
onTokenActionsBottomSheet { copyAddressButton.assertIsDisplayed() }
}
step("Assert 'Receive' button is displayed") {
onTokenActionsBottomSheet { receiveButton.assertIsDisplayed() }
}
step("Assert 'Send' button is displayed") {
onTokenActionsBottomSheet { sendButton.assertIsDisplayed() }
}
step("Assert 'Swap' button is displayed") {
onTokenActionsBottomSheet { swapButton.assertIsDisplayed() }
}
step("Assert 'Buy' button is displayed") {
onTokenActionsBottomSheet { buyButton.assertIsDisplayed() }
}
step("Assert 'Sell' button is displayed") {
onTokenActionsBottomSheet { sellButton.assertIsDisplayed() }
}
step("Assert 'Hide token' button is displayed") {
onTokenActionsBottomSheet { hideTokenButton.assertIsDisplayed() }
}
}
}
@AllureId("84")
@DisplayName("Action buttons (long tap): check 'Copy address' button")
@Test
fun clickOnCopyAddressButtonTest() {
val tokenTitle = "Bitcoin"
val balance = TOTAL_BALANCE
val bitcoinAddress = BITCOIN_ADDRESS
setupHooks(
additionalBeforeSection = {
clearClipboard()
},
additionalAfterSection = {
clearClipboard()
}
).run {
step("Open 'Main Screen'") {
openMainScreen()
}
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Long click on token with name: '$tokenTitle'") {
waitForIdle()
onMainScreen {
tokenWithTitleAndAddress(tokenTitle).performTouchInput {
longClick(
position = center,
durationMillis = 1000L
)
}
}
}
step("Assert 'Copy address' button is displayed") {
onTokenActionsBottomSheet { copyAddressButton.assertIsDisplayed() }
}
step("Click on 'Copy address' button") {
onTokenActionsBottomSheet { copyAddressButton.performClick() }
}
step("Assert snack bar message is displayed") {
onMainScreen { snackbarCopiedAddressMessage.assertIsDisplayed() }
}
step("Check clipboard has '$tokenTitle' address '$bitcoinAddress'") {
waitForIdle()
assertClipboardTextEquals(expected = bitcoinAddress)
}
}
}
@AllureId("82")
@DisplayName("Action buttons (long tap): check 'Buy' button")
@Test
fun clickOnBuyButtonTest() {
val tokenTitle = "Bitcoin"
val tokenSymbol = "BTC"
val balance = TOTAL_BALANCE
setupHooks().run {
step("Open 'Main Screen'") {
openMainScreen()
}
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Long click on token with name: '$tokenTitle'") {
waitForIdle()
onMainScreen {
tokenWithTitleAndAddress(tokenTitle).performTouchInput {
longClick(
position = center,
durationMillis = 1000L
)
}
}
}
step("Assert 'Buy' button is displayed") {
onTokenActionsBottomSheet { buyButton.assertIsDisplayed() }
}
step("Click on 'Buy' button") {
onTokenActionsBottomSheet { buyButton.performClick() }
}
step("Click on 'Confirm' button in 'Dialog'") {
waitForIdle()
onDialog { confirmButton.clickWithAssertion() }
}
step("Assert top app bar title contains '$tokenTitle'") {
onBuyTokenDetailsScreen { topBarTitle.assertTextContains("Buy $tokenTitle") }
}
step("Assert fiat currency text field is displayed") {
onBuyTokenDetailsScreen { fiatAmountTextField.assertIsDisplayed() }
}
step("Assert fiat currency icon is displayed") {
onBuyTokenDetailsScreen { fiatCurrencyIcon.assertIsDisplayed() }
}
step("Assert token amount field is displayed") {
onBuyTokenDetailsScreen { tokenAmountField.assertTextContains(tokenSymbol, substring = true) }
}
step("Assert 'Continue' button") {
onBuyTokenDetailsScreen { continueButton.assertIsDisplayed() }
}
}
}
@AllureId("87")
@DisplayName("Action buttons (long tap): check 'Swap' button")
@Test
fun clickOnSwapButtonTest() {
val tokenTitle = "Ethereum"
val tokenSymbol = "ETH"
val balance = TOTAL_BALANCE
setupHooks().run {
step("Open 'Main Screen'") {
openMainScreen()
}
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Long click on token with name: '$tokenTitle'") {
waitForIdle()
onMainScreen {
tokenWithTitleAndAddress(tokenTitle).performTouchInput {
longClick(
position = center,
durationMillis = 1000L
)
}
}
}
step("Assert 'Swap' button is displayed") {
onTokenActionsBottomSheet { swapButton.assertIsDisplayed() }
}
step("Click on 'Swap' button") {
onTokenActionsBottomSheet { swapButton.performClick() }
}
step("Close 'Stories' screen") {
onSwapStoriesScreen { closeButton.clickWithAssertion() }
}
step("Assert 'Swap' screen title is displayed") {
onSwapTokenScreen { title.assertIsDisplayed() }
}
step("Assert token symbol: '$tokenSymbol' is displayed") {
onSwapTokenScreen { tokenSymbol(tokenSymbol).assertIsDisplayed() }
}
}
}
@AllureId("83")
@DisplayName("Action buttons (long tap): check 'Send' button")
@Test
fun clickOnSendButtonTest() {
val tokenTitle = "Ethereum"
val tokenSymbol = "ETH"
val balance = TOTAL_BALANCE
setupHooks().run {
step("Open 'Main Screen'") {
openMainScreen()
}
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Long click on token with name: '$tokenTitle'") {
waitForIdle()
onMainScreen {
tokenWithTitleAndAddress(tokenTitle).performTouchInput {
longClick(
position = center,
durationMillis = 1000L
)
}
}
}
step("Assert 'Send' button is displayed") {
onTokenActionsBottomSheet { sendButton.assertIsDisplayed() }
}
step("Click on 'Send' button") {
onTokenActionsBottomSheet { sendButton.performClick() }
}
step("Assert amount input text field contains token symbol: '$tokenSymbol'") {
onSendScreen {
amountInputTextField.assertTextContains(value = tokenSymbol, substring = true)
}
}
}
}
@AllureId("86")
@DisplayName("Action buttons (long tap): check 'Receive' button")
@Test
fun clickOnReceiveButtonTest() {
val tokenTitle = "Bitcoin"
val balance = TOTAL_BALANCE
setupHooks().run {
step("Open 'Main Screen'") {
openMainScreen()
}
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Long click on token with name: '$tokenTitle'") {
waitForIdle()
onMainScreen {
tokenWithTitleAndAddress(tokenTitle).performTouchInput {
longClick(
position = center,
durationMillis = 1000L
)
}
}
}
step("Assert 'Receive' button is displayed") {
onTokenActionsBottomSheet { receiveButton.assertIsDisplayed() }
}
step("Click on 'Receive' button") {
onTokenActionsBottomSheet { receiveButton.performClick() }
}
step("Assert 'Token receive warning' bottom sheet is displayed") {
onTokenReceiveWarningBottomSheet { bottomSheet.assertIsDisplayed() }
}
step("Click on 'Got it' button") {
onTokenReceiveWarningBottomSheet { gotItButton.performClick() }
}
step("Click on 'Show QR code' button") {
onReceiveAssetsBottomSheet { showQrCodeButton.clickWithAssertion() }
}
step("Assert bottom sheet with QR code title is displayed") {
onTokenReceiveQrCodeBottomSheet { title.assertIsDisplayed() }
}
step("Assert QR code is displayed") {
onTokenReceiveQrCodeBottomSheet { qrCode.assertIsDisplayed() }
}
step("Assert address title is displayed") {
onTokenReceiveQrCodeBottomSheet { addressTitle.assertIsDisplayed() }
}
step("Assert address is displayed") {
onTokenReceiveQrCodeBottomSheet { address.assertIsDisplayed() }
}
step("Assert 'Copy' button is displayed") {
onTokenReceiveQrCodeBottomSheet { copyButton.assertIsDisplayed() }
}
step("Assert 'Share' button is displayed") {
onTokenReceiveQrCodeBottomSheet { shareButton.assertIsDisplayed() }
}
}
}
@AllureId("85")
@DisplayName("Action buttons (long tap): check 'Sell' button")
@Test
fun clickOnSellButtonTest() {
val tokenTitle = "Ethereum"
val tokenSymbol = "ETH"
val balance = TOTAL_BALANCE
val url = "sell.moonpay.com"
val useWithoutAccount = "Use without an account"
setupHooks().run {
step("Open 'Main Screen'") {
openMainScreen()
}
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Long click on token with name: '$tokenTitle'") {
waitForIdle()
onMainScreen {
tokenWithTitleAndAddress(tokenTitle).performTouchInput {
longClick(
position = center,
durationMillis = 1000L
)
}
}
}
step("Assert 'Receive' button is displayed") {
onTokenActionsBottomSheet { sellButton.assertIsDisplayed() }
}
step("Click on 'Receive' button") {
onTokenActionsBottomSheet { sellButton.performClick() }
}
step("Assert Chrome Browser is opened") {
ChromeBrowserPageObject { assertChromeIsOpened() }
}
if (ChromeBrowserPageObject.isElementWithTextExists(useWithoutAccount)) {
step("Click on '$useWithoutAccount' button on Chrome browser") {
ChromeBrowserPageObject { clickOnElementWithText(useWithoutAccount) }
}
}
step("Assert url contains: '$url'") {
ChromeBrowserPageObject { assertUrlContains(url) }
}
step("Assert token symbol '$tokenSymbol' is displayed") {
ChromeBrowserPageObject { assertElementWithTextExists(tokenSymbol) }
}
}
}
@AllureId("77")
@DisplayName("Action buttons (long tap): assert 'Sell' button is not displayed if token doesn't support it")
@Test
fun assertSellButtonIsNotDisplayedTest() {
val tokenTitle = "Bitcoin"
val balance = TOTAL_BALANCE
setupHooks().run {
step("Open 'Main Screen'") {
openMainScreen()
}
step("Synchronize addresses") {
synchronizeAddresses(balance)
}
step("Long click on token with name: '$tokenTitle'") {
waitForIdle()
onMainScreen {
tokenWithTitleAndAddress(tokenTitle).performTouchInput {
longClick(
position = center,
durationMillis = 1000L
)
}
}
}
step("Assert 'Sell' button is not displayed") {
onTokenActionsBottomSheet { sellButton.assertIsNotDisplayed() }
}
}
}
}

View file

@ -162,7 +162,7 @@ class TotalBalanceUpdateTest : BaseTestCase() {
}
}
step("Click 'Hide token' button") {
onBottomSheet { hideButton.clickWithAssertion() }
onTokenActionsBottomSheet { hideTokenButton.clickWithAssertion() }
}
step("Click 'Hide' button in dialog") {
onDialog {

View file

@ -67,7 +67,11 @@ internal class DefaultTangemPayStorage @Inject constructor(
secureStorage.get(createOrderIdKey(customerWalletAddress))?.decodeToString(throwOnInvalidSequence = true)
}
override suspend fun clear(customerWalletAddress: String) = withContext(dispatcherProvider.io) {
override suspend fun clearOrderId(customerWalletAddress: String) = withContext(dispatcherProvider.io) {
secureStorage.delete(createOrderIdKey(customerWalletAddress))
}
override suspend fun clearAll(customerWalletAddress: String) = withContext(dispatcherProvider.io) {
secureStorage.delete(createKey(customerWalletAddress))
secureStorage.delete(createOrderIdKey(customerWalletAddress))
}

View file

@ -49,8 +49,12 @@ internal object AccountDomainModule {
@Singleton
fun provideRecoverCryptoPortfolioUseCase(
accountsCRUDRepository: AccountsCRUDRepository,
mainAccountTokensMigration: MainAccountTokensMigration,
): RecoverCryptoPortfolioUseCase {
return RecoverCryptoPortfolioUseCase(crudRepository = accountsCRUDRepository)
return RecoverCryptoPortfolioUseCase(
crudRepository = accountsCRUDRepository,
mainAccountTokensMigration = mainAccountTokensMigration,
)
}
@Provides

View file

@ -16,7 +16,7 @@ import com.tangem.domain.wallets.legacy.UserWalletsListManager
import com.tangem.domain.wallets.repository.WalletNamesMigrationRepository
import com.tangem.domain.wallets.repository.WalletsRepository
import com.tangem.domain.wallets.usecase.*
import com.tangem.domain.yield.supply.YieldSupplyMarketRepository
import com.tangem.domain.yield.supply.YieldSupplyRepository
import com.tangem.domain.yield.supply.usecase.YieldSupplyApyFlowUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyApyUpdateUseCase
import com.tangem.feature.wallet.presentation.wallet.domain.IsWalletNFTEnabledSyncUseCase
@ -454,21 +454,17 @@ internal object WalletsDomainModule {
@Provides
@Singleton
fun provideYieldSupplyApyFlowUseCase(
yieldSupplyMarketRepository: YieldSupplyMarketRepository,
): YieldSupplyApyFlowUseCase {
fun provideYieldSupplyApyFlowUseCase(yieldSupplyRepository: YieldSupplyRepository): YieldSupplyApyFlowUseCase {
return YieldSupplyApyFlowUseCase(
yieldSupplyMarketRepository = yieldSupplyMarketRepository,
yieldSupplyRepository = yieldSupplyRepository,
)
}
@Provides
@Singleton
fun provideYieldSupplyApyUpdateUseCase(
yieldSupplyMarketRepository: YieldSupplyMarketRepository,
): YieldSupplyApyUpdateUseCase {
fun provideYieldSupplyApyUpdateUseCase(yieldSupplyRepository: YieldSupplyRepository): YieldSupplyApyUpdateUseCase {
return YieldSupplyApyUpdateUseCase(
yieldSupplyMarketRepository = yieldSupplyMarketRepository,
yieldSupplyRepository = yieldSupplyRepository,
)
}
}

View file

@ -4,7 +4,7 @@ import com.tangem.domain.blockaid.BlockAidGasEstimate
import com.tangem.domain.transaction.FeeRepository
import com.tangem.domain.transaction.error.FeeErrorResolver
import com.tangem.domain.yield.supply.YieldSupplyErrorResolver
import com.tangem.domain.yield.supply.YieldSupplyMarketRepository
import com.tangem.domain.yield.supply.YieldSupplyRepository
import com.tangem.domain.yield.supply.YieldSupplyTransactionRepository
import com.tangem.domain.yield.supply.usecase.*
import dagger.Module
@ -82,30 +82,54 @@ internal object YieldSupplyDomainModule {
@Provides
@Singleton
fun provideYieldSupplyGetTokenStatusUseCase(
yieldSupplyMarketRepository: YieldSupplyMarketRepository,
yieldSupplyRepository: YieldSupplyRepository,
): YieldSupplyGetTokenStatusUseCase {
return YieldSupplyGetTokenStatusUseCase(
yieldSupplyMarketRepository = yieldSupplyMarketRepository,
yieldSupplyRepository = yieldSupplyRepository,
)
}
@Provides
@Singleton
fun provideYieldSupplyGetApyUseCase(
yieldSupplyMarketRepository: YieldSupplyMarketRepository,
): YieldSupplyGetApyUseCase {
fun provideYieldSupplyGetApyUseCase(yieldSupplyRepository: YieldSupplyRepository): YieldSupplyGetApyUseCase {
return YieldSupplyGetApyUseCase(
yieldSupplyMarketRepository = yieldSupplyMarketRepository,
yieldSupplyRepository = yieldSupplyRepository,
)
}
@Provides
@Singleton
fun provideYieldSupplyGetChartUseCase(
yieldSupplyMarketRepository: YieldSupplyMarketRepository,
): YieldSupplyGetChartUseCase {
fun provideYieldSupplyGetChartUseCase(yieldSupplyRepository: YieldSupplyRepository): YieldSupplyGetChartUseCase {
return YieldSupplyGetChartUseCase(
yieldSupplyMarketRepository = yieldSupplyMarketRepository,
yieldSupplyRepository = yieldSupplyRepository,
)
}
@Provides
@Singleton
fun provideYieldSupplyIsAvailableUseCase(
yieldSupplyRepository: YieldSupplyRepository,
): YieldSupplyIsAvailableUseCase {
return YieldSupplyIsAvailableUseCase(
yieldSupplyRepository = yieldSupplyRepository,
)
}
@Provides
@Singleton
fun provideYieldSupplyActivateUseCase(yieldSupplyRepository: YieldSupplyRepository): YieldSupplyActivateUseCase {
return YieldSupplyActivateUseCase(
yieldSupplyRepository = yieldSupplyRepository,
)
}
@Provides
@Singleton
fun provideYieldSupplyDeactivateUseCase(
yieldSupplyRepository: YieldSupplyRepository,
): YieldSupplyDeactivateUseCase {
return YieldSupplyDeactivateUseCase(
yieldSupplyRepository = yieldSupplyRepository,
)
}
}

View file

@ -160,4 +160,6 @@ internal val Blockchain.moonPaySupportedCurrency: MoonPaySupportedCurrency?
Pepecoin, PepecoinTestnet -> null
Hyperliquid, HyperliquidTestnet -> null
Quai, QuaiTestnet -> null
Linea, LineaTestnet -> null
ArbitrumNova -> null
}

View file

@ -2,6 +2,7 @@ package com.tangem.tap.routing.utils
import com.tangem.common.routing.AppRoute
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.domain.models.PortfolioId
import com.tangem.domain.qrscanning.models.SourceType
import com.tangem.feature.qrscanning.QrScanningComponent
import com.tangem.feature.referral.api.ReferralComponent
@ -12,6 +13,7 @@ import com.tangem.features.account.AccountCreateEditComponent
import com.tangem.features.account.AccountDetailsComponent
import com.tangem.features.account.ArchivedAccountListComponent
import com.tangem.features.createwalletselection.CreateWalletSelectionComponent
import com.tangem.features.createwalletstart.CreateWalletStartComponent
import com.tangem.features.details.component.DetailsComponent
import com.tangem.features.disclaimer.api.components.DisclaimerComponent
import com.tangem.features.home.api.HomeComponent
@ -19,6 +21,7 @@ import com.tangem.features.hotwallet.*
import com.tangem.features.kyc.KycComponent
import com.tangem.features.managetokens.component.ChooseManagedTokensComponent
import com.tangem.features.managetokens.component.ManageTokensComponent
import com.tangem.features.managetokens.component.ManageTokensMode
import com.tangem.features.managetokens.component.ManageTokensSource
import com.tangem.features.markets.details.MarketsTokenDetailsComponent
import com.tangem.features.markets.tokenlist.MarketsTokenListComponent
@ -97,6 +100,7 @@ internal class ChildFactory @Inject constructor(
private val usedeskComponentFactory: UsedeskComponent.Factory,
private val chooseManagedTokensComponentFactory: ChooseManagedTokensComponent.Factory,
private val createWalletSelectionComponentFactory: CreateWalletSelectionComponent.Factory,
private val createWalletStartComponentFactory: CreateWalletStartComponent.Factory,
private val createMobileWalletComponentFactory: CreateMobileWalletComponent.Factory,
private val upgradeWalletComponentFactory: UpgradeWalletComponent.Factory,
private val addExistingWalletComponentFactory: AddExistingWalletComponent.Factory,
@ -140,9 +144,15 @@ internal class ChildFactory @Inject constructor(
AppRoute.ManageTokens.Source.STORIES -> ManageTokensSource.STORIES
}
val mode = when (val portfolio = route.portfolioId) {
is PortfolioId.Account -> ManageTokensMode.Account(portfolio.accountId)
is PortfolioId.Wallet -> ManageTokensMode.Wallet(portfolio.userWalletId)
null -> ManageTokensMode.None
}
createComponentChild(
context = context,
params = ManageTokensComponent.Params(route.userWalletId, source),
params = ManageTokensComponent.Params(mode, source),
componentFactory = manageTokensComponentFactory,
)
}
@ -200,7 +210,7 @@ internal class ChildFactory @Inject constructor(
createComponentChild(
context = context,
params = OnrampComponent.Params(
userWalletId = route.portfolioId.userWalletId, // todo account portfolioId param,
userWalletId = route.userWalletId,
cryptoCurrency = route.currency,
source = route.source,
shouldLaunchSepa = route.shouldLaunchSepa,
@ -274,7 +284,7 @@ internal class ChildFactory @Inject constructor(
createComponentChild(
context = context,
params = TokenDetailsComponent.Params(
userWalletId = route.portfolioId.userWalletId, // todo account portfolioId param
userWalletId = route.userWalletId,
currency = route.currency,
),
componentFactory = tokenDetailsComponentFactory,
@ -284,7 +294,7 @@ internal class ChildFactory @Inject constructor(
createComponentChild(
context = context,
params = StakingComponent.Params(
userWalletId = route.portfolioId.userWalletId, // todo account portfolioId param,
userWalletId = route.userWalletId,
cryptoCurrencyId = route.cryptoCurrencyId,
yieldId = route.yieldId,
),
@ -297,7 +307,7 @@ internal class ChildFactory @Inject constructor(
params = SwapComponent.Params(
currencyFrom = route.currencyFrom,
currencyTo = route.currencyTo,
userWalletId = route.portfolioId.userWalletId, // todo account portfolioId param,
userWalletId = route.userWalletId,
isInitialReverseOrder = route.isInitialReverseOrder,
screenSource = route.screenSource,
),
@ -308,7 +318,7 @@ internal class ChildFactory @Inject constructor(
createComponentChild(
context = context,
params = SendComponent.Params(
userWalletId = route.portfolioId.userWalletId, // todo account portfolioId param,
userWalletId = route.userWalletId,
currency = route.currency,
transactionId = route.transactionId,
amount = route.amount,
@ -468,6 +478,19 @@ internal class ChildFactory @Inject constructor(
componentFactory = chooseManagedTokensComponentFactory,
)
}
is AppRoute.CreateWalletStart -> {
val mode = when (route.mode) {
AppRoute.CreateWalletStart.Mode.ColdWallet -> CreateWalletStartComponent.Mode.ColdWallet
AppRoute.CreateWalletStart.Mode.HotWallet -> CreateWalletStartComponent.Mode.HotWallet
}
createComponentChild(
context = context,
params = CreateWalletStartComponent.Params(
mode = mode,
),
componentFactory = createWalletStartComponentFactory,
)
}
is AppRoute.CreateWalletSelection -> {
createComponentChild(
context = context,