diff --git a/app/src/androidTest/kotlin/com/tangem/common/constants/TestConstants.kt b/app/src/androidTest/kotlin/com/tangem/common/constants/TestConstants.kt index a985597ee8..dc2be15e46 100644 --- a/app/src/androidTest/kotlin/com/tangem/common/constants/TestConstants.kt +++ b/app/src/androidTest/kotlin/com/tangem/common/constants/TestConstants.kt @@ -6,4 +6,6 @@ object TestConstants { const val RECIPIENT_ADDRESS = "0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0" const val WAIT_UNTIL_TIMEOUT = 20_000L + + const val MARKETS_MAIN_NETWORK_SUFFIX = "MAIN" } \ No newline at end of file diff --git a/app/src/androidTest/kotlin/com/tangem/common/extensions/BaseTestCaseExt.kt b/app/src/androidTest/kotlin/com/tangem/common/extensions/BaseTestCaseExt.kt index 72637225d9..daace0f71a 100644 --- a/app/src/androidTest/kotlin/com/tangem/common/extensions/BaseTestCaseExt.kt +++ b/app/src/androidTest/kotlin/com/tangem/common/extensions/BaseTestCaseExt.kt @@ -1,11 +1,15 @@ package com.tangem.common.extensions +import androidx.test.uiautomator.By import com.tangem.common.BaseTestCase +import com.tangem.wallet.R +import io.github.kakaocup.kakao.common.utilities.getResourceString -fun BaseTestCase.swipeUp( - startHeightRatio: Float = 0.8f, - endHeightRatio: Float = 0.03f, - steps: Int = 15 +fun BaseTestCase.swipeVertical( + direction: SwipeDirection, + startHeightRatio: Float = if (direction == SwipeDirection.UP) 0.8f else 0.03f, + endHeightRatio: Float = if (direction == SwipeDirection.UP) 0.03f else 0.8f, + steps: Int = 15, ) { device.uiDevice.swipe( device.uiDevice.displayWidth / 2, @@ -14,4 +18,41 @@ fun BaseTestCase.swipeUp( (device.uiDevice.displayHeight * endHeightRatio).toInt(), steps ) +} + +fun BaseTestCase.pullToRefresh() { + swipeVertical( + direction = SwipeDirection.DOWN, + startHeightRatio = 0.2f, + endHeightRatio = 0.8f, + steps = 2000 + ) +} + +fun BaseTestCase.swipeMarketsBlock(direction: SwipeDirection) { + val searchBarText = device.uiDevice + .findObject(By.textContains(getResourceString(R.string.markets_search_header_title))) + val bounds = searchBarText.visibleBounds + + val centerX = bounds.centerX() + val startY = bounds.centerY() + val endY = when (direction) { + SwipeDirection.UP -> 50 + SwipeDirection.DOWN -> device.uiDevice.displayHeight - 100 + } + + device.uiDevice.swipe(centerX, startY, centerX, endY, 100) +} + +fun BaseTestCase.openTheAppFromRecents() { + device.uiDevice.pressRecentApps() + + val centerX = device.uiDevice.displayWidth / 2 + val centerY = device.uiDevice.displayHeight / 3 + device.uiDevice.click(centerX, centerY) + device.uiDevice.click(centerX, centerY) +} + +enum class SwipeDirection { + UP, DOWN } \ No newline at end of file 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 a7baa714a4..7c275607c9 100644 --- a/app/src/androidTest/kotlin/com/tangem/common/extensions/KNode.kt +++ b/app/src/androidTest/kotlin/com/tangem/common/extensions/KNode.kt @@ -5,4 +5,5 @@ import io.github.kakaocup.compose.node.element.KNode fun KNode.clickWithAssertion() { assertIsDisplayed() performClick() -} \ No newline at end of file +} + diff --git a/app/src/androidTest/kotlin/com/tangem/screens/BaseBottomSheetPageObject.kt b/app/src/androidTest/kotlin/com/tangem/screens/BaseBottomSheetPageObject.kt new file mode 100644 index 0000000000..d40a96c38a --- /dev/null +++ b/app/src/androidTest/kotlin/com/tangem/screens/BaseBottomSheetPageObject.kt @@ -0,0 +1,22 @@ +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(semanticsProvider = semanticsProvider) { + + val hideButton: KNode = child { + hasText(getResourceString(R.string.token_details_hide_token)) + hasTestTag(BaseBottomSheetTestTags.ACTION_TITLE) + } +} + +internal fun BaseTestCase.onBottomSheet(function: BaseBottomSheetPageObject.() -> Unit) = + onComposeScreen(composeTestRule, function) \ No newline at end of file diff --git a/app/src/androidTest/kotlin/com/tangem/screens/DialogPageObject.kt b/app/src/androidTest/kotlin/com/tangem/screens/DialogPageObject.kt index e60f497bc3..9543830d26 100644 --- a/app/src/androidTest/kotlin/com/tangem/screens/DialogPageObject.kt +++ b/app/src/androidTest/kotlin/com/tangem/screens/DialogPageObject.kt @@ -31,6 +31,16 @@ class DialogPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) : hasTestTag(BaseButtonTestTags.BUTTON) hasText(getResourceString(R.string.common_confirm)) } + + val continueButton: KNode = child { + hasTestTag(BaseButtonTestTags.BUTTON) + hasText(getResourceString(R.string.common_continue)) + } + + val okButton: KNode = child { + hasTestTag(BaseButtonTestTags.BUTTON) + hasText(getResourceString(R.string.common_ok)) + } } internal fun BaseTestCase.onDialog(function: DialogPageObject.() -> Unit) = diff --git a/app/src/androidTest/kotlin/com/tangem/screens/MarketsPageObject.kt b/app/src/androidTest/kotlin/com/tangem/screens/MarketsPageObject.kt new file mode 100644 index 0000000000..4f6707a071 --- /dev/null +++ b/app/src/androidTest/kotlin/com/tangem/screens/MarketsPageObject.kt @@ -0,0 +1,60 @@ +package com.tangem.screens + +import androidx.compose.ui.test.SemanticsMatcher +import androidx.compose.ui.test.SemanticsNodeInteractionsProvider +import com.tangem.common.BaseTestCase +import com.tangem.common.constants.TestConstants.MARKETS_MAIN_NETWORK_SUFFIX +import com.tangem.common.utils.LazyListItemNode +import com.tangem.core.ui.test.BaseButtonTestTags +import com.tangem.core.ui.test.MarketsTestTags +import com.tangem.core.ui.test.TopAppBarTestTags +import com.tangem.core.ui.utils.LazyListItemPositionSemantics +import com.tangem.features.onramp.impl.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.compose.node.element.lazylist.KLazyListNode +import io.github.kakaocup.kakao.common.utilities.getResourceString +import androidx.compose.ui.test.hasText as withText + +class MarketsPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) : + ComposeScreen(semanticsProvider = semanticsProvider) { + + private val lazyList = KLazyListNode( + semanticsProvider = semanticsProvider, + viewBuilderAction = { hasTestTag(MarketsTestTags.TOKENS_LIST) }, + itemTypeBuilder = { itemType(::LazyListItemNode) }, + positionMatcher = { position -> + SemanticsMatcher.expectValue( + LazyListItemPositionSemantics, + position + ) + } + ) + + val addToPortfolioButton: KNode = child { + hasTestTag(BaseButtonTestTags.TEXT) + hasText(getResourceString(R.string.common_add_to_portfolio)) + useUnmergedTree = true + } + + val mainNetworkSwitch: KNode = child { + hasAnyDescendant(withText(MARKETS_MAIN_NETWORK_SUFFIX)) + useUnmergedTree = true + }.child { hasTestTag(MarketsTestTags.ADD_TO_PORTFOLIO_SWITCH) } + + val topBarBackButton: KNode = child { + hasTestTag(TopAppBarTestTags.CLOSE_BUTTON) + useUnmergedTree = true + } + + fun tokenWithTitle(title: String): KNode { + return lazyList.child { + hasText(title) + useUnmergedTree = true + } + } +} + +internal fun BaseTestCase.onMarketsScreen(function: MarketsPageObject.() -> Unit) = + onComposeScreen(composeTestRule, function) \ No newline at end of file diff --git a/app/src/androidTest/kotlin/com/tangem/screens/SearchBarPageObject.kt b/app/src/androidTest/kotlin/com/tangem/screens/SearchBarPageObject.kt new file mode 100644 index 0000000000..45e3fae83b --- /dev/null +++ b/app/src/androidTest/kotlin/com/tangem/screens/SearchBarPageObject.kt @@ -0,0 +1,19 @@ +package com.tangem.screens + +import androidx.compose.ui.test.SemanticsNodeInteractionsProvider +import com.tangem.common.BaseTestCase +import com.tangem.core.ui.test.BaseSearchBarTestTags +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 SearchBarPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) : + ComposeScreen(semanticsProvider = semanticsProvider) { + + val searchField: KNode = child { + hasTestTag(BaseSearchBarTestTags.SEARCH_BAR) + } +} + +internal fun BaseTestCase.onSearchBar(function: SearchBarPageObject.() -> Unit) = + onComposeScreen(composeTestRule, function) \ No newline at end of file diff --git a/app/src/androidTest/kotlin/com/tangem/screens/SelectCountryPageObject.kt b/app/src/androidTest/kotlin/com/tangem/screens/SelectCountryPageObject.kt index b3a6a9d573..c3178f7435 100644 --- a/app/src/androidTest/kotlin/com/tangem/screens/SelectCountryPageObject.kt +++ b/app/src/androidTest/kotlin/com/tangem/screens/SelectCountryPageObject.kt @@ -4,6 +4,7 @@ import androidx.compose.ui.test.SemanticsMatcher import androidx.compose.ui.test.SemanticsNodeInteractionsProvider import com.tangem.common.BaseTestCase import com.tangem.common.utils.LazyListItemNode +import com.tangem.core.ui.test.BaseSearchBarTestTags import com.tangem.core.ui.test.SelectCountryBottomSheetTestTags import com.tangem.core.ui.utils.LazyListItemPositionSemantics import com.tangem.features.onramp.impl.R @@ -12,9 +13,8 @@ import io.github.kakaocup.compose.node.element.ComposeScreen.Companion.onCompose import io.github.kakaocup.compose.node.element.KNode import io.github.kakaocup.compose.node.element.lazylist.KLazyListNode import io.github.kakaocup.kakao.common.utilities.getResourceString -import androidx.compose.ui.test.hasText as withText import androidx.compose.ui.test.hasTestTag as withTestTag - +import androidx.compose.ui.test.hasText as withText class SelectCountryPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) : ComposeScreen(semanticsProvider = semanticsProvider) { @@ -33,7 +33,7 @@ class SelectCountryPageObject(semanticsProvider: SemanticsNodeInteractionsProvid ) val searchBar: KNode = child { - hasTestTag(SelectCountryBottomSheetTestTags.SEARCH_BAR) + hasTestTag(BaseSearchBarTestTags.SEARCH_BAR) useUnmergedTree = true } diff --git a/app/src/androidTest/kotlin/com/tangem/tests/HideTokenTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/HideTokenTest.kt index 9e1efb911a..fa4519eede 100644 --- a/app/src/androidTest/kotlin/com/tangem/tests/HideTokenTest.kt +++ b/app/src/androidTest/kotlin/com/tangem/tests/HideTokenTest.kt @@ -3,9 +3,9 @@ package com.tangem.tests import com.tangem.common.BaseTestCase import com.tangem.common.constants.TestConstants.TOTAL_BALANCE import com.tangem.common.extensions.clickWithAssertion -import com.tangem.screens.* import com.tangem.scenarios.openMainScreen import com.tangem.scenarios.synchronizeAddresses +import com.tangem.screens.* import dagger.hilt.android.testing.HiltAndroidTest import io.qameta.allure.kotlin.AllureId import io.qameta.allure.kotlin.junit4.DisplayName @@ -33,7 +33,7 @@ class HideTokenTest : BaseTestCase() { step("Assert 'Token details screen' open") { onTokenDetailsScreen { screenContainer.assertIsDisplayed() } } - step("Click 'More button'") { + step("Click 'More' button") { onTokenDetailsTopBar { moreButton.clickWithAssertion() } } step("Click 'Hide token' button") { diff --git a/app/src/androidTest/kotlin/com/tangem/tests/OrganizeTokensTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/OrganizeTokensTest.kt index e0f1d97826..76d0d0f0f6 100644 --- a/app/src/androidTest/kotlin/com/tangem/tests/OrganizeTokensTest.kt +++ b/app/src/androidTest/kotlin/com/tangem/tests/OrganizeTokensTest.kt @@ -3,12 +3,13 @@ package com.tangem.tests import androidx.compose.ui.test.onAllNodesWithText import com.tangem.common.BaseTestCase import com.tangem.common.constants.TestConstants.TOTAL_BALANCE +import com.tangem.common.extensions.SwipeDirection import com.tangem.common.extensions.clickWithAssertion -import com.tangem.common.extensions.swipeUp -import com.tangem.screens.onMainScreen -import com.tangem.screens.onOrganizeTokensScreen +import com.tangem.common.extensions.swipeVertical import com.tangem.scenarios.openMainScreen import com.tangem.scenarios.synchronizeAddresses +import com.tangem.screens.onMainScreen +import com.tangem.screens.onOrganizeTokensScreen import dagger.hilt.android.testing.HiltAndroidTest import io.qameta.allure.kotlin.AllureId import io.qameta.allure.kotlin.junit4.DisplayName @@ -28,12 +29,12 @@ class OrganizeTokensTest : BaseTestCase() { step("Open 'Main Screen'") { openMainScreen() } - step("Click on 'Synchronize addresses' button" ) { + step("Click on 'Synchronize addresses' button") { onMainScreen { synchronizeAddressesButton.clickWithAssertion() } } step("Swipe to 'Organize tokens' button") { - swipeUp() - swipeUp() + swipeVertical(SwipeDirection.UP) + swipeVertical(SwipeDirection.UP) } step("Click 'Organize tokens' button") { onMainScreen { organizeTokensButton().clickWithAssertion() } @@ -57,8 +58,8 @@ class OrganizeTokensTest : BaseTestCase() { onMainScreen { tokenNetworkGroupTitle(tokenNetwork).assertIsDisplayed() } } step("Swipe to 'Organize tokens' button") { - swipeUp() - swipeUp() + swipeVertical(SwipeDirection.UP) + swipeVertical(SwipeDirection.UP) } step("Click 'Organize tokens' button") { onMainScreen { organizeTokensButton().clickWithAssertion() } @@ -106,8 +107,8 @@ class OrganizeTokensTest : BaseTestCase() { } } step("Swipe to 'Organize tokens' button") { - swipeUp() - swipeUp() + swipeVertical(SwipeDirection.UP) + swipeVertical(SwipeDirection.UP) } step("Click 'Organize tokens' button") { onMainScreen { organizeTokensButton().clickWithAssertion() } @@ -133,7 +134,7 @@ class OrganizeTokensTest : BaseTestCase() { step("Open 'Main Screen'") { openMainScreen() } - step("Click on 'Synchronize addresses' button" ) { + step("Click on 'Synchronize addresses' button") { onMainScreen { synchronizeAddressesButton.clickWithAssertion() } } step("Check positions of tokens on 'Main Screen'") { @@ -143,8 +144,8 @@ class OrganizeTokensTest : BaseTestCase() { } } step("Swipe to 'Organize tokens' button") { - swipeUp() - swipeUp() + swipeVertical(SwipeDirection.UP) + swipeVertical(SwipeDirection.UP) } step("Click 'Organize tokens' button") { onMainScreen { organizeTokensButton().clickWithAssertion() } @@ -194,8 +195,8 @@ class OrganizeTokensTest : BaseTestCase() { } } step("Swipe to 'Organize tokens' button") { - swipeUp() - swipeUp() + swipeVertical(SwipeDirection.UP) + swipeVertical(SwipeDirection.UP) } step("Click 'Organize tokens' button") { onMainScreen { organizeTokensButton().clickWithAssertion() } @@ -234,6 +235,4 @@ class OrganizeTokensTest : BaseTestCase() { } } } - - } \ No newline at end of file diff --git a/app/src/androidTest/kotlin/com/tangem/tests/TermsOfServiceTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/TermsOfServiceTest.kt index 7f729f1c3c..379b5b898e 100644 --- a/app/src/androidTest/kotlin/com/tangem/tests/TermsOfServiceTest.kt +++ b/app/src/androidTest/kotlin/com/tangem/tests/TermsOfServiceTest.kt @@ -2,8 +2,9 @@ package com.tangem.tests import androidx.test.InstrumentationRegistry.getTargetContext import com.tangem.common.BaseTestCase +import com.tangem.common.extensions.SwipeDirection import com.tangem.common.extensions.clickWithAssertion -import com.tangem.common.extensions.swipeUp +import com.tangem.common.extensions.swipeVertical import com.tangem.screens.onDisclaimerScreen import com.tangem.screens.onStoriesScreen import dagger.hilt.android.testing.HiltAndroidTest @@ -37,7 +38,8 @@ class TermsOfServiceTest : BaseTestCase() { step("Assert 'Stories' screen is opened") { onStoriesScreen { scanButton.assertIsDisplayed() - orderButton.assertIsDisplayed()} + orderButton.assertIsDisplayed() + } } } } @@ -67,7 +69,7 @@ class TermsOfServiceTest : BaseTestCase() { device.uiDevice.pressRecentApps() } step("Stop app by swipe") { - swipeUp(startHeightRatio = 0.5f) + swipeVertical(SwipeDirection.UP, startHeightRatio = 0.5f) } step("Launch app") { device.apps.launch(packageName) @@ -90,7 +92,7 @@ class TermsOfServiceTest : BaseTestCase() { device.uiDevice.pressRecentApps() } step("Stop app by swipe") { - swipeUp(startHeightRatio = 0.5f) + swipeVertical(SwipeDirection.UP, startHeightRatio = 0.5f) } step("Launch app") { device.apps.launch(packageName) @@ -98,9 +100,9 @@ class TermsOfServiceTest : BaseTestCase() { step("Assert 'Stories' screen is opened") { onStoriesScreen { scanButton.assertIsDisplayed() - orderButton.assertIsDisplayed()} + orderButton.assertIsDisplayed() + } } } } - } \ No newline at end of file diff --git a/app/src/androidTest/kotlin/com/tangem/tests/WalletConnectTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/WalletConnectTest.kt index b0f6b79e78..db5e364f20 100644 --- a/app/src/androidTest/kotlin/com/tangem/tests/WalletConnectTest.kt +++ b/app/src/androidTest/kotlin/com/tangem/tests/WalletConnectTest.kt @@ -2,11 +2,12 @@ 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.extensions.clickWithAssertion -import com.tangem.common.extensions.swipeUp +import com.tangem.common.extensions.swipeVertical import com.tangem.common.utils.getWcUri -import com.tangem.screens.* import com.tangem.scenarios.* +import com.tangem.screens.* import dagger.hilt.android.testing.HiltAndroidTest import io.qameta.allure.kotlin.AllureId import io.qameta.allure.kotlin.junit4.DisplayName @@ -140,7 +141,7 @@ class WalletConnectTest : BaseTestCase() { device.uiDevice.pressRecentApps() } step("Stop app by swipe") { - swipeUp(startHeightRatio = 0.8f) + swipeVertical(SwipeDirection.UP, startHeightRatio = 0.8f) } step("Create WC session buy deeplink") { openAppByDeepLink(deepLinkUri) diff --git a/app/src/androidTest/kotlin/com/tangem/tests/balance/TotalBalanceUpdateTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/balance/TotalBalanceUpdateTest.kt new file mode 100644 index 0000000000..1c7fd38068 --- /dev/null +++ b/app/src/androidTest/kotlin/com/tangem/tests/balance/TotalBalanceUpdateTest.kt @@ -0,0 +1,209 @@ +package com.tangem.tests.balance + +import androidx.compose.ui.test.longClick +import com.tangem.common.BaseTestCase +import com.tangem.common.constants.TestConstants.TOTAL_BALANCE +import com.tangem.common.extensions.* +import com.tangem.common.utils.resetWireMockScenarioState +import com.tangem.common.utils.setWireMockScenarioState +import com.tangem.scenarios.openMainScreen +import com.tangem.scenarios.synchronizeAddresses +import com.tangem.screens.* +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 TotalBalanceUpdateTest : BaseTestCase() { + + @Test + @AllureId("150") + @DisplayName("Total balance: check balance update after pull to refresh") + fun afterPullToRefreshTest() { + val scenarioName = "eth_network_balance" + val scenarioState = "Empty" + val updatedBalance = "$763.55" + setupHooks( + additionalAfterSection = { + resetWireMockScenarioState(scenarioName) + } + ).run { + step("Open 'Main Screen'") { + openMainScreen() + } + step("Synchronize addresses") { + synchronizeAddresses(TOTAL_BALANCE) + } + step("Assert $TOTAL_BALANCE is displayed in total balance") { + onMainScreen { totalBalanceText.assertTextContains(TOTAL_BALANCE) } + } + step("Set WireMock scenario: '$scenarioName' to state: '$scenarioState'") { + setWireMockScenarioState(scenarioName = scenarioName, state = scenarioState) + } + step("Perform pull to refresh") { + pullToRefresh() + } + step("Assert Total balance is updated from $TOTAL_BALANCE to $updatedBalance") { + onMainScreen { totalBalanceText.assertTextContains(updatedBalance) } + } + } + } + + @Test + @AllureId("3997") + @DisplayName("Total balance: check balance update after token added") + fun afterAddTokenTest() { + val tokenTitle = "XRP" + val scenarioName = "quotes_api" + val scenarioState = "Ripple" + val updatedBalance = "$3,307.18" + setupHooks( + additionalAfterSection = { + resetWireMockScenarioState(scenarioName) + } + ).run { + step("Open 'Main Screen'") { + openMainScreen() + } + step("Synchronize addresses") { + synchronizeAddresses(TOTAL_BALANCE) + } + step("Assert $TOTAL_BALANCE is displayed in total balance") { + onMainScreen { totalBalanceText.assertTextContains(TOTAL_BALANCE) } + } + step("Open 'Markets screen'") { + swipeMarketsBlock(SwipeDirection.UP) + composeTestRule.waitForIdle() + } + step("Click on $tokenTitle token") { + onMarketsScreen { tokenWithTitle(tokenTitle).clickWithAssertion() } + } + step("Set WireMock scenario: '$scenarioName' to state: '$scenarioState'") { + setWireMockScenarioState(scenarioName = scenarioName, state = scenarioState) + } + step("Click on 'Add to portfolio' button") { + onMarketsScreen { addToPortfolioButton.clickWithAssertion() } + } + step("Toggle the main network switch") { + onMarketsScreen { mainNetworkSwitch.performClick() } + } + step("Click on 'Continue' button") { + onDialog { continueButton.clickWithAssertion() } + } + step("Assert 'Continue' is not displayed") { + onDialog { continueButton.assertIsNotDisplayed() } + } + step("Go back to 'Markets: tokens list'") { + composeTestRule.waitForIdle() + onMarketsScreen { topBarBackButton.clickWithAssertion() } + } + step("Close 'Markets screen'") { + onSearchBar { searchField.assertIsDisplayed() } + swipeMarketsBlock(SwipeDirection.DOWN) + } + step("Assert $updatedBalance is displayed in total balance") { + onMainScreen { totalBalanceText.assertTextContains(updatedBalance) } + } + } + } + + @Test + @AllureId("4000") + @DisplayName("Total balance: check balance update after collapse/expand") + fun afterCollapseAndExpandTest() { + setupHooks().run { + step("Open 'Main Screen'") { + openMainScreen() + } + step("Synchronize addresses") { + synchronizeAddresses(TOTAL_BALANCE) + } + step("Assert $TOTAL_BALANCE is displayed in total balance") { + onMainScreen { totalBalanceText.assertTextContains(TOTAL_BALANCE) } + } + step("Press 'Home' to collapse the app") { + device.uiDevice.pressHome() + } + step("Open the app from recent apps") { + openTheAppFromRecents() + } + step("Assert $TOTAL_BALANCE is displayed in total balance") { + onMainScreen { totalBalanceText.assertTextContains(TOTAL_BALANCE) } + } + } + } + + @Test + @AllureId("3998") + @DisplayName("Total balance: check balance update after hide token") + fun afterHideTokenTest() { + val tokenTitle = "Polygon" + val updatedBalance = "$3,114.34" + setupHooks().run { + step("Open 'Main Screen'") { + openMainScreen() + } + step("Synchronize addresses") { + synchronizeAddresses(TOTAL_BALANCE) + } + step("Assert $TOTAL_BALANCE is displayed in total balance") { + onMainScreen { totalBalanceText.assertTextContains(TOTAL_BALANCE) } + } + step("Long click on token with name: '$tokenTitle'") { + composeTestRule.waitForIdle() + onMainScreen { + tokenWithTitleAndAddress(tokenTitle).performTouchInput { + longClick( + position = center, + durationMillis = 1000L + ) + } + } + } + step("Click 'Hide token' button") { + onBottomSheet { hideButton.clickWithAssertion() } + } + step("Click 'Hide' button in dialog") { + onDialog { + dialogContainer.assertIsDisplayed() + okButton.clickWithAssertion() + } + } + step("Assert $updatedBalance is displayed in total balance") { + swipeVertical(SwipeDirection.DOWN) + onMainScreen { totalBalanceText.assertTextContains(updatedBalance) } + } + } + } + + @Test + @AllureId("4001") + @DisplayName("Total balance: check balance update after navigation") + fun afterNavigationTest() { + val tokenTitle = "Polygon" + setupHooks().run { + step("Open 'Main Screen'") { + openMainScreen() + } + step("Synchronize addresses") { + synchronizeAddresses(TOTAL_BALANCE) + } + step("Assert $TOTAL_BALANCE is displayed in total balance") { + onMainScreen { totalBalanceText.assertTextContains(TOTAL_BALANCE) } + } + step("Click on token with name: '$tokenTitle'") { + onMainScreen { tokenWithTitleAndAddress(tokenTitle).clickWithAssertion() } + } + step("Assert 'Token details screen' open") { + onTokenDetailsScreen { screenContainer.assertIsDisplayed() } + } + step("Click 'More' button") { + onTokenDetailsTopBar { backButton.clickWithAssertion() } + } + step("Assert $TOTAL_BALANCE is displayed in total balance") { + onMainScreen { totalBalanceText.assertTextContains(TOTAL_BALANCE) } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/sdk/mocks/content/WalletMockContent.kt b/app/src/main/java/com/tangem/tap/domain/sdk/mocks/content/WalletMockContent.kt index f562753a55..1db7cd1bb9 100644 --- a/app/src/main/java/com/tangem/tap/domain/sdk/mocks/content/WalletMockContent.kt +++ b/app/src/main/java/com/tangem/tap/domain/sdk/mocks/content/WalletMockContent.kt @@ -198,6 +198,13 @@ object WalletMockContent : MockContent { parentFingerprint = byteArrayOf(0, 0, 0, 0), childNumber = 0, ), + DerivationPath("m/44'/144'/0'/0/0") to ExtendedPublicKey( // xrp + publicKey = byteArrayOf(2, 38, -6, 92, -37, -91, -59, -108, -18, -119, -55, 41, 38, -33, 44, 59, 24, -79, -14, -38, -10, -123, 106, 56, 39, 8, 112, 29, -41, 99, 70, -104, -121), + chainCode = byteArrayOf(105, -21, -61, -50, 68, -89, 119, 53, -96, -40, 119, 77, -122, 121, 16, 40, -50, -48, -105, -101, -74, -7, -94, -59, -90, 96, 59, 99, 43, -91, 115, -29), + depth = 0, + parentFingerprint = byteArrayOf(0, 0, 0, 0), + childNumber = 0, + ), DerivationPath("m/44'/3'/0'/0/0") to ExtendedPublicKey( // doge publicKey = byteArrayOf(3, -25, -24, -97, -124, 24, -89, 44, 75, 123, 92, -86, -73, -93, 25, -90, -89, -95, 88, 3, 107, 37, -1, -85, -32, -57, -123, -41, 108, -9, -96, 77, -124), chainCode = byteArrayOf(119, 3, 41, 112, 71, 54, 72, 30, 39, 25, 25, -104, 92, 46, -109, 63, 93, 67, 43, -102, -87, 39, -95, 106, 45, 67, 109, -29, -35, 10, -107, 104), diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/SettingsRow.kt b/core/ui/src/main/java/com/tangem/core/ui/components/SettingsRow.kt index b1b8fa87b0..b49c5737ad 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/SettingsRow.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/SettingsRow.kt @@ -11,8 +11,10 @@ import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.test.BaseBottomSheetTestTags /** * [Show in Figma](https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?type=design&node-id=281-248&mode=design&t=bXqehWPHyATKcZEW-4) @@ -38,7 +40,7 @@ fun SimpleSettingsRow( onItemsClick() } }, - ), + ).testTag(BaseBottomSheetTestTags.ACTION_TITLE), horizontalArrangement = Arrangement.Start, verticalAlignment = Alignment.CenterVertically, ) { diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/TangemSwitch.kt b/core/ui/src/main/java/com/tangem/core/ui/components/TangemSwitch.kt index 972f347106..de1f9aa454 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/TangemSwitch.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/TangemSwitch.kt @@ -15,10 +15,12 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.testTag import androidx.compose.ui.semantics.Role import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.test.MarketsTestTags @Suppress("MagicNumber") @Composable @@ -56,7 +58,7 @@ fun TangemSwitch( onClick = { onCheckedChange(!checked) }, - ), + ).testTag(MarketsTestTags.ADD_TO_PORTFOLIO_SWITCH), ) { BoxWithConstraints( modifier = Modifier diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/fields/SearchBar.kt b/core/ui/src/main/java/com/tangem/core/ui/components/fields/SearchBar.kt index 12847efe53..94f6b64e78 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/fields/SearchBar.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/fields/SearchBar.kt @@ -38,7 +38,7 @@ import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview -import com.tangem.core.ui.test.SelectCountryBottomSheetTestTags +import com.tangem.core.ui.test.BaseSearchBarTestTags @Composable fun SearchBar( @@ -64,7 +64,7 @@ fun SearchBar( } } .focusRequester(focusRequester) - .testTag(SelectCountryBottomSheetTestTags.SEARCH_BAR), + .testTag(BaseSearchBarTestTags.SEARCH_BAR), enabled = enabled, value = state.query, onValueChange = state.onQueryChange, diff --git a/core/ui/src/main/java/com/tangem/core/ui/test/BaseBottomSheetTestTags.kt b/core/ui/src/main/java/com/tangem/core/ui/test/BaseBottomSheetTestTags.kt new file mode 100644 index 0000000000..2604a7ad0e --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/test/BaseBottomSheetTestTags.kt @@ -0,0 +1,5 @@ +package com.tangem.core.ui.test + +object BaseBottomSheetTestTags { + const val ACTION_TITLE = "BASE_BOTTOM_SHEET_ACTION_TITLE" +} \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/test/BaseSearchBarTestTags.kt b/core/ui/src/main/java/com/tangem/core/ui/test/BaseSearchBarTestTags.kt new file mode 100644 index 0000000000..ad2b165837 --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/test/BaseSearchBarTestTags.kt @@ -0,0 +1,5 @@ +package com.tangem.core.ui.test + +object BaseSearchBarTestTags { + const val SEARCH_BAR = "BASE_SEARCH_BAR" +} \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/test/MarketsTestTags.kt b/core/ui/src/main/java/com/tangem/core/ui/test/MarketsTestTags.kt new file mode 100644 index 0000000000..0721a092cd --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/test/MarketsTestTags.kt @@ -0,0 +1,7 @@ +package com.tangem.core.ui.test + +object MarketsTestTags { + const val TOKENS_LIST = "MARKETS_TOKENS_LIST" + const val TOKENS_LIST_ITEM = "MARKETS_TOKENS_LIST_ITEM" + const val ADD_TO_PORTFOLIO_SWITCH = "MARKETS_ADD_TO_PORTFOLIO_SWITCH" +} \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/test/SelectCountryBottomSheetTestTags.kt b/core/ui/src/main/java/com/tangem/core/ui/test/SelectCountryBottomSheetTestTags.kt index 6a2d859e19..acb5cfa60f 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/test/SelectCountryBottomSheetTestTags.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/test/SelectCountryBottomSheetTestTags.kt @@ -5,7 +5,6 @@ object SelectCountryBottomSheetTestTags { const val LAZY_LIST = "SELECT_COUNTRY_BOTTOM_SHEET_LAZY_LIST" const val COUNTRY_ITEM = "SELECT_COUNTRY_BOTTOM_SHEET_COUNTRY_ITEM" const val UNAVAILABLE_COUNTRY_ITEM = "SELECT_COUNTRY_BOTTOM_SHEET_UNAVAILABLE_COUNTRY_ITEM" - const val SEARCH_BAR = "SELECT_COUNTRY_BOTTOM_SHEET_SEARCH_BAR" const val COUNTRY_ICON = "SELECT_COUNTRY_BOTTOM_SHEET_COUNTRY_ICON" const val UNAVAILABLE_COUNTRY_ICON = "SELECT_COUNTRY_BOTTOM_SHEET_UNAVAILABLE_COUNTRY_ICON" const val COUNTRY_NAME = "SELECT_COUNTRY_BOTTOM_SHEET_COUNTRY_NAME" diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/AddToPortfolioBottomSheet.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/AddToPortfolioBottomSheet.kt index fdfbb03db2..c12a36531c 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/AddToPortfolioBottomSheet.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/AddToPortfolioBottomSheet.kt @@ -26,8 +26,8 @@ import com.tangem.common.ui.userwallet.UserWalletItem import com.tangem.core.ui.components.* import com.tangem.core.ui.components.block.TangemBlockCardColors import com.tangem.core.ui.components.block.information.InformationBlock -import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig +import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet import com.tangem.core.ui.components.buttons.common.TangemButton import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition import com.tangem.core.ui.components.buttons.common.TangemButtonSize @@ -228,9 +228,7 @@ private fun NetworkSelection(state: SelectNetworkUM, modifier: Modifier = Modifi isLastItem = index == state.networks.lastIndex, content = { BlockchainRow( - modifier = Modifier.padding( - end = TangemTheme.dimens.spacing4, - ), + modifier = Modifier.padding(end = TangemTheme.dimens.spacing4), model = network, action = { TangemSwitch( diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListItem.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListItem.kt index 01bcc834fd..e0daa6f742 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListItem.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListItem.kt @@ -12,6 +12,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.RectangleShape +import androidx.compose.ui.platform.testTag import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter @@ -28,6 +29,7 @@ import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.res.LocalWindowSize import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.core.ui.test.MarketsTestTags import com.tangem.core.ui.windowsize.WindowSizeType import com.tangem.features.markets.impl.R import com.tangem.features.markets.tokenlist.impl.ui.preview.MarketChartListItemPreviewDataProvider @@ -41,7 +43,8 @@ internal fun MarketsListItem(model: MarketsListItemUM, modifier: Modifier = Modi modifier = modifier .fillMaxWidth() .clip(RectangleShape) - .clickable(onClick = onClick), + .clickable(onClick = onClick) + .testTag(MarketsTestTags.TOKENS_LIST_ITEM), model = model, ) } diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListLazyColumn.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListLazyColumn.kt index 91029b1f71..bc0f3aea6d 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListLazyColumn.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListLazyColumn.kt @@ -10,6 +10,7 @@ import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.testTag import com.tangem.core.ui.components.UnableToLoadData import com.tangem.core.ui.components.buttons.SecondarySmallButton import com.tangem.core.ui.components.buttons.SmallButtonConfig @@ -18,6 +19,7 @@ import com.tangem.core.ui.event.EventEffect import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringResourceSafe import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.test.MarketsTestTags import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.features.markets.impl.R import com.tangem.features.markets.tokenlist.impl.ui.state.ListUM @@ -65,7 +67,7 @@ internal fun MarketsListLazyColumn( } } else { LazyColumn( - modifier = modifier, + modifier = modifier.testTag(MarketsTestTags.TOKENS_LIST), state = lazyListState, contentPadding = PaddingValues(bottom = bottomBarHeight), userScrollEnabled = true,