Updated on 2026-08-14
This commit is contained in:
parent
8ea23a2dd7
commit
4f1710d77c
23 changed files with 884 additions and 29 deletions
|
|
@ -18,6 +18,7 @@ import com.kaspersky.kaspresso.testcases.api.testcase.TestCase
|
|||
import com.tangem.common.allure.FailedStepScreenshotInterceptor
|
||||
import com.tangem.common.constants.TestConstants.ALLURE_LABEL_NAME
|
||||
import com.tangem.common.constants.TestConstants.ALLURE_LABEL_VALUE
|
||||
import com.tangem.common.constants.TestConstants.WAIT_UNTIL_TIMEOUT
|
||||
import com.tangem.common.rules.ApiEnvironmentRule
|
||||
import com.tangem.datasource.api.common.config.managers.ApiConfigsManager
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
|
|
@ -179,6 +180,14 @@ abstract class BaseTestCase : TestCase(
|
|||
|
||||
fun waitForIdle() = composeTestRule.waitForIdle()
|
||||
|
||||
/**
|
||||
* Waits until [block] stops throwing (or [timeoutMillis] elapses). Use in scenario (BaseTestCase extension)
|
||||
* code where flakySafely is unavailable; in test bodies prefer flakySafely.
|
||||
*/
|
||||
fun awaitSuccess(timeoutMillis: Long = WAIT_UNTIL_TIMEOUT, block: () -> Unit) {
|
||||
composeTestRule.waitUntil(timeoutMillis = timeoutMillis) { runCatching(block).isSuccess }
|
||||
}
|
||||
|
||||
private fun applicationInjectionRule(): ApplicationInjectionExecutionRule {
|
||||
return ApplicationInjectionExecutionRule(
|
||||
toggleStates = mapOf(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
package com.tangem.common.utils
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import com.google.zxing.BinaryBitmap
|
||||
import com.google.zxing.DecodeHintType
|
||||
import com.google.zxing.RGBLuminanceSource
|
||||
import com.google.zxing.common.HybridBinarizer
|
||||
import com.google.zxing.qrcode.QRCodeReader
|
||||
|
||||
/** Decodes the text encoded in a QR-code [bitmap] (e.g. captured from a Compose node via captureToImage). */
|
||||
fun decodeQrCode(bitmap: Bitmap): String {
|
||||
val width = bitmap.width
|
||||
val height = bitmap.height
|
||||
val pixels = IntArray(width * height)
|
||||
bitmap.getPixels(pixels, 0, width, 0, 0, width, height)
|
||||
|
||||
val source = RGBLuminanceSource(width, height, pixels)
|
||||
val binaryBitmap = BinaryBitmap(HybridBinarizer(source))
|
||||
val hints = mapOf(DecodeHintType.TRY_HARDER to true)
|
||||
|
||||
return QRCodeReader().decode(binaryBitmap, hints).text
|
||||
}
|
||||
|
|
@ -61,6 +61,19 @@ fun BaseTestCase.openMainScreen(
|
|||
}
|
||||
}
|
||||
|
||||
/** Opens the main screen, synchronizes addresses, and opens the details of the token with [tokenName]. */
|
||||
fun BaseTestCase.openTokenDetails(tokenName: String) {
|
||||
step("Open 'Main Screen'") {
|
||||
openMainScreen()
|
||||
}
|
||||
step("Synchronize addresses") {
|
||||
synchronizeAddresses()
|
||||
}
|
||||
step("Click on token with name: '$tokenName'") {
|
||||
onMainScreen { tokenWithTitleAndAddress(tokenName).clickWithAssertion() }
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTestApi::class)
|
||||
fun BaseTestCase.openMainScreenWithExistingHotWallet(seedPhrase: String, accessCode: String = "") {
|
||||
step("Click on 'Get started' button") {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package com.tangem.scenarios
|
||||
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.common.constants.TestConstants.WAIT_UNTIL_TIMEOUT
|
||||
import com.tangem.common.extensions.clickWithAssertion
|
||||
import com.tangem.common.extensions.performTextInputInChunks
|
||||
import com.tangem.screens.accounts.onAccountDetailsScreen
|
||||
|
|
@ -16,11 +15,6 @@ import com.tangem.core.res.R as CoreResR
|
|||
|
||||
private fun mainAccountName(): String = getResourceString(CoreResR.string.account_main_account_title)
|
||||
|
||||
// flakySafely is unavailable in BaseTestCase extensions — wait until the assertion/action stops throwing.
|
||||
private fun BaseTestCase.awaitSuccess(block: () -> Unit) {
|
||||
composeTestRule.waitUntil(timeoutMillis = WAIT_UNTIL_TIMEOUT) { runCatching(block).isSuccess }
|
||||
}
|
||||
|
||||
fun BaseTestCase.openManageTokens(accountName: String = mainAccountName()) {
|
||||
openWalletSettingsScreen()
|
||||
openAccountDetails(accountName)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,58 @@
|
|||
package com.tangem.scenarios
|
||||
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.common.constants.TestConstants.WAIT_UNTIL_TIMEOUT_LONG
|
||||
import com.tangem.common.extensions.clickWithAssertion
|
||||
import com.tangem.common.extensions.extractText
|
||||
import com.tangem.common.utils.decodeQrCode
|
||||
import com.tangem.screens.onAddFundsBottomSheet
|
||||
import com.tangem.screens.onReceiveAssetsBottomSheet
|
||||
import com.tangem.screens.onTokenDetailsScreen
|
||||
import com.tangem.screens.onTokenReceiveQrCodeBottomSheet
|
||||
import com.tangem.screens.onTokenReceiveWarningBottomSheet
|
||||
import io.qameta.allure.kotlin.Allure.step
|
||||
import org.junit.Assert
|
||||
|
||||
/** Opens the receive flow from a funded token's details via 'Add funds' → 'Receive'. */
|
||||
fun BaseTestCase.openReceiveViaAddFunds() {
|
||||
step("Click on 'Add funds' button") {
|
||||
onTokenDetailsScreen { addFundsButton.clickWithAssertion() }
|
||||
}
|
||||
step("Click on 'Receive' button in bottom sheet") {
|
||||
onAddFundsBottomSheet { receiveButton.clickWithAssertion() }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts the QR code encodes the displayed address for both address types of a two-address-type coin,
|
||||
* and that the two addresses differ.
|
||||
*/
|
||||
fun BaseTestCase.assertQrCodesMatchForBothAddressTypes() {
|
||||
step("Go to QR code bottom sheet for the first address type") {
|
||||
goToQrCodeBottomSheet()
|
||||
}
|
||||
var firstAddress = ""
|
||||
step("Assert QR code encodes the first displayed address") {
|
||||
firstAddress = assertQrCodeEncodesDisplayedAddress()
|
||||
}
|
||||
step("Go back to the receive addresses") {
|
||||
device.uiDevice.pressBack()
|
||||
}
|
||||
step("Switch to the second address type") {
|
||||
awaitSuccess(WAIT_UNTIL_TIMEOUT_LONG) { onReceiveAssetsBottomSheet { addressesPager.assertIsDisplayed() } }
|
||||
onReceiveAssetsBottomSheet { scrollToAddress(1) }
|
||||
}
|
||||
step("Click on 'Show QR code' button for the second address type") {
|
||||
onReceiveAssetsBottomSheet { showQrCodeButton(1).clickWithAssertion() }
|
||||
}
|
||||
var secondAddress = ""
|
||||
step("Assert QR code encodes the second displayed address") {
|
||||
secondAddress = assertQrCodeEncodesDisplayedAddress()
|
||||
}
|
||||
step("Assert the two address types are different") {
|
||||
Assert.assertNotEquals(firstAddress, secondAddress)
|
||||
}
|
||||
}
|
||||
|
||||
fun BaseTestCase.goToQrCodeBottomSheet() {
|
||||
step("Assert 'Token receive warning' bottom sheet is displayed") {
|
||||
|
|
@ -15,7 +62,7 @@ fun BaseTestCase.goToQrCodeBottomSheet() {
|
|||
onTokenReceiveWarningBottomSheet { gotItButton.performClick() }
|
||||
}
|
||||
step("Click on 'Show QR code' button") {
|
||||
onReceiveAssetsBottomSheet { showQrCodeButton.clickWithAssertion() }
|
||||
onReceiveAssetsBottomSheet { showQrCodeButton().clickWithAssertion() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -39,3 +86,16 @@ fun BaseTestCase.checkQrCodeBottomSheetScenario() {
|
|||
onTokenReceiveQrCodeBottomSheet { shareButton.assertIsDisplayed() }
|
||||
}
|
||||
}
|
||||
|
||||
/** Decodes the QR code on the receive bottom sheet and asserts it encodes the displayed address; returns that address. */
|
||||
fun BaseTestCase.assertQrCodeEncodesDisplayedAddress(): String {
|
||||
var displayedAddress = ""
|
||||
step("Assert QR code encodes the displayed address") {
|
||||
onTokenReceiveQrCodeBottomSheet {
|
||||
displayedAddress = address.extractText()
|
||||
val decoded = decodeQrCode(captureQrCodeBitmap())
|
||||
Assert.assertEquals(displayedAddress, decoded)
|
||||
}
|
||||
}
|
||||
return displayedAddress
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
package com.tangem.screens
|
||||
|
||||
import androidx.compose.ui.test.ExperimentalTestApi
|
||||
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.test.TokenReceiveAssetsBottomSheetTestTags
|
||||
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
|
||||
|
|
@ -11,10 +13,23 @@ import io.github.kakaocup.kakao.common.utilities.getResourceString
|
|||
class ReceiveAssetsBottomSheetPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
|
||||
ComposeScreen<ReceiveAssetsBottomSheetPageObject>(semanticsProvider = semanticsProvider) {
|
||||
|
||||
val showQrCodeButton: KNode = child {
|
||||
/** 'Show QR code' button of the address at [index]; both pager cards stay composed, so match by position. */
|
||||
fun showQrCodeButton(index: Int = 0): KNode = child {
|
||||
hasText(getResourceString(R.string.token_receive_show_qr_code_title))
|
||||
hasPosition(index)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val addressesPager: KNode = child {
|
||||
hasTestTag(TokenReceiveAssetsBottomSheetTestTags.ADDRESSES_PAGER)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
/** Pages the addresses carousel to the address of the given [index]. */
|
||||
@OptIn(ExperimentalTestApi::class)
|
||||
fun scrollToAddress(index: Int) {
|
||||
addressesPager { performScrollToIndex(index) }
|
||||
}
|
||||
}
|
||||
|
||||
internal fun BaseTestCase.onReceiveAssetsBottomSheet(function: ReceiveAssetsBottomSheetPageObject.() -> Unit) =
|
||||
|
|
|
|||
|
|
@ -118,6 +118,11 @@ class TokenDetailsPageObject(semanticsProvider: SemanticsNodeInteractionsProvide
|
|||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
/** 'Receive' row of the zero-balance actions block (Buy / Swap / Receive), shown instead of the action buttons. */
|
||||
val receiveButton: KNode = child {
|
||||
hasText(getResourceString(R.string.common_receive))
|
||||
}
|
||||
|
||||
fun networkFeeNotificationIcon(feeCurrencyName: String): KNode = child {
|
||||
hasAnySibling(withText(getResourceString(R.string.warning_send_blocked_funds_for_fee_title, feeCurrencyName)))
|
||||
hasTestTag(NotificationTestTags.ICON)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
package com.tangem.screens
|
||||
|
||||
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.core.ui.test.TokenMarketBlockTestTags
|
||||
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
|
||||
|
||||
class TokenMarketBlockPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
|
||||
ComposeScreen<TokenMarketBlockPageObject>(semanticsProvider = semanticsProvider) {
|
||||
|
||||
val block: KNode = child {
|
||||
hasTestTag(TokenMarketBlockTestTags.BLOCK)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val title: KNode = child {
|
||||
hasTestTag(TokenMarketBlockTestTags.TITLE)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val price: KNode = child {
|
||||
hasTestTag(TokenMarketBlockTestTags.PRICE)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val priceChange: KNode = child {
|
||||
hasTestTag(TokenMarketBlockTestTags.PRICE_CHANGE)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val chart: KNode = child {
|
||||
hasTestTag(TokenMarketBlockTestTags.CHART)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
}
|
||||
|
||||
internal fun BaseTestCase.onTokenMarketBlock(function: TokenMarketBlockPageObject.() -> Unit) =
|
||||
onComposeScreen(composeTestRule, function)
|
||||
|
|
@ -1,11 +1,15 @@
|
|||
package com.tangem.screens
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import androidx.compose.ui.graphics.asAndroidBitmap
|
||||
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
|
||||
import androidx.compose.ui.test.captureToImage
|
||||
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.intercept.operation.ComposeOperationType
|
||||
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
|
||||
|
|
@ -50,6 +54,17 @@ class TokenReceiveQrCodeBottomSheetPageObject(semanticsProvider: SemanticsNodeIn
|
|||
hasText(getResourceString(R.string.common_share))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
/** Captures the QR code node as a bitmap via the Kakao node delegate (no raw composeTestRule access). */
|
||||
fun captureQrCodeBitmap(): Bitmap {
|
||||
lateinit var bitmap: Bitmap
|
||||
qrCode.delegate.perform(QrCodeAction.CAPTURE) {
|
||||
bitmap = captureToImage().asAndroidBitmap()
|
||||
}
|
||||
return bitmap
|
||||
}
|
||||
|
||||
private enum class QrCodeAction : ComposeOperationType { CAPTURE }
|
||||
}
|
||||
|
||||
internal fun BaseTestCase.onTokenReceiveQrCodeBottomSheet(function: TokenReceiveQrCodeBottomSheetPageObject.() -> Unit) =
|
||||
|
|
|
|||
|
|
@ -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.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
|
||||
|
|
@ -18,9 +17,7 @@ class TokenReceiveWarningBottomSheetPageObject(semanticsProvider: SemanticsNodeI
|
|||
}
|
||||
|
||||
val gotItButton: KNode = child {
|
||||
hasTestTag(BaseButtonTestTags.TEXT)
|
||||
hasText(getResourceString(R.string.common_got_it))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,16 @@ class TxHistoryPageObject(semanticsProvider: SemanticsNodeInteractionsProvider)
|
|||
hasTestTag(TransactionHistoryItemTestTags.STATUS_CONFIRMED)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
fun transactionUnconfirmedStatus(title: String): KNode = transactionItem(title).child {
|
||||
hasTestTag(TransactionHistoryItemTestTags.STATUS_UNCONFIRMED)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
fun transactionAddress(title: String, address: String): KNode = transactionItem(title).child {
|
||||
hasText(text = address, substring = true)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
}
|
||||
|
||||
internal fun BaseTestCase.onTxHistoryScreen(function: TxHistoryPageObject.() -> Unit) =
|
||||
|
|
|
|||
|
|
@ -1,23 +1,39 @@
|
|||
package com.tangem.tests.actionButtons
|
||||
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.common.constants.TestConstants.QUOTES_API_SCENARIO
|
||||
import com.tangem.common.constants.TestConstants.SVS_SEED_PHRASE_12
|
||||
import com.tangem.common.constants.TestConstants.USER_TOKENS_API_SCENARIO
|
||||
import com.tangem.common.constants.TestConstants.WAIT_UNTIL_TIMEOUT
|
||||
import com.tangem.common.constants.TestConstants.WAIT_UNTIL_TIMEOUT_LONG
|
||||
import com.tangem.common.constants.TestConstants.XRP_RECIPIENT_ADDRESS
|
||||
import com.tangem.common.extensions.clickWithAssertion
|
||||
import com.tangem.common.extensions.pullToRefresh
|
||||
import com.tangem.common.utils.resetWireMockScenarioState
|
||||
import com.tangem.common.utils.setWireMockScenarioState
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.scenarios.checkQrCodeBottomSheetScenario
|
||||
import com.tangem.scenarios.enterAmountAndOpenSendConfirm
|
||||
import com.tangem.scenarios.goToQrCodeBottomSheet
|
||||
import com.tangem.scenarios.openMainScreen
|
||||
import com.tangem.scenarios.openSendFromTokenDetails
|
||||
import com.tangem.scenarios.openSendScreenWithHotWallet
|
||||
import com.tangem.scenarios.openSendSuccessScreenViaLongClickOnSendButton
|
||||
import com.tangem.scenarios.readNetworkFeeAmount
|
||||
import com.tangem.scenarios.synchronizeAddresses
|
||||
import com.tangem.scenarios.waitUntilNetworkFeeIsStable
|
||||
import com.tangem.screens.onAddFundsBottomSheet
|
||||
import com.tangem.screens.onDialog
|
||||
import com.tangem.screens.onMainScreen
|
||||
import com.tangem.screens.onSendScreen
|
||||
import com.tangem.screens.onSendSuccessScreen
|
||||
import com.tangem.screens.onSwapStoriesScreen
|
||||
import com.tangem.screens.onSwapTokenScreen
|
||||
import com.tangem.screens.onTokenDetailsScreen
|
||||
import com.tangem.screens.onTransferBottomSheet
|
||||
import com.tangem.screens.onTxHistoryScreen
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import io.github.kakaocup.kakao.common.utilities.getResourceString
|
||||
import io.qameta.allure.kotlin.AllureId
|
||||
import io.qameta.allure.kotlin.junit4.DisplayName
|
||||
import org.junit.Ignore
|
||||
|
|
@ -259,4 +275,146 @@ class TokenDetailsScreenActionButtonsTest : BaseTestCase() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AllureId("4465")
|
||||
@DisplayName("Action buttons (token details screen): 'Send' blocked while a transaction is active, works after completion")
|
||||
@Test
|
||||
fun sendBlockedWhileTransactionActiveTest() {
|
||||
val tokenName = "XRP Ledger"
|
||||
val amount = "1"
|
||||
val userTokensState = "XRPHotWalletSvS"
|
||||
val quotesState = "Ripple"
|
||||
val startedState = "Started"
|
||||
val rippleAccountInfoScenario = "ripple_account_info"
|
||||
val pendingSendMessagePrefix =
|
||||
getResourceString(R.string.token_button_unavailability_reason_pending_transaction_send).substringBefore("%")
|
||||
|
||||
setupHooks(
|
||||
additionalAfterSection = {
|
||||
resetWireMockScenarioState(USER_TOKENS_API_SCENARIO)
|
||||
resetWireMockScenarioState(QUOTES_API_SCENARIO)
|
||||
resetWireMockScenarioState(rippleAccountInfoScenario)
|
||||
},
|
||||
).run {
|
||||
step("Set WireMock scenario: '$USER_TOKENS_API_SCENARIO' to state: '$userTokensState'") {
|
||||
setWireMockScenarioState(scenarioName = USER_TOKENS_API_SCENARIO, state = userTokensState)
|
||||
}
|
||||
step("Set WireMock scenario: '$QUOTES_API_SCENARIO' to state: '$quotesState'") {
|
||||
setWireMockScenarioState(scenarioName = QUOTES_API_SCENARIO, state = quotesState)
|
||||
}
|
||||
step("Set WireMock scenario: '$rippleAccountInfoScenario' to state: '$startedState'") {
|
||||
setWireMockScenarioState(scenarioName = rippleAccountInfoScenario, state = startedState)
|
||||
}
|
||||
step("Open the send flow for '$tokenName' on an existing hot wallet") {
|
||||
openSendScreenWithHotWallet(seedPhrase = SVS_SEED_PHRASE_12, tokenName = tokenName)
|
||||
}
|
||||
step("Enter amount '$amount' and open the 'Send confirm' screen") {
|
||||
enterAmountAndOpenSendConfirm(amount = amount, recipientAddress = XRP_RECIPIENT_ADDRESS)
|
||||
}
|
||||
waitUntilNetworkFeeIsStable { readNetworkFeeAmount() }
|
||||
step("Sign, send and open the 'Transaction sent' screen") {
|
||||
openSendSuccessScreenViaLongClickOnSendButton()
|
||||
}
|
||||
step("Click on 'Close' button") {
|
||||
onSendSuccessScreen { closeButton.clickWithAssertion() }
|
||||
}
|
||||
step("Assert 'Token details' screen is displayed") {
|
||||
onTokenDetailsScreen { screenContainer.assertIsDisplayed() }
|
||||
}
|
||||
step("Open the transfer bottom sheet") {
|
||||
onTokenDetailsScreen { transferButton.clickWithAssertion() }
|
||||
}
|
||||
step("Assert 'Send' button is not enabled while the transaction is active") {
|
||||
flakySafely(WAIT_UNTIL_TIMEOUT_LONG) {
|
||||
onTransferBottomSheet { sendButton.assertIsNotEnabled() }
|
||||
}
|
||||
}
|
||||
step("Click on 'Send' button") {
|
||||
onTransferBottomSheet { sendButton.performClick() }
|
||||
}
|
||||
step("Assert pending-transaction notification dialog is displayed") {
|
||||
onDialog { containerWithText(pendingSendMessagePrefix).assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Send' screen is not opened") {
|
||||
onSendScreen { amountInputTextField.assertDoesNotExist() }
|
||||
}
|
||||
// Tapping the 'Send' row dismisses the transfer bottom sheet (onActionDispatched) before the dialog shows.
|
||||
step("Close the notification dialog") {
|
||||
onDialog { okButton.clickWithAssertion() }
|
||||
}
|
||||
step("Pull to refresh to complete the active transaction") {
|
||||
pullToRefresh()
|
||||
}
|
||||
step("Open the transfer bottom sheet again") {
|
||||
onTokenDetailsScreen { transferButton.clickWithAssertion() }
|
||||
}
|
||||
step("Assert 'Send' button is enabled after the transaction is completed") {
|
||||
flakySafely(WAIT_UNTIL_TIMEOUT_LONG) {
|
||||
onTransferBottomSheet { sendButton.assertIsEnabled() }
|
||||
}
|
||||
}
|
||||
step("Click on 'Send' button") {
|
||||
onTransferBottomSheet { sendButton.performClick() }
|
||||
}
|
||||
step("Assert 'Send' screen is displayed") {
|
||||
flakySafely(WAIT_UNTIL_TIMEOUT_LONG) {
|
||||
onSendScreen { amountInputTextField.assertIsDisplayed() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AllureId("10209")
|
||||
@DisplayName("Action buttons (token details screen): 'Send' unavailable for a zero-balance token with an active transaction")
|
||||
@Test
|
||||
fun sendUnavailableForZeroBalanceWithActiveTransactionTest() {
|
||||
val tokenName = "Dogecoin"
|
||||
val zeroBalanceState = "ZeroBalance"
|
||||
val activeTxHistoryState = "UnconfirmedOutgoing"
|
||||
val balanceScenarioName = "dogecoin_balance"
|
||||
val txHistoryScenarioName = "dogecoin_tx_history"
|
||||
val sendingTitle = getResourceString(R.string.common_sending)
|
||||
|
||||
setupHooks(
|
||||
additionalAfterSection = {
|
||||
resetWireMockScenarioState(USER_TOKENS_API_SCENARIO)
|
||||
resetWireMockScenarioState(QUOTES_API_SCENARIO)
|
||||
resetWireMockScenarioState(balanceScenarioName)
|
||||
resetWireMockScenarioState(txHistoryScenarioName)
|
||||
}
|
||||
).run {
|
||||
step("Set WireMock scenario: '$USER_TOKENS_API_SCENARIO' to state: '$tokenName'") {
|
||||
setWireMockScenarioState(scenarioName = USER_TOKENS_API_SCENARIO, state = tokenName)
|
||||
}
|
||||
step("Set WireMock scenario: '$QUOTES_API_SCENARIO' to state: '$tokenName'") {
|
||||
setWireMockScenarioState(scenarioName = QUOTES_API_SCENARIO, state = tokenName)
|
||||
}
|
||||
step("Set WireMock scenario: '$balanceScenarioName' to state: '$zeroBalanceState'") {
|
||||
setWireMockScenarioState(scenarioName = balanceScenarioName, state = zeroBalanceState)
|
||||
}
|
||||
step("Set WireMock scenario: '$txHistoryScenarioName' to state: '$activeTxHistoryState'") {
|
||||
setWireMockScenarioState(scenarioName = txHistoryScenarioName, state = activeTxHistoryState)
|
||||
}
|
||||
step("Open 'Main Screen'") {
|
||||
openMainScreen()
|
||||
}
|
||||
step("Synchronize addresses") {
|
||||
synchronizeAddresses()
|
||||
}
|
||||
step("Click on token with name: '$tokenName'") {
|
||||
onMainScreen { tokenWithTitleAndAddress(tokenName).clickWithAssertion() }
|
||||
}
|
||||
step("Assert 'Token details' screen is displayed") {
|
||||
onTokenDetailsScreen { screenContainer.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert active outgoing '$sendingTitle' transaction block is displayed") {
|
||||
flakySafely(WAIT_UNTIL_TIMEOUT_LONG) {
|
||||
onTxHistoryScreen { transactionItem(sendingTitle).assertIsDisplayed() }
|
||||
}
|
||||
}
|
||||
step("Assert 'Transfer' button is not displayed for the zero-balance token") {
|
||||
onTokenDetailsScreen { transferButton.assertIsNotDisplayed() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,268 @@
|
|||
package com.tangem.tests.tokenDetails
|
||||
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.common.constants.TestConstants.QUOTES_API_SCENARIO
|
||||
import com.tangem.common.constants.TestConstants.USER_TOKENS_API_SCENARIO
|
||||
import com.tangem.common.extensions.clickWithAssertion
|
||||
import com.tangem.common.utils.resetWireMockScenarioState
|
||||
import com.tangem.common.utils.setWireMockScenarioState
|
||||
import com.tangem.scenarios.assertQrCodeEncodesDisplayedAddress
|
||||
import com.tangem.scenarios.assertQrCodesMatchForBothAddressTypes
|
||||
import com.tangem.scenarios.goToQrCodeBottomSheet
|
||||
import com.tangem.scenarios.openReceiveViaAddFunds
|
||||
import com.tangem.scenarios.openTokenDetails
|
||||
import com.tangem.screens.onTokenDetailsScreen
|
||||
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 TokenDetailsAddressesTest : BaseTestCase() {
|
||||
|
||||
@AllureId("4947")
|
||||
@DisplayName("Token details (address): QR code encodes the displayed address (Bitcoin, 2 address types)")
|
||||
@Test
|
||||
fun qrCodeEncodesDisplayedAddressBitcoinTest() {
|
||||
val tokenName = "Bitcoin"
|
||||
|
||||
setupHooks().run {
|
||||
step("Open token details for '$tokenName'") {
|
||||
openTokenDetails(tokenName)
|
||||
}
|
||||
step("Open receive via 'Add funds'") {
|
||||
openReceiveViaAddFunds()
|
||||
}
|
||||
step("Assert QR codes match for both address types") {
|
||||
assertQrCodesMatchForBothAddressTypes()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AllureId("10218")
|
||||
@DisplayName("Token details (address): QR code encodes the displayed address (Cosmos)")
|
||||
@Test
|
||||
fun qrCodeEncodesDisplayedAddressCosmosTest() {
|
||||
val tokenName = "Cosmos"
|
||||
val networksProvidersScenario = "networks_providers"
|
||||
val appTransfersNetworksState = "AppTransfersNetworks"
|
||||
|
||||
setupHooks(
|
||||
additionalBeforeAppLaunchSection = {
|
||||
setWireMockScenarioState(networksProvidersScenario, appTransfersNetworksState)
|
||||
},
|
||||
additionalAfterSection = {
|
||||
resetWireMockScenarioState(USER_TOKENS_API_SCENARIO)
|
||||
resetWireMockScenarioState(QUOTES_API_SCENARIO)
|
||||
resetWireMockScenarioState(networksProvidersScenario)
|
||||
},
|
||||
).run {
|
||||
step("Set WireMock scenario: '$USER_TOKENS_API_SCENARIO' to state: '$tokenName'") {
|
||||
setWireMockScenarioState(scenarioName = USER_TOKENS_API_SCENARIO, state = tokenName)
|
||||
}
|
||||
step("Set WireMock scenario: '$QUOTES_API_SCENARIO' to state: '$appTransfersNetworksState'") {
|
||||
setWireMockScenarioState(scenarioName = QUOTES_API_SCENARIO, state = appTransfersNetworksState)
|
||||
}
|
||||
|
||||
step("Open token details for '$tokenName'") {
|
||||
openTokenDetails(tokenName)
|
||||
}
|
||||
step("Open receive via 'Add funds'") {
|
||||
openReceiveViaAddFunds()
|
||||
}
|
||||
step("Go to QR code bottom sheet") {
|
||||
goToQrCodeBottomSheet()
|
||||
}
|
||||
step("Assert QR code encodes the displayed address") {
|
||||
assertQrCodeEncodesDisplayedAddress()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AllureId("10219")
|
||||
@DisplayName("Token details (address): QR code encodes the displayed address (Kaspa)")
|
||||
@Test
|
||||
fun qrCodeEncodesDisplayedAddressKaspaTest() {
|
||||
val tokenName = "Kaspa"
|
||||
val networksProvidersScenario = "networks_providers"
|
||||
val appTransfersNetworksState = "AppTransfersNetworks"
|
||||
val quotesKaspaState = "Kaspa"
|
||||
val kaspaUtxoScenario = "kaspa_utxo"
|
||||
val kaspaUtxoState = "more_than_84_android"
|
||||
|
||||
setupHooks(
|
||||
additionalBeforeAppLaunchSection = {
|
||||
setWireMockScenarioState(networksProvidersScenario, appTransfersNetworksState)
|
||||
},
|
||||
additionalAfterSection = {
|
||||
resetWireMockScenarioState(USER_TOKENS_API_SCENARIO)
|
||||
resetWireMockScenarioState(QUOTES_API_SCENARIO)
|
||||
resetWireMockScenarioState(networksProvidersScenario)
|
||||
resetWireMockScenarioState(kaspaUtxoScenario)
|
||||
},
|
||||
).run {
|
||||
step("Set WireMock scenario: '$USER_TOKENS_API_SCENARIO' to state: '$tokenName'") {
|
||||
setWireMockScenarioState(scenarioName = USER_TOKENS_API_SCENARIO, state = tokenName)
|
||||
}
|
||||
step("Set WireMock scenario: '$QUOTES_API_SCENARIO' to state: '$quotesKaspaState'") {
|
||||
setWireMockScenarioState(scenarioName = QUOTES_API_SCENARIO, state = quotesKaspaState)
|
||||
}
|
||||
step("Set WireMock scenario: '$kaspaUtxoScenario' to state: '$kaspaUtxoState'") {
|
||||
setWireMockScenarioState(scenarioName = kaspaUtxoScenario, state = kaspaUtxoState)
|
||||
}
|
||||
|
||||
step("Open token details for '$tokenName'") {
|
||||
openTokenDetails(tokenName)
|
||||
}
|
||||
step("Open receive via 'Add funds'") {
|
||||
openReceiveViaAddFunds()
|
||||
}
|
||||
step("Go to QR code bottom sheet") {
|
||||
goToQrCodeBottomSheet()
|
||||
}
|
||||
step("Assert QR code encodes the displayed address") {
|
||||
assertQrCodeEncodesDisplayedAddress()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AllureId("10215")
|
||||
@DisplayName("Token details (address): QR code encodes the displayed address (Litecoin, 2 address types)")
|
||||
@Test
|
||||
fun qrCodeEncodesDisplayedAddressLitecoinTest() {
|
||||
val tokenName = "Litecoin"
|
||||
val userTokensState = "Litecoin"
|
||||
|
||||
setupHooks(
|
||||
additionalAfterSection = { resetWireMockScenarioState(USER_TOKENS_API_SCENARIO) },
|
||||
).run {
|
||||
step("Set WireMock scenario: '$USER_TOKENS_API_SCENARIO' to state: '$userTokensState'") {
|
||||
setWireMockScenarioState(scenarioName = USER_TOKENS_API_SCENARIO, state = userTokensState)
|
||||
}
|
||||
|
||||
step("Open token details for '$tokenName'") {
|
||||
openTokenDetails(tokenName)
|
||||
}
|
||||
step("Click on 'Receive' button") {
|
||||
onTokenDetailsScreen { receiveButton.clickWithAssertion() }
|
||||
}
|
||||
step("Assert QR codes match for both address types") {
|
||||
assertQrCodesMatchForBothAddressTypes()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AllureId("10220")
|
||||
@DisplayName("Token details (address): QR code encodes the displayed address (XDC Network, 2 address types)")
|
||||
@Test
|
||||
fun qrCodeEncodesDisplayedAddressXdcTest() {
|
||||
val tokenName = "XDC Network"
|
||||
val userTokensState = "XDC"
|
||||
|
||||
setupHooks(
|
||||
additionalAfterSection = { resetWireMockScenarioState(USER_TOKENS_API_SCENARIO) },
|
||||
).run {
|
||||
step("Set WireMock scenario: '$USER_TOKENS_API_SCENARIO' to state: '$userTokensState'") {
|
||||
setWireMockScenarioState(scenarioName = USER_TOKENS_API_SCENARIO, state = userTokensState)
|
||||
}
|
||||
|
||||
step("Open token details for '$tokenName'") {
|
||||
openTokenDetails(tokenName)
|
||||
}
|
||||
step("Click on 'Receive' button") {
|
||||
onTokenDetailsScreen { receiveButton.clickWithAssertion() }
|
||||
}
|
||||
step("Assert QR codes match for both address types") {
|
||||
assertQrCodesMatchForBothAddressTypes()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AllureId("10216")
|
||||
@DisplayName("Token details (address): QR code encodes the displayed address (Hedera)")
|
||||
@Test
|
||||
fun qrCodeEncodesDisplayedAddressHederaTest() {
|
||||
val tokenName = "Hedera"
|
||||
val networksProvidersScenario = "networks_providers"
|
||||
val appTransfersNetworksState = "AppTransfersNetworks"
|
||||
|
||||
setupHooks(
|
||||
additionalBeforeAppLaunchSection = {
|
||||
setWireMockScenarioState(networksProvidersScenario, appTransfersNetworksState)
|
||||
},
|
||||
additionalAfterSection = {
|
||||
resetWireMockScenarioState(USER_TOKENS_API_SCENARIO)
|
||||
resetWireMockScenarioState(QUOTES_API_SCENARIO)
|
||||
resetWireMockScenarioState(networksProvidersScenario)
|
||||
},
|
||||
).run {
|
||||
step("Set WireMock scenario: '$USER_TOKENS_API_SCENARIO' to state: '$tokenName'") {
|
||||
setWireMockScenarioState(scenarioName = USER_TOKENS_API_SCENARIO, state = tokenName)
|
||||
}
|
||||
step("Set WireMock scenario: '$QUOTES_API_SCENARIO' to state: '$appTransfersNetworksState'") {
|
||||
setWireMockScenarioState(scenarioName = QUOTES_API_SCENARIO, state = appTransfersNetworksState)
|
||||
}
|
||||
|
||||
step("Open token details for '$tokenName'") {
|
||||
openTokenDetails(tokenName)
|
||||
}
|
||||
step("Open receive via 'Add funds'") {
|
||||
openReceiveViaAddFunds()
|
||||
}
|
||||
step("Go to QR code bottom sheet") {
|
||||
goToQrCodeBottomSheet()
|
||||
}
|
||||
step("Assert QR code encodes the displayed address") {
|
||||
assertQrCodeEncodesDisplayedAddress()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AllureId("10217")
|
||||
@DisplayName("Token details (address): QR code encodes the displayed address (Ethereum)")
|
||||
@Test
|
||||
fun qrCodeEncodesDisplayedAddressEthereumTest() {
|
||||
val tokenName = "Ethereum"
|
||||
|
||||
setupHooks().run {
|
||||
step("Open token details for '$tokenName'") {
|
||||
openTokenDetails(tokenName)
|
||||
}
|
||||
step("Open receive via 'Add funds'") {
|
||||
openReceiveViaAddFunds()
|
||||
}
|
||||
step("Go to QR code bottom sheet") {
|
||||
goToQrCodeBottomSheet()
|
||||
}
|
||||
step("Assert QR code encodes the displayed address") {
|
||||
assertQrCodeEncodesDisplayedAddress()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AllureId("10214")
|
||||
@DisplayName("Token details (address): QR code encodes the displayed address (Decimal Smart Chain, 2 address types)")
|
||||
@Test
|
||||
fun qrCodeEncodesDisplayedAddressDecimalTest() {
|
||||
val tokenName = "Decimal Smart Chain"
|
||||
val userTokensState = "Decimal"
|
||||
|
||||
setupHooks(
|
||||
additionalAfterSection = { resetWireMockScenarioState(USER_TOKENS_API_SCENARIO) },
|
||||
).run {
|
||||
step("Set WireMock scenario: '$USER_TOKENS_API_SCENARIO' to state: '$userTokensState'") {
|
||||
setWireMockScenarioState(scenarioName = USER_TOKENS_API_SCENARIO, state = userTokensState)
|
||||
}
|
||||
|
||||
step("Open token details for '$tokenName'") {
|
||||
openTokenDetails(tokenName)
|
||||
}
|
||||
step("Click on 'Receive' action") {
|
||||
onTokenDetailsScreen { receiveButton.clickWithAssertion() }
|
||||
}
|
||||
step("Assert QR codes match for both address types") {
|
||||
assertQrCodesMatchForBothAddressTypes()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
package com.tangem.tests.tokenDetails
|
||||
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.common.constants.TestConstants.QUOTES_API_SCENARIO
|
||||
import com.tangem.common.constants.TestConstants.USER_TOKENS_API_SCENARIO
|
||||
import com.tangem.common.constants.TestConstants.WAIT_UNTIL_TIMEOUT_LONG
|
||||
import com.tangem.common.extensions.clickWithAssertion
|
||||
import com.tangem.common.utils.resetWireMockScenarioState
|
||||
import com.tangem.common.utils.setWireMockScenarioState
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.scenarios.openMainScreen
|
||||
import com.tangem.scenarios.synchronizeAddresses
|
||||
import com.tangem.screens.onMainScreen
|
||||
import com.tangem.screens.onTokenDetailsScreen
|
||||
import com.tangem.screens.onTokenMarketBlock
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import io.github.kakaocup.kakao.common.utilities.getResourceString
|
||||
import io.qameta.allure.kotlin.AllureId
|
||||
import io.qameta.allure.kotlin.junit4.DisplayName
|
||||
import org.junit.Test
|
||||
|
||||
@HiltAndroidTest
|
||||
class TokenDetailsMarketPriceTests : BaseTestCase() {
|
||||
|
||||
@AllureId("301")
|
||||
@DisplayName("Token details: Market Price block data")
|
||||
@Test
|
||||
fun marketPriceBlockDataTest() {
|
||||
val tokenName = "Dogecoin"
|
||||
val marketPriceTitle = getResourceString(R.string.markets_common_market_price)
|
||||
|
||||
setupHooks(
|
||||
additionalAfterSection = {
|
||||
resetWireMockScenarioState(USER_TOKENS_API_SCENARIO)
|
||||
resetWireMockScenarioState(QUOTES_API_SCENARIO)
|
||||
}
|
||||
).run {
|
||||
step("Set WireMock scenario: '$USER_TOKENS_API_SCENARIO' to state: '$tokenName'") {
|
||||
setWireMockScenarioState(scenarioName = USER_TOKENS_API_SCENARIO, state = tokenName)
|
||||
}
|
||||
step("Set WireMock scenario: '$QUOTES_API_SCENARIO' to state: '$tokenName'") {
|
||||
setWireMockScenarioState(scenarioName = QUOTES_API_SCENARIO, state = tokenName)
|
||||
}
|
||||
step("Open 'Main Screen'") {
|
||||
openMainScreen()
|
||||
}
|
||||
step("Synchronize addresses") {
|
||||
synchronizeAddresses()
|
||||
}
|
||||
step("Click on token with name: '$tokenName'") {
|
||||
onMainScreen { tokenWithTitleAndAddress(tokenName).clickWithAssertion() }
|
||||
}
|
||||
step("Assert 'Token details' screen is displayed") {
|
||||
onTokenDetailsScreen { screenContainer.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Market Price' block is displayed with title '$marketPriceTitle'") {
|
||||
onTokenMarketBlock {
|
||||
block.assertIsDisplayed()
|
||||
title.assertTextEquals(marketPriceTitle)
|
||||
}
|
||||
}
|
||||
step("Assert price rate is displayed") {
|
||||
flakySafely(WAIT_UNTIL_TIMEOUT_LONG) {
|
||||
onTokenMarketBlock { price.assertIsDisplayed() }
|
||||
}
|
||||
}
|
||||
step("Assert 24h price change is displayed") {
|
||||
onTokenMarketBlock { priceChange.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert mini chart is displayed") {
|
||||
onTokenMarketBlock { chart.assertIsDisplayed() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
package com.tangem.tests.tokenDetails
|
||||
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.common.constants.TestConstants.DOGECOIN_RECIPIENT_ADDRESS
|
||||
import com.tangem.common.constants.TestConstants.QUOTES_API_SCENARIO
|
||||
import com.tangem.common.constants.TestConstants.USER_TOKENS_API_SCENARIO
|
||||
import com.tangem.common.constants.TestConstants.WAIT_UNTIL_TIMEOUT_LONG
|
||||
import com.tangem.common.extensions.clickWithAssertion
|
||||
import com.tangem.common.utils.resetWireMockScenarioState
|
||||
import com.tangem.common.utils.setWireMockScenarioState
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.scenarios.openMainScreen
|
||||
import com.tangem.scenarios.synchronizeAddresses
|
||||
import com.tangem.screens.onMainScreen
|
||||
import com.tangem.screens.onTokenDetailsScreen
|
||||
import com.tangem.screens.onTxHistoryScreen
|
||||
import com.tangem.utils.toBriefAddressFormat
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import io.github.kakaocup.kakao.common.utilities.getResourceString
|
||||
import io.qameta.allure.kotlin.AllureId
|
||||
import io.qameta.allure.kotlin.junit4.DisplayName
|
||||
import org.junit.Test
|
||||
|
||||
@HiltAndroidTest
|
||||
class TokenDetailsTests : BaseTestCase() {
|
||||
|
||||
private val txHistoryScenarioName = "dogecoin_tx_history"
|
||||
|
||||
@AllureId("304")
|
||||
@DisplayName("Token details: active outgoing transaction block")
|
||||
@Test
|
||||
fun activeOutgoingTransactionBlockTest() {
|
||||
val tokenName = "Dogecoin"
|
||||
val currencySymbol = "DOGE"
|
||||
val txHistoryScenarioState = "UnconfirmedOutgoing"
|
||||
val sendingTitle = getResourceString(R.string.common_sending)
|
||||
val recipientBriefAddress = DOGECOIN_RECIPIENT_ADDRESS.toBriefAddressFormat()
|
||||
|
||||
setupHooks(
|
||||
additionalAfterSection = {
|
||||
resetWireMockScenarioState(USER_TOKENS_API_SCENARIO)
|
||||
resetWireMockScenarioState(QUOTES_API_SCENARIO)
|
||||
resetWireMockScenarioState(txHistoryScenarioName)
|
||||
}
|
||||
).run {
|
||||
step("Set WireMock scenario: '$USER_TOKENS_API_SCENARIO' to state: '$tokenName'") {
|
||||
setWireMockScenarioState(scenarioName = USER_TOKENS_API_SCENARIO, state = tokenName)
|
||||
}
|
||||
step("Set WireMock scenario: '$QUOTES_API_SCENARIO' to state: '$tokenName'") {
|
||||
setWireMockScenarioState(scenarioName = QUOTES_API_SCENARIO, state = tokenName)
|
||||
}
|
||||
step("Set WireMock scenario: '$txHistoryScenarioName' to state: '$txHistoryScenarioState'") {
|
||||
setWireMockScenarioState(scenarioName = txHistoryScenarioName, state = txHistoryScenarioState)
|
||||
}
|
||||
step("Open 'Main Screen'") {
|
||||
openMainScreen()
|
||||
}
|
||||
step("Synchronize addresses") {
|
||||
synchronizeAddresses()
|
||||
}
|
||||
step("Click on token with name: '$tokenName'") {
|
||||
onMainScreen { tokenWithTitleAndAddress(tokenName).clickWithAssertion() }
|
||||
}
|
||||
step("Assert 'Token details' screen is displayed") {
|
||||
onTokenDetailsScreen { screenContainer.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert active outgoing '$sendingTitle' transaction is displayed") {
|
||||
flakySafely(WAIT_UNTIL_TIMEOUT_LONG) {
|
||||
onTxHistoryScreen { transactionItem(sendingTitle).assertIsDisplayed() }
|
||||
}
|
||||
}
|
||||
step("Assert active outgoing transaction status is unconfirmed") {
|
||||
onTxHistoryScreen { transactionUnconfirmedStatus(sendingTitle).assertIsDisplayed() }
|
||||
}
|
||||
step("Assert active outgoing transaction amount is displayed in '$currencySymbol'") {
|
||||
onTxHistoryScreen {
|
||||
transactionAmount(sendingTitle).assertIsDisplayed()
|
||||
transactionCurrency(sendingTitle).assertTextEquals(currencySymbol)
|
||||
}
|
||||
}
|
||||
step("Assert active outgoing transaction recipient address '$recipientBriefAddress' is displayed") {
|
||||
onTxHistoryScreen { transactionAddress(sendingTitle, recipientBriefAddress).assertIsDisplayed() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -160,6 +160,10 @@ object WalletMockContent : MockContent {
|
|||
publicKey = byteArrayOf(2, -40, 115, -15, 80, 104, 100, -29, 80, 29, 112, -35, -54, 64, -98, 45, 115, 108, 93, 113, -71, 89, 17, 72, 98, 21, 126, 82, -50, 50, -12, -87, -62),
|
||||
chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41),
|
||||
),
|
||||
DerivationPath("m/44'/111111'/0'/0/0") to ExtendedPublicKey( // Kaspa
|
||||
publicKey = byteArrayOf(2, -40, 115, -15, 80, 104, 100, -29, 80, 29, 112, -35, -54, 64, -98, 45, 115, 108, 93, 113, -71, 89, 17, 72, 98, 21, 126, 82, -50, 50, -12, -87, -62),
|
||||
chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41),
|
||||
),
|
||||
),
|
||||
extendedPublicKey = ExtendedPublicKey(
|
||||
publicKey = secp256k1WalletPublicKey,
|
||||
|
|
@ -254,6 +258,13 @@ object WalletMockContent : MockContent {
|
|||
parentFingerprint = byteArrayOf(0, 0, 0, 0),
|
||||
childNumber = 0,
|
||||
),
|
||||
DerivationPath("m/84'/2'/0'/0/0") to ExtendedPublicKey( // ltc (reuses valid btc key)
|
||||
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
|
||||
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
|
||||
depth = 0,
|
||||
parentFingerprint = byteArrayOf(0, 0, 0, 0),
|
||||
childNumber = 0,
|
||||
),
|
||||
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth
|
||||
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
|
||||
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
|
||||
|
|
@ -261,6 +272,13 @@ object WalletMockContent : MockContent {
|
|||
parentFingerprint = byteArrayOf(0, 0, 0, 0),
|
||||
childNumber = 0,
|
||||
),
|
||||
DerivationPath("m/44'/550'/0'/0/0") to ExtendedPublicKey( // xdc (EVM, reuses valid eth key)
|
||||
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
|
||||
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
|
||||
depth = 0,
|
||||
parentFingerprint = byteArrayOf(0, 0, 0, 0),
|
||||
childNumber = 0,
|
||||
),
|
||||
DerivationPath("m/44'/60'/0'/0/1") to ExtendedPublicKey( // eth (account 2)
|
||||
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
|
||||
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
|
||||
|
|
@ -486,6 +504,13 @@ object WalletMockContent : MockContent {
|
|||
parentFingerprint = byteArrayOf(0, 0, 0, 0),
|
||||
childNumber = 0,
|
||||
),
|
||||
DerivationPath("m/44'/3030'/0'/0'/0'") to ExtendedPublicKey( // Hedera (address resolves via network)
|
||||
publicKey = byteArrayOf(-65, -53, -62, -12, -57, -32, -38, -9, -128, -52, -83, -61, 73, 39, 41, 15, -74, -97, 38, 52, -101, 63, 74, -56, -20, 15, 57, -127, 114, -93, -17, -109),
|
||||
chainCode = byteArrayOf(-81, 15, 125, 28, -115, -22, 87, 81, 87, -123, -25, -74, 86, 2, 1, 110, -115, 65, -110, 63, -64, 83, -93, -97, -104, 123, 12, -26, 94, 27, 84, -6),
|
||||
depth = 0,
|
||||
parentFingerprint = byteArrayOf(0, 0, 0, 0),
|
||||
childNumber = 0,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue