diff --git a/app/src/androidTest/kotlin/com/tangem/scenarios/ManageTokensScenarios.kt b/app/src/androidTest/kotlin/com/tangem/scenarios/ManageTokensScenarios.kt index 4d04dde6ae..85b85decfc 100644 --- a/app/src/androidTest/kotlin/com/tangem/scenarios/ManageTokensScenarios.kt +++ b/app/src/androidTest/kotlin/com/tangem/scenarios/ManageTokensScenarios.kt @@ -4,7 +4,6 @@ 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.datasource.local.preferences.PreferencesKeys import com.tangem.screens.accounts.onAccountDetailsScreen import com.tangem.screens.onAddCustomTokenScreen import com.tangem.screens.onDetailsScreen @@ -13,7 +12,6 @@ import com.tangem.screens.onManageTokensScreen import com.tangem.screens.onWalletSettingsScreen import io.github.kakaocup.kakao.common.utilities.getResourceString import io.qameta.allure.kotlin.Allure.step -import kotlinx.coroutines.runBlocking import com.tangem.core.res.R as CoreResR private fun mainAccountName(): String = getResourceString(CoreResR.string.account_main_account_title) @@ -68,18 +66,6 @@ fun BaseTestCase.addCustomTokenWithCustomDerivation(network: String, contract: S navigateBackToMainFromManageTokens() } -private const val MAX_BACKS_TO_MANAGE_TOKENS = 5 - -// The device-backs to close the sheet vary — press back until Manage Tokens is shown, then fail loudly. -private fun BaseTestCase.closeAddCustomTokenSheet() { - repeat(MAX_BACKS_TO_MANAGE_TOKENS) { - if (runCatching { onManageTokensScreen { searchField.assertIsDisplayed() } }.isSuccess) return - device.uiDevice.pressBack() - waitForIdle() - } - onManageTokensScreen { searchField.assertIsDisplayed() } -} - private fun BaseTestCase.navigateBackToWalletSettings() { step("Click on 'Manage tokens' screen 'Back' button") { waitForIdle() @@ -91,28 +77,6 @@ private fun BaseTestCase.navigateBackToWalletSettings() { } } -fun BaseTestCase.forgetCurrentWalletAndReArmForNextScan() { - step("Close 'Add custom token' bottom sheet") { closeAddCustomTokenSheet() } - navigateBackToWalletSettings() - step("Click on 'Forget wallet' button") { - waitForIdle() - onWalletSettingsScreen { - scrollToForgetWallet() - forgetWalletButton.clickWithAssertion() - } - } - step("Confirm forgetting the wallet") { - awaitSuccess { onDialog { forgetButton.assertIsDisplayed() } } - onDialog { forgetButton.clickWithAssertion() } - } - // Markets tooltip is a one-time app-level flag; re-arm it so the next scan's openMainScreen can dismiss it. - step("Re-arm the markets tooltip for the next scan") { - runBlocking { - appPreferencesStore.editData { it.set(PreferencesKeys.SHOULD_SHOW_MARKETS_TOOLTIP_KEY, value = true) } - } - } -} - fun BaseTestCase.assertDerivationPathsInSelector(networkToOpen: String, vararg expectedPaths: Pair) { step("Click on network: '$networkToOpen'") { awaitSuccess { onAddCustomTokenScreen { scrollToNetwork(networkToOpen) } } diff --git a/app/src/androidTest/kotlin/com/tangem/tests/main/AddCustomTokenTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/main/AddCustomTokenTest.kt index 6c61f76733..9f5dbcfdf0 100644 --- a/app/src/androidTest/kotlin/com/tangem/tests/main/AddCustomTokenTest.kt +++ b/app/src/androidTest/kotlin/com/tangem/tests/main/AddCustomTokenTest.kt @@ -9,7 +9,6 @@ import com.tangem.common.utils.setWireMockScenarioState import com.tangem.domain.models.scan.ProductType import com.tangem.scenarios.addCustomTokenWithCustomDerivation import com.tangem.scenarios.assertDerivationPathsInSelector -import com.tangem.scenarios.forgetCurrentWalletAndReArmForNextScan import com.tangem.scenarios.navigateBackToMainFromManageTokens import com.tangem.scenarios.openAddCustomToken import com.tangem.scenarios.openMainScreen @@ -208,38 +207,62 @@ class AddCustomTokenTest : BaseTestCase() { } @AllureId("776") - @DisplayName("Add custom token: derivation paths match the card version (V1/V2/V3)") + @DisplayName("Add custom token: derivation paths match a legacy-batch V1 Wallet card") @Test - fun derivationPathsMatchCardVersionTest() { + fun derivationPathsLegacyBatchWalletTest() { setupHooks( additionalAfterSection = { resetWireMockScenarioState(COINS_API_SCENARIO) }, ).run { step("Set WireMock scenario: '$COINS_API_SCENARIO' to state: '$richState'") { setWireMockScenarioState(COINS_API_SCENARIO, richState) } - step("Assert derivation paths for a legacy-batch V1 Wallet card") { - openMainScreen(mockContent = Wallet1LegacyDerivationMockContent) - openAddCustomToken() + step("Open 'Main Screen'") { openMainScreen(mockContent = Wallet1LegacyDerivationMockContent) } + step("Open 'Add custom token' screen") { openAddCustomToken() } + step("Assert V1 derivation paths are displayed in the selector") { assertDerivationPathsInSelector( ethereumNetwork, bitcoinNetworkId to "m/44'/0'/0'/0/0", ethereumClassicNetworkId to "m/44'/61'/0'/0/0", ) - forgetCurrentWalletAndReArmForNextScan() } - step("Assert derivation paths for a V2 Wallet card") { - openMainScreen() - openAddCustomToken() + } + } + + @AllureId("10204") + @DisplayName("Add custom token: derivation paths match a V2 Wallet card") + @Test + fun derivationPathsWalletTest() { + setupHooks( + additionalAfterSection = { resetWireMockScenarioState(COINS_API_SCENARIO) }, + ).run { + step("Set WireMock scenario: '$COINS_API_SCENARIO' to state: '$richState'") { + setWireMockScenarioState(COINS_API_SCENARIO, richState) + } + step("Open 'Main Screen'") { openMainScreen() } + step("Open 'Add custom token' screen") { openAddCustomToken() } + step("Assert V2 derivation paths are displayed in the selector") { assertDerivationPathsInSelector( ethereumNetwork, bitcoinNetworkId to "m/44'/0'/0'/0/0", ethereumClassicNetworkId to "m/44'/60'/0'/0/0", ) - forgetCurrentWalletAndReArmForNextScan() } - step("Assert derivation paths for a V3 Wallet 2 card") { - openMainScreen(productType = ProductType.Wallet2) - openAddCustomToken() + } + } + + @AllureId("10205") + @DisplayName("Add custom token: derivation paths match a V3 Wallet 2 card") + @Test + fun derivationPathsWallet2Test() { + setupHooks( + additionalAfterSection = { resetWireMockScenarioState(COINS_API_SCENARIO) }, + ).run { + step("Set WireMock scenario: '$COINS_API_SCENARIO' to state: '$richState'") { + setWireMockScenarioState(COINS_API_SCENARIO, richState) + } + step("Open 'Main Screen'") { openMainScreen(productType = ProductType.Wallet2) } + step("Open 'Add custom token' screen") { openAddCustomToken() } + step("Assert V3 derivation paths are displayed in the selector") { assertDerivationPathsInSelector( ethereumNetwork, bitcoinNetworkId to "m/84'/0'/0'/0/0", diff --git a/app/src/androidTest/kotlin/com/tangem/tests/send/sendViaSwap/SendViaSwapTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/send/sendViaSwap/SendViaSwapTest.kt index eb64d3839f..d53d345b5e 100644 --- a/app/src/androidTest/kotlin/com/tangem/tests/send/sendViaSwap/SendViaSwapTest.kt +++ b/app/src/androidTest/kotlin/com/tangem/tests/send/sendViaSwap/SendViaSwapTest.kt @@ -14,6 +14,7 @@ import com.tangem.common.extensions.extractText import com.tangem.common.extensions.clickWithAssertion import com.tangem.common.utils.resetWireMockScenarioState import com.tangem.common.utils.setWireMockScenarioState +import com.tangem.domain.models.scan.ProductType import com.tangem.scenarios.* import com.tangem.screens.* import com.tangem.tap.domain.sdk.mocks.content.Wallet2WithDerivationsMockContent @@ -825,4 +826,112 @@ class SendViaSwapTest : BaseTestCase() { } } } + + @AllureId("3972") + @DisplayName("Send via Swap: single-currency card has no 'Convert' button in Send") + @Test + fun singleCurrencyCardNoConvertButtonInSendTest() { + val cardType = ProductType.Note + val tokenTitle = "Dogecoin" + + setupHooks().run { + step("Open 'Main Screen' on '${cardType.name}' card") { + openMainScreen(cardType) + } + step("Assert 'Add funds' button is displayed") { + onMainScreen { addFundsButton.assertIsDisplayed() } + } + step("Assert 'Transfer' button is displayed") { + onMainScreen { transferButton.assertIsDisplayed() } + } + step("Assert 'Swap' button is not displayed") { + onMainScreen { swapButton.assertIsNotDisplayed() } + } + step("Click on 'Transfer' button") { + onMainScreen { transferButton.performClick() } + } + step("Click on token: '$tokenTitle'") { + onChooseTokenBottomSheet { tokenWithTitle(tokenTitle).clickWithAssertion() } + } + step("Click on 'Send' button in bottom sheet") { + onTransferBottomSheet { sendButton.clickWithAssertion() } + } + step("Assert amount input text field is displayed") { + flakySafely { onSendScreen { amountInputTextField.assertIsDisplayed() } } + } + step("Assert 'Swap to another token' button is not displayed") { + onSendScreen { swapToAnotherTokenButton.assertDoesNotExist() } + } + } + } + + @AllureId("10196") + @DisplayName("Send via Swap: memo-restricted network is not selectable as a receive token") + @Test + fun memoRestrictedNetworkNotSelectableAsReceiveTokenTest() { + val tokenName = "Bitcoin" + val algorand = "Algorand" + val bitcoinBalanceScenarioName = "bitcoin_utxo" + val bitcoinBalanceScenarioState = "Balance" + val assetsScenarioName = "express_api_assets" + val assetsScenarioState = "BitcoinExchangeEnabled" + val userTokensScenarioState = "Wallet2" + val coinsScenarioName = "coins_api" + val coinsScenarioState = "WithAlgorand" + val warningTitle = getResourceString(R.string.express_swap_not_supported_title, algorand) + val warningMessage = getResourceString(R.string.express_swap_not_supported_text) + + setupHooks( + additionalAfterSection = { + resetWireMockScenarioState(bitcoinBalanceScenarioName) + resetWireMockScenarioState(assetsScenarioName) + resetWireMockScenarioState(USER_TOKENS_API_SCENARIO) + resetWireMockScenarioState(coinsScenarioName) + } + ).run { + + step("Set WireMock scenario: '$bitcoinBalanceScenarioName' to state: '$bitcoinBalanceScenarioState'") { + setWireMockScenarioState(scenarioName = bitcoinBalanceScenarioName, state = bitcoinBalanceScenarioState) + } + step("Set WireMock scenario: '$assetsScenarioName' to state: '$assetsScenarioState'") { + setWireMockScenarioState(scenarioName = assetsScenarioName, state = assetsScenarioState) + } + step("Set WireMock scenario: '$USER_TOKENS_API_SCENARIO' to state: '$userTokensScenarioState'") { + setWireMockScenarioState(scenarioName = USER_TOKENS_API_SCENARIO, state = userTokensScenarioState) + } + step("Set WireMock scenario: '$coinsScenarioName' to state: '$coinsScenarioState'") { + setWireMockScenarioState(scenarioName = coinsScenarioName, state = coinsScenarioState) + } + step("Open 'Send' screen") { + openSendScreen(tokenName, mockContent = Wallet2WithDerivationsMockContent) + } + step("Click on 'Swap to another token' button") { + onSendScreen { swapToAnotherTokenButton.performClick() } + } + step("Type '$algorand' in search text field") { + onSendViaSwapScreen { + searchField.performClick() + searchField.performTextInput(algorand) + } + } + step("Click on token: '$algorand'") { + onSendViaSwapScreen { tokenItem(algorand).performClick() } + } + step("Assert warning bottom sheet icon is displayed") { + onWarningBottomSheet { icon.assertIsDisplayed() } + } + step("Assert warning bottom sheet title is displayed") { + onWarningBottomSheet { title(warningTitle).assertIsDisplayed() } + } + step("Assert warning bottom sheet message is displayed") { + onWarningBottomSheet { message(warningMessage).assertIsDisplayed() } + } + step("Click on 'Ok, Got it!' button") { + onWarningBottomSheet { okGotItButton.performClick() } + } + step("Assert 'Swap to another token' screen is displayed") { + onSendViaSwapScreen { tokenItem(algorand).assertIsDisplayed() } + } + } + } } \ No newline at end of file