diff --git a/app/src/androidTest/kotlin/com/tangem/common/BaseTestCase.kt b/app/src/androidTest/kotlin/com/tangem/common/BaseTestCase.kt index 8532e23891..cb51a8d6be 100644 --- a/app/src/androidTest/kotlin/com/tangem/common/BaseTestCase.kt +++ b/app/src/androidTest/kotlin/com/tangem/common/BaseTestCase.kt @@ -147,6 +147,7 @@ abstract class BaseTestCase : TestCase( toggleStates = mapOf( "SWAP_REDESIGN_ENABLED" to false, "ACCOUNTS_FEATURE_ENABLED" to true, + "GASLESS_APPROVAL_ENABLED" to true, ) ) } diff --git a/app/src/androidTest/kotlin/com/tangem/common/extensions/KNode.kt b/app/src/androidTest/kotlin/com/tangem/common/extensions/KNode.kt index 004e367549..d26878e4f4 100644 --- a/app/src/androidTest/kotlin/com/tangem/common/extensions/KNode.kt +++ b/app/src/androidTest/kotlin/com/tangem/common/extensions/KNode.kt @@ -18,3 +18,12 @@ fun KNode.assertTextContainsSafe( ) } +fun KNode.isDisplayedSafely(): Boolean { + return try { + assertIsDisplayed() + true + } catch (_: AssertionError) { + false + } +} + diff --git a/app/src/androidTest/kotlin/com/tangem/scenarios/SwapScenarios.kt b/app/src/androidTest/kotlin/com/tangem/scenarios/SwapScenarios.kt index cc2c466cb3..e239b87144 100644 --- a/app/src/androidTest/kotlin/com/tangem/scenarios/SwapScenarios.kt +++ b/app/src/androidTest/kotlin/com/tangem/scenarios/SwapScenarios.kt @@ -3,6 +3,7 @@ package com.tangem.scenarios import androidx.compose.ui.test.click import com.tangem.common.BaseTestCase import com.tangem.common.extensions.clickWithAssertion +import com.tangem.common.extensions.isDisplayedSafely import com.tangem.screens.* import io.github.kakaocup.kakao.common.utilities.getResourceString import io.qameta.allure.kotlin.Allure.step @@ -195,6 +196,51 @@ fun BaseTestCase.selectFeeType(feeType: FeeType, selectedFeeAmount: String) { } } +fun BaseTestCase.selectFeeTypeWithGasless(feeType: FeeType, selectedFeeAmount: String) { + step("Click on 'Select fee' icon") { + onSwapTokenScreen { selectFeeIcon.performClick() } + } + + when (feeType) { + FeeType.Market -> selectMarketFee(selectedFeeAmount) + FeeType.Fast -> selectFastFee(selectedFeeAmount) + } +} + +private fun BaseTestCase.selectMarketFee(selectedFeeAmount: String) { + step("Deselect current fee and select 'Market'") { + onSwapSelectNetworkFeeBottomSheet { + if (fastSelectorItem.isDisplayedSafely()) { + fastSelectorItem.performClick() + } + marketSelectorItem.performClick() + } + } + step("Click on 'Apply' button") { + onSwapSelectNetworkFeeBottomSheet { applyButton.performClick() } + } + step("Assert fee amount is equal to 'Market' fee:'$selectedFeeAmount'") { + onSwapTokenScreen { feeAmount.assertTextContains(selectedFeeAmount, substring = true) } + } +} + +private fun BaseTestCase.selectFastFee(selectedFeeAmount: String) { + step("Deselect current fee and select 'Fast'") { + onSwapSelectNetworkFeeBottomSheet { + if (marketSelectorItem.isDisplayedSafely()) { + marketSelectorItem.performClick() + } + fastSelectorItem.performClick() + } + } + step("Click on 'Apply' button") { + onSwapSelectNetworkFeeBottomSheet { applyButton.performClick() } + } + step("Assert fee amount is equal to 'Fast' fee:'$selectedFeeAmount'") { + onSwapTokenScreen { feeAmount.assertTextContains(selectedFeeAmount, substring = true) } + } +} + fun BaseTestCase.chackUnableToCoverFeeNotification(networkName: String, currencySymbol: String) { step("Assert 'Unable to cover '$networkName' fee notification title is displayed'") { onSwapTokenScreen { unableToCoverFeeNotificationTitle(networkName).assertIsDisplayed() } @@ -207,6 +253,9 @@ fun BaseTestCase.chackUnableToCoverFeeNotification(networkName: String, currency ).assertIsDisplayed() } } + step("Assert 'Unable to cover '$networkName' fee notification icon is displayed'") { + onSwapTokenScreen { unableToCoverFeeNotificationIcon(networkName).assertIsDisplayed() } + } } sealed class SwapEntryPoint { diff --git a/app/src/androidTest/kotlin/com/tangem/tests/actionButtons/TokenDetailsScreenActionButtonsTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/actionButtons/TokenDetailsScreenActionButtonsTest.kt index 5a158f6e07..f634fe21c0 100644 --- a/app/src/androidTest/kotlin/com/tangem/tests/actionButtons/TokenDetailsScreenActionButtonsTest.kt +++ b/app/src/androidTest/kotlin/com/tangem/tests/actionButtons/TokenDetailsScreenActionButtonsTest.kt @@ -2,17 +2,16 @@ package com.tangem.tests.actionButtons import com.tangem.common.BaseTestCase import com.tangem.common.constants.TestConstants.WAIT_UNTIL_TIMEOUT -import com.tangem.common.extensions.SwipeDirection import com.tangem.common.extensions.assertIsDimmed 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.checkQrCodeBottomSheetScenario import com.tangem.scenarios.goToQrCodeBottomSheet import com.tangem.scenarios.openMainScreen import com.tangem.scenarios.synchronizeAddresses -import com.tangem.screens.* +import com.tangem.screens.onMainScreen +import com.tangem.screens.onSwapStoriesScreen +import com.tangem.screens.onSwapTokenScreen +import com.tangem.screens.onTokenDetailsScreen import dagger.hilt.android.testing.HiltAndroidTest import io.qameta.allure.kotlin.AllureId import io.qameta.allure.kotlin.junit4.DisplayName @@ -124,97 +123,6 @@ class TokenDetailsScreenActionButtonsTest : BaseTestCase() { } } - @AllureId("4460") - @DisplayName("Action buttons (token details screen): check 'Swap' button (provider error)") - @Test - fun checkSwapButtonProviderErrorTest() { - val tokenTitle = "POL (ex-MATIC)" - - setupHooks().run { - step("Open 'Main Screen'") { - openMainScreen() - } - step("Synchronize addresses") { - synchronizeAddresses() - } - step("Swipe up") { - swipeVertical(SwipeDirection.UP) - } - step("Click on token with name: '$tokenTitle'") { - waitForIdle() - onMainScreen { tokenWithTitleAndAddress(tokenTitle).performClick() } - } - step("Assert 'Swap' button is dimmed") { - onTokenDetailsScreen { swapButton().assertIsDimmed() } - } - step("Click on 'Swap' button") { - onTokenDetailsScreen { swapButton().performClick() } - } - step("Assert swapping $tokenTitle is not supported dialog text is displayed") { - onSwapIsNotSupportedDialog { text(tokenTitle).assertIsDisplayed() } - } - step("Assert 'Ok' button is displayed") { - onSwapIsNotSupportedDialog { okButton.assertIsDisplayed() } - } - step("Click on 'Ok' button") { - onSwapIsNotSupportedDialog { okButton.performClick() } - } - step("Assert 'Swap' button is dimmed") { - onTokenDetailsScreen { swapButton().assertIsDimmed() } - } - } - } - - @AllureId("4461") - @DisplayName("Action buttons (token details screen): check 'Swap' button (Express error)") - @Test - fun checkSwapButtonExpressErrorTest() { - val tokenTitle = "Polygon" - val scenarioName = "express_api_assets" - val scenarioState = "Error" - - setupHooks( - additionalAfterSection = { - resetWireMockScenarioState(scenarioName) - } - ).run { - step("Set WireMock scenario: '$scenarioName' to state: '$scenarioState'") { - setWireMockScenarioState(scenarioName, scenarioState) - } - step("Open 'Main Screen'") { - openMainScreen() - } - step("Synchronize addresses") { - synchronizeAddresses() - } - step("Swipe up") { - swipeVertical(SwipeDirection.UP) - } - step("Click on token with name: '$tokenTitle'") { - waitForIdle() - onMainScreen { tokenWithTitleAndAddress(tokenTitle).performClick() } - } - step("Assert 'Swap' button is dimmed") { - onTokenDetailsScreen { swapButton().assertIsDimmed() } - } - step("Click on 'Swap' button") { - onTokenDetailsScreen { swapButton().performClick() } - } - step("Assert operation is unavailable dialog text is displayed") { - onOperationIsUnavailableDialog { text.assertIsDisplayed() } - } - step("Assert 'Ok' button is displayed") { - onOperationIsUnavailableDialog { okButton.assertIsDisplayed() } - } - step("Click on 'Ok' button") { - onOperationIsUnavailableDialog { okButton.performClick() } - } - step("Assert 'Swap' button is dimmed") { - onTokenDetailsScreen { swapButton().assertIsDimmed() } - } - } - } - @AllureId("3590") @DisplayName("Action buttons (token details screen): validate UI") @Test diff --git a/app/src/androidTest/kotlin/com/tangem/tests/swap/SwapChooseTokenScreenTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/swap/SwapChooseTokenScreenTest.kt index 9bf3c4f8a1..f84fdea929 100644 --- a/app/src/androidTest/kotlin/com/tangem/tests/swap/SwapChooseTokenScreenTest.kt +++ b/app/src/androidTest/kotlin/com/tangem/tests/swap/SwapChooseTokenScreenTest.kt @@ -86,12 +86,7 @@ class SwapChooseTokenScreenTest : BaseTestCase() { onSwapChooseTokenScreen { tokenWithTitle(bitcoin).assertIsNotDisplayed() } } step("Assert '$jesusCoin' is displayed and unavailable for swap") { - onSwapChooseTokenScreen { - tokenWithTitle( - tokenTitle = jesusCoin, - availableForSwap = false - ).assertIsDisplayed() - } + onSwapChooseTokenScreen { tokenWithTitle(tokenTitle = jesusCoin).assertIsDisplayed() } } step("Assert custom token without backend id '$salam' is not displayed") { onSwapChooseTokenScreen { tokenWithTitle(salam).assertIsNotDisplayed() } diff --git a/app/src/androidTest/kotlin/com/tangem/tests/swap/SwapTokenScreenTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/swap/SwapTokenScreenTest.kt index e4112e9c00..095b1ccacb 100644 --- a/app/src/androidTest/kotlin/com/tangem/tests/swap/SwapTokenScreenTest.kt +++ b/app/src/androidTest/kotlin/com/tangem/tests/swap/SwapTokenScreenTest.kt @@ -461,8 +461,6 @@ class SwapTokenScreenTest : BaseTestCase() { val polygon = "Polygon" val bitcoin = "Bitcoin" val salam = "Salam" - val jesusCoin = "Jesus Coin" - val myria = "Myria" val scenarioState = "CustomTokenAndJesusAdded" setupHooks( @@ -505,30 +503,6 @@ class SwapTokenScreenTest : BaseTestCase() { step("Assert 'Swap' button is dimmed") { onTokenDetailsScreen { swapButton().assertIsDimmed(true) } } - step("Press 'Back' button") { - device.uiDevice.pressBack() - } - step("Swipe up") { - onMainScreen { tokenWithTitleAndAddress(jesusCoin).assertIsDisplayed() } - waitForIdle() - swipeVertical(SwipeDirection.UP) - } - step("Click on token with name: '$jesusCoin' in 'Ethereum' network. Swap unavailable") { - waitForIdle() - onMainScreen { tokenWithTitleAndAddress(jesusCoin).clickWithAssertion() } - } - step("Assert 'Swap' button is dimmed") { - onTokenDetailsScreen { swapButton().assertIsDimmed(true) } - } - step("Press 'Back' button") { - device.uiDevice.pressBack() - } - step("Click on custom token with 'exchangeAvailable=true': '$myria'. Swap unavailable") { - onMainScreen { tokenWithTitleAndAddress(myria).clickWithAssertion() } - } - step("Assert 'Swap' button is dimmed") { - onTokenDetailsScreen { swapButton().assertIsDimmed(true) } - } } } @@ -592,10 +566,9 @@ class SwapTokenScreenTest : BaseTestCase() { fun unableToCoverMarketAndFastFeeTest() { val tokenName = "POL (ex-MATIC)" val inputAmount = "0.0001" - val market = "Market" - val fast = "Fast" - val marketFeeAmount = "$18,932" - val fastFeeAmount = "$24,139" + val marketFeeType = "Market" + val fastFeeType = "Fast" + val feeAmount = "$" val scenarioName = "eth_network_balance" val scenarioState = "LessThanDollar" val networkName = "Ethereum" @@ -633,9 +606,9 @@ class SwapTokenScreenTest : BaseTestCase() { textInput.performTextReplacement(inputAmount) } } - step("Select '$market' fee type") { + step("Select '$marketFeeType' fee type") { flakySafely(WAIT_UNTIL_TIMEOUT_LONG) { - selectFeeType(FeeType.Market, selectedFeeAmount = marketFeeAmount) + selectFeeType(feeType = FeeType.Market, feeAmount) } } step("Check 'Unable to cover '$networkName' fee notification") { @@ -644,9 +617,9 @@ class SwapTokenScreenTest : BaseTestCase() { step("Assert 'Swap' button is disabled") { onSwapTokenScreen { swapButton.assertIsNotEnabled() } } - step("Select '$fast' fee type") { + step("Select '$fastFeeType' fee type") { flakySafely(WAIT_UNTIL_TIMEOUT_LONG) { - selectFeeType(FeeType.Fast, selectedFeeAmount = fastFeeAmount) + selectFeeType(feeType = FeeType.Fast, feeAmount) } } step("Check 'Unable to cover '$networkName' fee notification") { @@ -658,9 +631,6 @@ class SwapTokenScreenTest : BaseTestCase() { } } - @ApiEnv( - ApiEnvConfig(ApiConfig.ID.Express, ApiEnvironment.PROD) - ) @AllureId("8537") @DisplayName("Swap: check switch fee type (unable to cover 'Fast' fee)") @Test @@ -716,26 +686,25 @@ class SwapTokenScreenTest : BaseTestCase() { } step("Select '$fastFeeType' fee type") { flakySafely(WAIT_UNTIL_TIMEOUT_LONG) { - selectFeeType(FeeType.Fast, selectedFeeAmount = fastFeeAmount) + selectFeeTypeWithGasless(feeType = FeeType.Fast, fastFeeAmount) } } step("Assert fee amount is equal to '$fastFeeType' fee:'$fastFeeAmount'") { onSwapTokenScreen { feeAmount.assertTextContains(fastFeeAmount, substring = true) } } step("Check 'Unable to cover '$networkName' fee notification") { - chackUnableToCoverFeeNotification(networkName = networkName, currencySymbol = currencySymbol) + flakySafely(WAIT_UNTIL_TIMEOUT_LONG) { + chackUnableToCoverFeeNotification(networkName = networkName, currencySymbol = currencySymbol) + } } step("Assert 'Swap' button is disabled") { onSwapTokenScreen { swapButton.assertIsNotEnabled() } } step("Select '$marketFeeType' fee type") { flakySafely(WAIT_UNTIL_TIMEOUT_LONG) { - selectFeeType(FeeType.Market, selectedFeeAmount = marketFeeAmount) + selectFeeTypeWithGasless(feeType = FeeType.Market, marketFeeAmount) } } - step("Assert fee amount is equal to '$marketFeeType' fee:'$marketFeeAmount'") { - onSwapTokenScreen { feeAmount.assertTextContains(marketFeeAmount, substring = true) } - } step("Assert 'Swap' button is enabled") { waitForIdle() onSwapTokenScreen { swapButton.assertIsEnabled() } diff --git a/app/src/androidTest/kotlin/com/tangem/tests/swap/SwapTokenScreenWarningsTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/swap/SwapTokenScreenWarningsTest.kt index 4ba809b933..a64fd32341 100644 --- a/app/src/androidTest/kotlin/com/tangem/tests/swap/SwapTokenScreenWarningsTest.kt +++ b/app/src/androidTest/kotlin/com/tangem/tests/swap/SwapTokenScreenWarningsTest.kt @@ -6,6 +6,7 @@ import com.tangem.common.annotations.ApiEnv import com.tangem.common.annotations.ApiEnvConfig 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.* import com.tangem.common.utils.resetWireMockScenarioState import com.tangem.common.utils.setWireMockScenarioState @@ -126,10 +127,9 @@ class SwapTokenScreenWarningsTest : BaseTestCase() { } } step("Check 'Unable to cover '$networkName' fee notification") { - chackUnableToCoverFeeNotification(networkName = networkName, currencySymbol = currencySymbol) - } - step("Assert 'Unable to cover '$networkName' fee notification icon is displayed'") { - onSwapTokenScreen { unableToCoverFeeNotificationIcon(networkName).assertIsDisplayed() } + flakySafely(WAIT_UNTIL_TIMEOUT_LONG) { + chackUnableToCoverFeeNotification(networkName = networkName, currencySymbol = currencySymbol) + } } step("Assert 'Swap' button is disabled") { onSwapTokenScreen { swapButton.assertIsNotEnabled() } @@ -202,7 +202,12 @@ class SwapTokenScreenWarningsTest : BaseTestCase() { } } step("Assert fiat amount with warning is displayed") { - onSwapTokenScreen { receiveFiatAmountWithPriceImpactWarning.assertTextContains("%", substring = true) } + flakySafely(WAIT_UNTIL_TIMEOUT_LONG) { + onSwapTokenScreen { + waitForIdle() + receiveFiatAmountWithPriceImpactWarning.assertTextContains("%", substring = true) + } + } } step("Assert receive amount information icon is displayed") { onSwapTokenScreen { receiveFiatAmountInformationIcon.assertIsDisplayed() }