diff --git a/app/src/androidTest/kotlin/com/tangem/common/BaseTestCase.kt b/app/src/androidTest/kotlin/com/tangem/common/BaseTestCase.kt index df3927d4fb..a7aa7666e3 100644 --- a/app/src/androidTest/kotlin/com/tangem/common/BaseTestCase.kt +++ b/app/src/androidTest/kotlin/com/tangem/common/BaseTestCase.kt @@ -84,6 +84,7 @@ abstract class BaseTestCase : TestCase( * – and only after that the activity should be launched. */ protected fun setupHooks( + additionalBeforeAppLaunchSection: () -> Unit = {}, additionalBeforeSection: () -> Unit = {}, additionalAfterSection: () -> Unit = {}, ) = before { @@ -91,6 +92,7 @@ abstract class BaseTestCase : TestCase( // Setup WireMock redirect for CI with local WireMock instances val wiremockUrl = InstrumentationRegistry.getArguments().getString(WIREMOCK_BASE_URL_ARG) WireMockRedirectInterceptor.overriddenBaseUrl = wiremockUrl + additionalBeforeAppLaunchSection() hiltRule.inject() runBlocking { appPreferencesStore.editData { mutablePreferences -> diff --git a/app/src/androidTest/kotlin/com/tangem/common/extensions/UiDeviceExt.kt b/app/src/androidTest/kotlin/com/tangem/common/extensions/UiDeviceExt.kt index 992a417013..03dcf422f5 100644 --- a/app/src/androidTest/kotlin/com/tangem/common/extensions/UiDeviceExt.kt +++ b/app/src/androidTest/kotlin/com/tangem/common/extensions/UiDeviceExt.kt @@ -2,6 +2,7 @@ package com.tangem.common.extensions import androidx.test.uiautomator.By import com.tangem.common.BaseTestCase +import com.tangem.common.constants.TestConstants.WAIT_UNTIL_TIMEOUT_LONG import com.tangem.wallet.R import io.github.kakaocup.kakao.common.utilities.getResourceString @@ -74,8 +75,17 @@ fun BaseTestCase.stopApp(packageName: String) { } fun BaseTestCase.launchApp(packageName: String) { - device.apps.waitForAppLaunchAndReady(packageName = packageName) device.apps.launch(packageName) + device.apps.waitForAppLaunchAndReady(packageName = packageName) +} + +fun BaseTestCase.restartApp(packageName: String) { + device.uiDevice.pressHome() + device.apps.kill(packageName) + waitForIdle() + device.apps.launch(packageName) + device.apps.waitForAppLaunchAndReady(timeout = WAIT_UNTIL_TIMEOUT_LONG, packageName = packageName) + waitForIdle() } enum class SwipeDirection { diff --git a/app/src/androidTest/kotlin/com/tangem/scenarios/MarketsScenarios.kt b/app/src/androidTest/kotlin/com/tangem/scenarios/MarketsScenarios.kt new file mode 100644 index 0000000000..02142e077c --- /dev/null +++ b/app/src/androidTest/kotlin/com/tangem/scenarios/MarketsScenarios.kt @@ -0,0 +1,26 @@ +package com.tangem.scenarios + +import com.tangem.common.BaseTestCase +import com.tangem.common.extensions.clickWithAssertion +import com.tangem.screens.onMainScreen +import com.tangem.screens.onMarketsScreen +import com.tangem.screens.onMarketsTokenDetailsScreen +import io.qameta.allure.kotlin.Allure.step + +fun BaseTestCase.openMarketTokenDetailsScreen(blockchainName: String, tokenName: String) { + step("Open 'Markets' screen") { + onMainScreen { searchThroughMarketPlaceholder.performClick() } + waitForIdle() + } + step("Click on 'Search' placeholder") { + onMarketsScreen { searchThroughMarketPlaceholder.performClick() } + } + step("Click on $blockchainName blockchain") { + waitForIdle() + onMarketsScreen { tokenWithTitle(blockchainName).clickWithAssertion() } + } + step("Click on $tokenName token") { + waitForIdle() + onMarketsTokenDetailsScreen { tokenWithTitle(tokenName).clickWithAssertion() } + } +} \ No newline at end of file diff --git a/app/src/androidTest/kotlin/com/tangem/scenarios/SwapScenarios.kt b/app/src/androidTest/kotlin/com/tangem/scenarios/SwapScenarios.kt new file mode 100644 index 0000000000..a86ca56854 --- /dev/null +++ b/app/src/androidTest/kotlin/com/tangem/scenarios/SwapScenarios.kt @@ -0,0 +1,180 @@ +package com.tangem.scenarios + +import androidx.compose.ui.test.click +import com.tangem.common.BaseTestCase +import com.tangem.common.extensions.clickWithAssertion +import com.tangem.screens.* +import io.github.kakaocup.kakao.common.utilities.getResourceString +import io.qameta.allure.kotlin.Allure.step +import com.tangem.common.ui.R as CommonUiR + +private val firstStoryIndex = 0 +private val firstStoryTitle = getResourceString(CommonUiR.string.swap_story_first_title) +private val firstStorySubtitle = getResourceString(CommonUiR.string.swap_story_first_subtitle) +private val secondStoryIndex = 1 +private val secondStoryTitle = getResourceString(CommonUiR.string.swap_story_second_title) +private val secondStorySubtitle = getResourceString(CommonUiR.string.swap_story_second_subtitle) +private val thirdStoryIndex = 2 +private val thirdStoryTitle = getResourceString(CommonUiR.string.swap_story_third_title) +private val thirdStorySubtitle = getResourceString(CommonUiR.string.swap_story_third_subtitle) +private val forthStoryIndex = 3 +private val forthStoryTitle = getResourceString(CommonUiR.string.swap_story_forth_title) +private val forthStorySubtitle = getResourceString(CommonUiR.string.swap_story_forth_subtitle) +private val fifthStoryIndex = 4 +private val fifthStoryTitle = getResourceString(CommonUiR.string.swap_story_fifth_title) +private val fifthStorySubtitle = getResourceString(CommonUiR.string.swap_story_fifth_subtitle) + +fun BaseTestCase.openSwapScreen( + from: SwapEntryPoint, + storiesExist: Boolean = true, +) { + when (from) { + SwapEntryPoint.MainScreen -> step("Click on 'Swap' button on 'Main' screen") { + onMainScreen { swapButton.performClick() } + } + + SwapEntryPoint.TokenDetails -> step("Click on 'Swap' button on 'Token details' screen") { + onTokenDetailsScreen { swapButton().performClick() } + } + + SwapEntryPoint.MarketsTokenDetails -> step("Click on 'Swap' button on 'Markets' token details screen") { + onMarketsTokenDetailsScreen { swapPortfolioQuickActionButton.performClick() } + } + + SwapEntryPoint.TokenActionsBottomSheet -> step("Click on 'Swap' button on token actions bottom sheet") { + onTokenActionsBottomSheet { swapButton.performClick() } + } + } + + if (storiesExist) { + step("Close 'Stories' screen") { + onSwapStoriesScreen { closeButton.clickWithAssertion() } + } + } else { + step("Assert 'Stories' screen is not displayed") { + onSwapStoriesScreen { container.assertDoesNotExist() } + } + } + + step("Assert 'Swap' screen title is displayed") { + onSwapTokenScreen { title.assertIsDisplayed() } + } +} + +fun BaseTestCase.checkStoriesContent( + storyIndex: Int, + storyTitle: String, + storySubtitle: String, + ) { + step("Assert 'Close' button is displayed") { + onSwapStoriesScreen { closeButton.assertIsDisplayed() } + } + step("Assert progress bar item №${storyIndex + 1} is displayed") { + onSwapStoriesScreen { progressBarItem(storyIndex).assertIsDisplayed() } + } + step("Assert story title is $storyTitle") { + onSwapStoriesScreen { title.assertTextContains(storyTitle) } + } + step("Assert story subtitle is $storySubtitle") { + onSwapStoriesScreen { subtitle.assertTextContains(storySubtitle) } + } +} + +fun BaseTestCase.checkStoriesChanges() { + step("Check title and subtitle for story №${firstStoryIndex + 1}") { + checkStoriesContent( + storyIndex = firstStoryIndex, + storyTitle = firstStoryTitle, + storySubtitle = firstStorySubtitle + ) + } + step("Click on right side") { + onSwapStoriesScreen { container.performTouchInput { click(centerRight) } } + } + step("Check title and subtitle for story №${secondStoryIndex + 1}") { + checkStoriesContent( + storyIndex = secondStoryIndex, + storyTitle = secondStoryTitle, + storySubtitle = secondStorySubtitle + ) + } + step("Click on right side") { + onSwapStoriesScreen { container.performTouchInput { click(centerRight) } } + } + step("Check title and subtitle for story №${thirdStoryIndex + 1}") { + checkStoriesContent( + storyIndex = thirdStoryIndex, + storyTitle = thirdStoryTitle, + storySubtitle = thirdStorySubtitle + ) + } + step("Click on right side") { + onSwapStoriesScreen { container.performTouchInput { click(centerRight) } } + } + step("Check title and subtitle for story №${forthStoryIndex + 1}") { + checkStoriesContent( + storyIndex = forthStoryIndex, + storyTitle = forthStoryTitle, + storySubtitle = forthStorySubtitle + ) + } + step("Click on right side") { + onSwapStoriesScreen { container.performTouchInput { click(centerRight) } } + } + step("Check title and subtitle for story №${fifthStoryIndex + 1}") { + checkStoriesContent( + storyIndex = fifthStoryIndex, + storyTitle = fifthStoryTitle, + storySubtitle = fifthStorySubtitle + ) + } + step("Click on left side") { + onSwapStoriesScreen { container.performTouchInput { click(centerLeft) } } + } + step("Check title and subtitle for story №${forthStoryIndex + 1}") { + checkStoriesContent( + storyIndex = forthStoryIndex, + storyTitle = forthStoryTitle, + storySubtitle = forthStorySubtitle + ) + } + step("Click on left side") { + onSwapStoriesScreen { container.performTouchInput { click(centerLeft) } } + } + step("Check title and subtitle for story №${thirdStoryIndex + 1}") { + checkStoriesContent( + storyIndex = thirdStoryIndex, + storyTitle = thirdStoryTitle, + storySubtitle = thirdStorySubtitle + ) + } + step("Click on left side") { + onSwapStoriesScreen { container.performTouchInput { click(centerLeft) } } + } + step("Check title and subtitle for story №${secondStoryIndex + 1}") { + checkStoriesContent( + storyIndex = secondStoryIndex, + storyTitle = secondStoryTitle, + storySubtitle = secondStorySubtitle + ) + } + step("Click on left side") { + onSwapStoriesScreen { container.performTouchInput { click(centerLeft) } } + } + step("Check title and subtitle for story №${firstStoryIndex + 1}") { + checkStoriesContent( + storyIndex = firstStoryIndex, + storyTitle = firstStoryTitle, + storySubtitle = firstStorySubtitle + ) + } +} + +sealed class SwapEntryPoint { + object MainScreen : SwapEntryPoint() + object TokenDetails : SwapEntryPoint() + object MarketsTokenDetails : SwapEntryPoint() + object TokenActionsBottomSheet : SwapEntryPoint() +} + + diff --git a/app/src/androidTest/kotlin/com/tangem/screens/SwapStoriesPageObject.kt b/app/src/androidTest/kotlin/com/tangem/screens/SwapStoriesPageObject.kt index e48a981112..f9d696a638 100644 --- a/app/src/androidTest/kotlin/com/tangem/screens/SwapStoriesPageObject.kt +++ b/app/src/androidTest/kotlin/com/tangem/screens/SwapStoriesPageObject.kt @@ -10,10 +10,31 @@ import io.github.kakaocup.compose.node.element.KNode class SwapStoriesPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) : ComposeScreen(semanticsProvider = semanticsProvider) { + val container: KNode = child { + hasTestTag(SwapStoriesScreenTestTags.SCREEN_CONTAINER) + useUnmergedTree = true + } + val closeButton: KNode = child { hasTestTag(SwapStoriesScreenTestTags.CLOSE_BUTTON) useUnmergedTree = true } + + fun progressBarItem(index: Int): KNode = child { + hasTestTag(SwapStoriesScreenTestTags.PROGRESS_BAR_ITEM) + hasPosition(index) + useUnmergedTree = true + } + + val title: KNode = child { + hasTestTag(SwapStoriesScreenTestTags.TITLE) + useUnmergedTree = true + } + + val subtitle: KNode = child { + hasTestTag(SwapStoriesScreenTestTags.SUBTITLE) + useUnmergedTree = true + } } internal fun BaseTestCase.onSwapStoriesScreen(function: SwapStoriesPageObject.() -> Unit) = diff --git a/app/src/androidTest/kotlin/com/tangem/tests/swap/SwapStoriesTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/swap/SwapStoriesTest.kt index ccbca2b78c..2f3f1a81d6 100644 --- a/app/src/androidTest/kotlin/com/tangem/tests/swap/SwapStoriesTest.kt +++ b/app/src/androidTest/kotlin/com/tangem/tests/swap/SwapStoriesTest.kt @@ -1,10 +1,13 @@ package com.tangem.tests.swap +import androidx.compose.ui.test.longClick +import androidx.test.InstrumentationRegistry.getTargetContext import com.tangem.common.BaseTestCase import com.tangem.common.extensions.assertHasBadge -import com.tangem.common.extensions.clickWithAssertion -import com.tangem.scenarios.openMainScreen -import com.tangem.scenarios.synchronizeAddresses +import com.tangem.common.extensions.restartApp +import com.tangem.common.utils.resetWireMockScenarioState +import com.tangem.common.utils.setWireMockScenarioState +import com.tangem.scenarios.* import com.tangem.screens.* import dagger.hilt.android.testing.HiltAndroidTest import io.qameta.allure.kotlin.AllureId @@ -30,14 +33,8 @@ class SwapStoriesTest : BaseTestCase() { step("Assert 'Swap' button has badge") { onMainScreen { swapButton.assertHasBadge() } } - step("Click on 'Swap' button") { - onMainScreen { swapButton.performClick() } - } - step("Close 'Stories' screen") { - onSwapStoriesScreen { closeButton.clickWithAssertion() } - } - step("Assert 'Swap' screen title is displayed") { - onSwapTokenScreen { title.assertIsDisplayed() } + step("Open 'Swap' screen") { + openSwapScreen(from = SwapEntryPoint.MainScreen) } step("Click on 'Close' button") { onSwapTokenScreen { closeButton.performClick() } @@ -68,14 +65,8 @@ class SwapStoriesTest : BaseTestCase() { step("Assert 'Swap' button has badge") { onTokenDetailsScreen { swapButton().assertHasBadge() } } - step("Click on 'Swap' button") { - onTokenDetailsScreen { swapButton().performClick() } - } - step("Close 'Stories' screen") { - onSwapStoriesScreen { closeButton.clickWithAssertion() } - } - step("Assert 'Swap' screen title is displayed") { - onSwapTokenScreen { title.assertIsDisplayed() } + step("Open 'Swap' screen") { + openSwapScreen(from = SwapEntryPoint.TokenDetails) } step("Click on 'Close' button") { onSwapTokenScreen { closeButton.performClick() } @@ -102,33 +93,15 @@ class SwapStoriesTest : BaseTestCase() { step("Synchronize addresses") { synchronizeAddresses() } - step("Open 'Markets' screen") { - onMainScreen { searchThroughMarketPlaceholder.performClick() } - waitForIdle() - } - step("") { - onMarketsScreen { searchThroughMarketPlaceholder.performClick() } - } - step("Click on $tokenName token") { - waitForIdle() - onMarketsScreen { tokenWithTitle(tokenName).clickWithAssertion() } - } - step("Click on $tokenName token") { - waitForIdle() - onMarketsTokenDetailsScreen { tokenWithTitle(tokenName).performClick() } + step("Open 'Markets' token details screen for token '$tokenName'") { + openMarketTokenDetailsScreen(blockchainName = tokenName, tokenName = tokenName) } step("Assert 'Swap' button has badge") { onMarketsTokenDetailsScreen { swapPortfolioQuickActionButton.assertIsDisplayed() } onMarketsTokenDetailsScreen { swapPortfolioQuickActionButton.assertContentDescriptionEquals(badgeShown) } } - step("Click on 'Swap' button") { - onMarketsTokenDetailsScreen { swapPortfolioQuickActionButton.performClick() } - } - step("Close 'Stories' screen") { - onSwapStoriesScreen { closeButton.clickWithAssertion() } - } - step("Assert 'Swap' screen title is displayed") { - onSwapTokenScreen { title.assertIsDisplayed() } + step("Open 'Swap' screen") { + openSwapScreen(from = SwapEntryPoint.MarketsTokenDetails) } step("Click on 'Close' button") { onSwapTokenScreen { closeButton.performClick() } @@ -138,4 +111,327 @@ class SwapStoriesTest : BaseTestCase() { } } } + + @AllureId("5469") + @DisplayName("Check unavailable swap stories on 'Main' screen") + @Test + fun checkUnavailableSwapStoriesOnMainScreen() { + val scenarioName = "stories_first_time_swap" + val scenarioErrorState = "Error" + val packageName = getTargetContext().packageName + + setupHooks( + additionalBeforeAppLaunchSection = { + setWireMockScenarioState(scenarioName = scenarioName, state = scenarioErrorState) + }, + additionalAfterSection = { + resetWireMockScenarioState(scenarioName) + } + ).run { + + step("Open 'Main Screen'") { + openMainScreen() + } + step("Synchronize addresses") { + synchronizeAddresses() + } + step("Assert 'Swap' button has badge") { + onMainScreen { swapButton.assertHasBadge(false) } + } + step("Open 'Swap' screen") { + openSwapScreen(from = SwapEntryPoint.MainScreen, storiesExist = false) + } + step("Reset WireMock scenario state") { + resetWireMockScenarioState(scenarioName) + } + step("Click on 'Close' button") { + onSwapTokenScreen { closeButton.performClick() } + } + step("Restart app") { + restartApp(packageName) + } + step("Assert 'Swap' button is displayed") { + waitForIdle() + onMainScreen { swapButton.assertIsDisplayed() } + } + step("Assert 'Swap' button has badge") { + onMainScreen { swapButton.assertHasBadge() } + } + step("Open 'Swap' screen") { + openSwapScreen(from = SwapEntryPoint.MainScreen, storiesExist = true) + } + } + } + + @AllureId("5471") + @DisplayName("Check unavailable swap stories on 'Token details' screen") + @Test + fun checkUnavailableSwapStoriesOnTokenDetailsScreen() { + val scenarioName = "stories_first_time_swap" + val scenarioErrorState = "Error" + val packageName = getTargetContext().packageName + val tokenName = "Ethereum" + + + setupHooks( + additionalBeforeAppLaunchSection = { + setWireMockScenarioState(scenarioName = scenarioName, state = scenarioErrorState) + }, + additionalAfterSection = { + resetWireMockScenarioState(scenarioName) + } + ).run { + + step("Open 'Main Screen'") { + openMainScreen() + } + step("Synchronize addresses") { + synchronizeAddresses() + } + step("Click on token with name: '$tokenName'") { + onMainScreen { tokenWithTitleAndAddress(tokenName).performClick() } + } + step("Assert 'Swap' button has badge") { + onTokenDetailsScreen { swapButton().assertHasBadge(false) } + } + step("Open 'Swap' screen") { + openSwapScreen(from = SwapEntryPoint.TokenDetails, storiesExist = false) + } + step("Click on 'Close' button") { + onSwapTokenScreen { closeButton.performClick() } + } + step("Reset WireMock scenario state") { + resetWireMockScenarioState(scenarioName) + } + step("Restart app") { + restartApp(packageName) + } + step("Assert 'Swap' button has badge") { + waitForIdle() + onMainScreen { swapButton.assertHasBadge() } + } + step("Open 'Swap' screen") { + openSwapScreen(from = SwapEntryPoint.TokenDetails, storiesExist = true) + } + } + } + + @AllureId("5471") + @DisplayName("Check unavailable swap stories on 'Markets' token details screen") + @Test + fun checkUnavailableSwapStoriesOnMarketsTokenDetailsScreen() { + val scenarioName = "stories_first_time_swap" + val scenarioErrorState = "Error" + val packageName = getTargetContext().packageName + val tokenName = "Ethereum" + val badgeShown = "Badge shown" + val badgeHidden = "Badge hidden" + + setupHooks( + additionalBeforeAppLaunchSection = { + setWireMockScenarioState(scenarioName = scenarioName, state = scenarioErrorState) + }, + additionalAfterSection = { + resetWireMockScenarioState(scenarioName) + } + ).run { + + step("Open 'Main Screen'") { + openMainScreen() + } + step("Synchronize addresses") { + synchronizeAddresses() + } + step("Open 'Markets' token details screen for token '$tokenName'") { + openMarketTokenDetailsScreen(blockchainName = tokenName, tokenName = tokenName) + } + step("Assert 'Swap' button has badge") { + waitForIdle() + onMarketsTokenDetailsScreen { swapPortfolioQuickActionButton.assertIsDisplayed() } + onMarketsTokenDetailsScreen { swapPortfolioQuickActionButton.assertContentDescriptionEquals(badgeHidden) } + } + step("Open 'Swap' screen") { + openSwapScreen(from = SwapEntryPoint.MarketsTokenDetails, storiesExist = false) + } + step("Click on 'Close' button") { + onSwapTokenScreen { closeButton.performClick() } + } + step("Reset WireMock scenario state") { + resetWireMockScenarioState(scenarioName) + } + step("Restart app") { + restartApp(packageName) + } + step("Open 'Markets' token details screen for token '$tokenName'") { + openMarketTokenDetailsScreen(blockchainName = tokenName, tokenName = tokenName) + } + step("Assert 'Swap' button has badge") { + waitForIdle() + onMarketsTokenDetailsScreen { swapPortfolioQuickActionButton.assertIsDisplayed() } + onMarketsTokenDetailsScreen { swapPortfolioQuickActionButton.assertContentDescriptionEquals(badgeShown) } + } + step("Open 'Swap' screen") { + openSwapScreen(from = SwapEntryPoint.MarketsTokenDetails, storiesExist = true) + } + } + } + + @AllureId("5474") + @DisplayName("Check 'Swap' stories on 'Main' screen") + @Test + fun checkSwapStoriesOnMainScreenTest() { + + setupHooks().run { + + step("Open 'Main Screen'") { + openMainScreen() + } + step("Synchronize addresses") { + synchronizeAddresses() + } + step("Click on 'Swap' button on 'Main' screen") { + onMainScreen { swapButton.performClick() } + } + step("Check stories changes") { + checkStoriesChanges() + } + step("Click on 'Close' button") { + onSwapStoriesScreen { closeButton.performClick() } + } + step("Assert 'Swap' screen title is displayed") { + onSwapTokenScreen { title.assertIsDisplayed() } + } + step("Click on 'Close' button") { + onSwapTokenScreen { closeButton.performClick() } + } + step("Open 'Swap' screen without stories") { + openSwapScreen(from = SwapEntryPoint.MainScreen, storiesExist = false) + } + } + } + + @AllureId("5475") + @DisplayName("Check 'Swap' stories on 'Token details' screen") + @Test + fun checkSwapStoriesOnTokenDetailsScreenTest() { + val tokenName = "Ethereum" + + setupHooks().run { + + step("Open 'Main Screen'") { + openMainScreen() + } + step("Synchronize addresses") { + synchronizeAddresses() + } + step("Click on token with name: '$tokenName'") { + onMainScreen { tokenWithTitleAndAddress(tokenName).performClick() } + } + step("Assert 'Swap' button has badge") { + onTokenDetailsScreen { swapButton().assertHasBadge() } + } + step("Click on 'Swap' button on 'Token details' screen") { + onTokenDetailsScreen { swapButton().performClick() } + } + step("Check stories changes") { + checkStoriesChanges() + } + step("Click on 'Close' button") { + onSwapStoriesScreen { closeButton.performClick() } + } + step("Assert 'Swap' screen title is displayed") { + onSwapTokenScreen { title.assertIsDisplayed() } + } + step("Click on 'Close' button") { + onSwapTokenScreen { closeButton.performClick() } + } + step("Open 'Swap' screen without stories") { + openSwapScreen(from = SwapEntryPoint.TokenDetails, storiesExist = false) + } + } + } + + @AllureId("5476") + @DisplayName("Check 'Swap' stories on 'Markets' screen") + @Test + fun checkSwapStoriesOnMarketTokenDetailsScreenTest() { + val tokenName = "Ethereum" + + setupHooks().run { + + step("Open 'Main Screen'") { + openMainScreen() + } + step("Synchronize addresses") { + synchronizeAddresses() + } + step("Open 'Markets' token details screen for token '$tokenName'") { + openMarketTokenDetailsScreen(blockchainName = tokenName, tokenName = tokenName) + } + step("Click on 'Swap' button on 'Markets' token details screen") { + onMarketsTokenDetailsScreen { swapPortfolioQuickActionButton.performClick() } + } + step("Check stories changes") { + checkStoriesChanges() + } + step("Click on 'Close' button") { + onSwapStoriesScreen { closeButton.performClick() } + } + step("Assert 'Swap' screen title is displayed") { + onSwapTokenScreen { title.assertIsDisplayed() } + } + step("Click on 'Close' button") { + onSwapTokenScreen { closeButton.performClick() } + } + step("Open 'Swap' screen without stories") { + openSwapScreen(from = SwapEntryPoint.MarketsTokenDetails, storiesExist = false) + } + } + } + + @AllureId("5477") + @DisplayName("Check 'Swap' stories on token actions bottom sheet") + @Test + fun checkSwapStoriesOnTokenActionsBottomSheetTest() { + val tokenName = "Ethereum" + + setupHooks().run { + + step("Open 'Main Screen'") { + openMainScreen() + } + step("Synchronize addresses") { + synchronizeAddresses() + } + step("Long click on token with name: '$tokenName'") { + waitForIdle() + onMainScreen { + tokenWithTitleAndAddress(tokenName).performTouchInput { + longClick( + position = center, + durationMillis = 1000L + ) + } + } + } + step("Click on 'Swap' button") { + onTokenActionsBottomSheet { swapButton.performClick() } + } + step("Check stories changes") { + checkStoriesChanges() + } + step("Click on 'Close' button") { + onSwapStoriesScreen { closeButton.performClick() } + } + step("Assert 'Swap' screen title is displayed") { + onSwapTokenScreen { title.assertIsDisplayed() } + } + step("Click on 'Close' button") { + onSwapTokenScreen { closeButton.performClick() } + } + step("Open 'Swap' screen without stories") { + openSwapScreen(from = SwapEntryPoint.TokenActionsBottomSheet, storiesExist = false) + } + } + } } \ No newline at end of file diff --git a/common/ui/src/main/java/com/tangem/common/ui/swapStoriesScreen/SwapStoriesScreen.kt b/common/ui/src/main/java/com/tangem/common/ui/swapStoriesScreen/SwapStoriesScreen.kt index dede83288b..cd75f1b70f 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/swapStoriesScreen/SwapStoriesScreen.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/swapStoriesScreen/SwapStoriesScreen.kt @@ -94,6 +94,7 @@ private fun SwapStoriesText(current: SwapStoriesUM.Content.Config) { ), color = TangemTheme.colors.text.constantWhite, textAlign = TextAlign.Center, + modifier = Modifier.testTag(SwapStoriesScreenTestTags.TITLE), ) Text( text = current.subtitle.resolveReference(), @@ -105,6 +106,7 @@ private fun SwapStoriesText(current: SwapStoriesUM.Content.Config) { ), color = SubtitleColor, textAlign = TextAlign.Center, + modifier = Modifier.testTag(SwapStoriesScreenTestTags.SUBTITLE), ) } } diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/stories/inner/StoriesProgressBar.kt b/core/ui/src/main/java/com/tangem/core/ui/components/stories/inner/StoriesProgressBar.kt index 05d61b51f0..00592f5bf2 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/stories/inner/StoriesProgressBar.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/stories/inner/StoriesProgressBar.kt @@ -8,16 +8,20 @@ import androidx.compose.animation.core.tween import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.testTag import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.tangem.core.ui.components.SpacerW4 import com.tangem.core.ui.res.TangemColorPalette import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.test.SwapStoriesScreenTestTags import kotlinx.coroutines.delay private const val STORIES_ANIMATION_SPEED_ZERO_DURATION = 3000L @@ -99,6 +103,7 @@ fun StoriesProgressBar( .clip(RoundedCornerShape(2.dp)) .background(TangemColorPalette.White) .fillMaxHeight() + .testTag(SwapStoriesScreenTestTags.PROGRESS_BAR_ITEM) .let { modifier -> when (index) { currentStep -> modifier.fillMaxWidth(progress.value) diff --git a/core/ui/src/main/java/com/tangem/core/ui/test/SwapStoriesScreenTestTags.kt b/core/ui/src/main/java/com/tangem/core/ui/test/SwapStoriesScreenTestTags.kt index 40a0ffe621..b61b3e88c4 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/test/SwapStoriesScreenTestTags.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/test/SwapStoriesScreenTestTags.kt @@ -3,4 +3,7 @@ package com.tangem.core.ui.test object SwapStoriesScreenTestTags { const val SCREEN_CONTAINER = "SWAP_STORIES_SCREEN_CONTAINER" const val CLOSE_BUTTON = "SWAP_STORIES_SCREEN_CLOSE_BUTTON" + const val PROGRESS_BAR_ITEM = "SWAP_STORIES_SCREEN_PROGRESS_BAR_ITEM" + const val TITLE = "SWAP_STORIES_SCREEN_TITLE" + const val SUBTITLE = "SWAP_STORIES_SCREEN_SUBTITLE" } \ No newline at end of file