diff --git a/app/src/androidTest/kotlin/com/tangem/common/ApplicationInjectionExecutionRule.kt b/app/src/androidTest/kotlin/com/tangem/common/ApplicationInjectionExecutionRule.kt index 75662e25d4..2445305b72 100644 --- a/app/src/androidTest/kotlin/com/tangem/common/ApplicationInjectionExecutionRule.kt +++ b/app/src/androidTest/kotlin/com/tangem/common/ApplicationInjectionExecutionRule.kt @@ -7,23 +7,91 @@ import dagger.hilt.android.testing.OnComponentReadyRunner import org.junit.rules.TestRule import org.junit.runner.Description import org.junit.runners.model.Statement +import timber.log.Timber -class ApplicationInjectionExecutionRule : TestRule { +class ApplicationInjectionExecutionRule( + private val toggleStates: Map +) : TestRule { private val tangemApplication: TangemApplication get() = ApplicationProvider.getApplicationContext() + private var originalFeatureTogglesValues: Map? = null + override fun apply(base: Statement, description: Description): Statement { return object : Statement() { override fun evaluate() { + saveOriginalFeatureToggles() + overrideFeatureToggles() + OnComponentReadyRunner.addListener( tangemApplication, ApplicationEntryPoint::class.java ) { _: ApplicationEntryPoint -> tangemApplication.preInit() tangemApplication.init() } - base.evaluate() + + try { + base.evaluate() + } finally { + restoreOriginalFeatureToggles() + } } } } + + @Suppress("UNCHECKED_CAST") + private fun saveOriginalFeatureToggles() { + try { + val featureTogglesClass = Class.forName("com.tangem.core.configtoggle.FeatureToggles") + val valuesField = featureTogglesClass.getDeclaredField("values") + valuesField.isAccessible = true + originalFeatureTogglesValues = valuesField.get(null) as Map + } catch (e: Exception) { + Timber.e("Failed to save original toggles values: ${e.message}") + } + } + + @Suppress("UNCHECKED_CAST") + private fun overrideFeatureToggles() { + try { + val featureTogglesClass = Class.forName("com.tangem.core.configtoggle.FeatureToggles") + val valuesField = featureTogglesClass.getDeclaredField("values") + valuesField.isAccessible = true + + val originalValues = originalFeatureTogglesValues ?: + (valuesField.get(null) as Map) + + val newValues = originalValues.toMutableMap() + + toggleStates.forEach { (toggle, enabled) -> + if (enabled) { + newValues[toggle] = "1.0.0" + } else { + newValues.remove(toggle) + } + } + + valuesField.set(null, newValues) + + Timber.i("FeatureToggles.values updated: $toggleStates") + + } catch (e: Exception) { + Timber.e("FeatureToggles.values didn't change with error: ${e.message}") + } + } + + private fun restoreOriginalFeatureToggles() { + try { + if (originalFeatureTogglesValues != null) { + val featureTogglesClass = Class.forName("com.tangem.core.configtoggle.FeatureToggles") + val valuesField = featureTogglesClass.getDeclaredField("values") + valuesField.isAccessible = true + valuesField.set(null, originalFeatureTogglesValues) + Timber.i("FeatureToggles.values restored") + } + } catch (e: Exception) { + Timber.e("FeatureToggles.values didn't restored with error: ${e.message}") + } + } } \ No newline at end of file diff --git a/app/src/androidTest/kotlin/com/tangem/common/BaseTestCase.kt b/app/src/androidTest/kotlin/com/tangem/common/BaseTestCase.kt index 57a2c29563..8a40e56185 100644 --- a/app/src/androidTest/kotlin/com/tangem/common/BaseTestCase.kt +++ b/app/src/androidTest/kotlin/com/tangem/common/BaseTestCase.kt @@ -16,8 +16,6 @@ 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.rules.ApiEnvironmentRule -import com.tangem.core.configtoggle.feature.FeatureTogglesManager -import com.tangem.core.configtoggle.feature.MutableFeatureTogglesManager import com.tangem.datasource.api.common.config.managers.ApiConfigsManager import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.preferences.PreferencesKeys @@ -53,9 +51,6 @@ abstract class BaseTestCase : TestCase( @Inject lateinit var appPreferencesStore: AppPreferencesStore - @Inject - lateinit var featureTogglesManager: FeatureTogglesManager - @Inject lateinit var promoRepository: PromoRepository @@ -75,7 +70,7 @@ abstract class BaseTestCase : TestCase( @JvmField val ruleChain: TestRule = RuleChain .outerRule(hiltRule) - .around(ApplicationInjectionExecutionRule()) + .around(applicationInjectionRule()) .around(permissionRule) .around(apiEnvironmentRule) .around(composeTestRule) @@ -110,7 +105,6 @@ abstract class BaseTestCase : TestCase( apiEnvironmentRule.setup(apiConfigsManager) ActivityScenario.launch(MainActivity::class.java) Intents.init() - setFeatureToggles() additionalBeforeSection() }.after { additionalAfterSection() @@ -141,14 +135,15 @@ abstract class BaseTestCase : TestCase( fun waitForIdle() = composeTestRule.waitForIdle() - private fun setFeatureToggles() { - runBlocking { - with(featureTogglesManager as MutableFeatureTogglesManager) { - changeToggle("NEW_TOKEN_RECEIVE_ENABLED", true) - changeToggle("WALLET_BALANCE_FETCHER_ENABLED", true) - changeToggle("SWAP_REDESIGN_ENABLED", true) - changeToggle("NEW_ONRAMP_MAIN_ENABLED", true) - } - } + private fun applicationInjectionRule(): ApplicationInjectionExecutionRule { + return ApplicationInjectionExecutionRule( + toggleStates = mapOf( + "NEW_TOKEN_RECEIVE_ENABLED" to true, + "WALLET_BALANCE_FETCHER_ENABLED" to true, + "SWAP_REDESIGN_ENABLED" to true, + "NEW_ONRAMP_MAIN_ENABLED" to true, + "HOT_WALLET_ENABLED" to true + ) + ) } } \ No newline at end of file diff --git a/app/src/androidTest/kotlin/com/tangem/scenarios/BaseScenarios.kt b/app/src/androidTest/kotlin/com/tangem/scenarios/BaseScenarios.kt index 1761e307c2..e84ee3a24c 100644 --- a/app/src/androidTest/kotlin/com/tangem/scenarios/BaseScenarios.kt +++ b/app/src/androidTest/kotlin/com/tangem/scenarios/BaseScenarios.kt @@ -26,8 +26,11 @@ fun BaseTestCase.scanCard( step("Click on 'Accept' button") { onDisclaimerScreen { acceptButton.clickWithAssertion() } } - step("Click on 'Scan' button") { - onStoriesScreen { scanButton.clickWithAssertion() } + step("Click on 'Get started' button") { + onStoriesScreen { getStartedButton.clickWithAssertion() } + } + step("Click on 'Scan card or ring' button") { + onCreateWalletStartScreen { scanCardOrRingButton.clickWithAssertion() } } if (alreadyActivatedDialogIsShown) { step("Click on 'This is my wallet' button") { diff --git a/app/src/androidTest/kotlin/com/tangem/screens/CreateWalletStartPageObject.kt b/app/src/androidTest/kotlin/com/tangem/screens/CreateWalletStartPageObject.kt new file mode 100644 index 0000000000..b06335d752 --- /dev/null +++ b/app/src/androidTest/kotlin/com/tangem/screens/CreateWalletStartPageObject.kt @@ -0,0 +1,23 @@ +package com.tangem.screens + +import androidx.compose.ui.test.SemanticsNodeInteractionsProvider +import com.tangem.common.BaseTestCase +import com.tangem.core.ui.test.BaseButtonTestTags +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 +import com.tangem.features.onboarding.v2.impl.R as OnboardingImplR + +class CreateWalletStartPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) : + ComposeScreen(semanticsProvider = semanticsProvider) { + + val scanCardOrRingButton: KNode = child { + hasTestTag(BaseButtonTestTags.TEXT) + hasText(getResourceString(OnboardingImplR.string.welcome_unlock_card)) + useUnmergedTree = true + } +} + +internal fun BaseTestCase.onCreateWalletStartScreen(function: CreateWalletStartPageObject.() -> Unit) = + onComposeScreen(composeTestRule, function) \ No newline at end of file diff --git a/app/src/androidTest/kotlin/com/tangem/screens/DetailsPageObject.kt b/app/src/androidTest/kotlin/com/tangem/screens/DetailsPageObject.kt index 62b73d6c4b..49cc06a3ad 100644 --- a/app/src/androidTest/kotlin/com/tangem/screens/DetailsPageObject.kt +++ b/app/src/androidTest/kotlin/com/tangem/screens/DetailsPageObject.kt @@ -42,6 +42,7 @@ class DetailsPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) : hasTestTag(DetailsScreenTestTags.SCREEN_ITEM) hasText(getResourceString(R.string.app_settings_title)) } + val contactSupportButton: KNode = child { hasTestTag(DetailsScreenTestTags.SCREEN_ITEM) hasText(getResourceString(R.string.details_row_title_contact_to_support)) @@ -50,6 +51,11 @@ class DetailsPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) : hasTestTag(DetailsScreenTestTags.SCREEN_ITEM) hasText(getResourceString(R.string.disclaimer_title)) } + + val versionName: KNode = child { + hasTestTag(DetailsScreenTestTags.VERSION_NAME) + useUnmergedTree = true + } } internal fun BaseTestCase.onDetailsScreen(function: DetailsPageObject.() -> Unit) = diff --git a/app/src/androidTest/kotlin/com/tangem/screens/StoriesPageObject.kt b/app/src/androidTest/kotlin/com/tangem/screens/StoriesPageObject.kt index f9666ceeb4..faf2492a94 100644 --- a/app/src/androidTest/kotlin/com/tangem/screens/StoriesPageObject.kt +++ b/app/src/androidTest/kotlin/com/tangem/screens/StoriesPageObject.kt @@ -2,20 +2,20 @@ package com.tangem.screens import androidx.compose.ui.test.SemanticsNodeInteractionsProvider import com.tangem.common.BaseTestCase -import com.tangem.core.ui.test.StoriesScreenTestTags +import com.tangem.core.ui.test.BaseButtonTestTags +import com.tangem.features.onboarding.v2.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.kakao.common.utilities.getResourceString class StoriesPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) : ComposeScreen(semanticsProvider = semanticsProvider) { - val scanButton: KNode = child { - hasTestTag(StoriesScreenTestTags.SCAN_BUTTON) - } - - val orderButton: KNode = child { - hasTestTag(StoriesScreenTestTags.ORDER_BUTTON) + val getStartedButton: KNode = child { + hasTestTag(BaseButtonTestTags.TEXT) + hasText(getResourceString(R.string.common_get_started)) + useUnmergedTree = true } } diff --git a/app/src/androidTest/kotlin/com/tangem/tests/DetailsTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/DetailsTest.kt index 49fe556eba..c084d381c8 100644 --- a/app/src/androidTest/kotlin/com/tangem/tests/DetailsTest.kt +++ b/app/src/androidTest/kotlin/com/tangem/tests/DetailsTest.kt @@ -4,10 +4,7 @@ import com.tangem.common.BaseTestCase import com.tangem.common.extensions.clickWithAssertion import com.tangem.domain.models.scan.ProductType import com.tangem.scenarios.openMainScreen -import com.tangem.screens.onDetailsScreen -import com.tangem.screens.onReferralProgramScreen -import com.tangem.screens.onTopBar -import com.tangem.screens.onWalletSettingsScreen +import com.tangem.screens.* import dagger.hilt.android.testing.HiltAndroidTest import io.qameta.allure.kotlin.AllureId import io.qameta.allure.kotlin.junit4.DisplayName @@ -31,9 +28,6 @@ class DetailsTest : BaseTestCase() { step("Assert 'Wallet connect' button is visible") { walletConnectButton.assertIsDisplayed() } - step("Assert 'Scan card' button is visible") { - scanCardButton.assertIsDisplayed() - } step("Assert 'Buy Tangem card' button is visible") { buyTangemButton.assertIsDisplayed() } @@ -131,9 +125,6 @@ class DetailsTest : BaseTestCase() { step("Assert 'Wallet connect' button does not exist") { walletConnectButton.assertIsNotDisplayed() } - step("Assert 'Scan card' button is visible") { - scanCardButton.assertIsDisplayed() - } step("Assert 'Buy Tangem card' button is visible") { buyTangemButton.assertIsDisplayed() } diff --git a/app/src/androidTest/kotlin/com/tangem/tests/FeedbackTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/FeedbackTest.kt index 9d75140152..0a20f32754 100644 --- a/app/src/androidTest/kotlin/com/tangem/tests/FeedbackTest.kt +++ b/app/src/androidTest/kotlin/com/tangem/tests/FeedbackTest.kt @@ -139,8 +139,11 @@ class FeedbackTest : BaseTestCase() { step("Set scanning error") { MockProvider.setEmulateError(TangemSdkError.TagLost()) } - step("Click on 'Scan' button") { - onStoriesScreen { scanButton.performClick() } + step("Click on 'Get started' button") { + onStoriesScreen { getStartedButton.clickWithAssertion() } + } + step("Click on 'Scan card or ring' button") { + onCreateWalletStartScreen { scanCardOrRingButton.clickWithAssertion() } } step("Force show 'Scan warning' dialog"){ runOnUiThread { @@ -178,8 +181,11 @@ class FeedbackTest : BaseTestCase() { step("Click on 'Accept' button") { onDisclaimerScreen { acceptButton.clickWithAssertion() } } - step("Click on 'Scan' button") { - onStoriesScreen { scanButton.clickWithAssertion() } + step("Click on 'Get started' button") { + onStoriesScreen { getStartedButton.clickWithAssertion() } + } + step("Click on 'Scan card or ring' button") { + onCreateWalletStartScreen { scanCardOrRingButton.clickWithAssertion() } } step("Check 'Already used Wallet' dialog") { checkAlreadyUsedWalletDialog() diff --git a/app/src/androidTest/kotlin/com/tangem/tests/ScanErrorTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/ScanErrorTest.kt deleted file mode 100644 index c31340f9dd..0000000000 --- a/app/src/androidTest/kotlin/com/tangem/tests/ScanErrorTest.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.tangem.tests - -import com.tangem.common.BaseTestCase -import com.tangem.common.extensions.clickWithAssertion -import com.tangem.screens.onDisclaimerScreen -import com.tangem.screens.onMainScreen -import com.tangem.screens.onStoriesScreen -import com.tangem.tap.domain.sdk.mocks.MockProvider -import dagger.hilt.android.testing.HiltAndroidTest -import org.junit.Test - -@HiltAndroidTest -class ScanErrorTest : BaseTestCase() { - - @Test - fun goToMainTest() = - setupHooks().run { - onDisclaimerScreen { - step("Click on 'Accept' button") { - acceptButton.clickWithAssertion() - } - } - onStoriesScreen { - step("Click on 'Scan' button emulating scan error") { - MockProvider.setEmulateError() - scanButton.clickWithAssertion() - } - step("Click on 'Scan' button again without emulating error") { - MockProvider.resetEmulateError() - scanButton.clickWithAssertion() - } - } - onMainScreen { - step("Make sure wallet screen is visible") { - assertIsDisplayed() - } - } - } -} \ No newline at end of file diff --git a/app/src/androidTest/kotlin/com/tangem/tests/StoriesTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/StoriesTest.kt deleted file mode 100644 index d87e1be98c..0000000000 --- a/app/src/androidTest/kotlin/com/tangem/tests/StoriesTest.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.tangem.tests - -import android.content.Intent.ACTION_VIEW -import com.tangem.common.BaseTestCase -import com.tangem.common.extensions.clickWithAssertion -import com.tangem.screens.onDisclaimerScreen -import com.tangem.screens.onStoriesScreen -import dagger.hilt.android.testing.HiltAndroidTest -import io.github.kakaocup.kakao.intent.KIntent - -@HiltAndroidTest -class StoriesTest : BaseTestCase() { - - // @Test - fun clickOnOrderButtonTest() = - setupHooks().run { - val buyWalletUrl = "https://buy.tangem.com/" - onDisclaimerScreen { - step("Click on 'Accept' button") { - acceptButton.clickWithAssertion() - } - } - onStoriesScreen { - step("Click on 'Order' button") { - orderButton.clickWithAssertion() - } - step("Assert: browser opened") { - val expectedIntent = KIntent { - hasAction(ACTION_VIEW) - hasData { toString().startsWith(buyWalletUrl) } - } - expectedIntent.intended() - device.uiDevice.pressBack() - } - } - } -} \ 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 3b956d2bea..046964ff53 100644 --- a/app/src/androidTest/kotlin/com/tangem/tests/TermsOfServiceTest.kt +++ b/app/src/androidTest/kotlin/com/tangem/tests/TermsOfServiceTest.kt @@ -37,8 +37,7 @@ class TermsOfServiceTest : BaseTestCase() { } step("Assert 'Stories' screen is opened") { onStoriesScreen { - scanButton.assertIsDisplayed() - orderButton.assertIsDisplayed() + getStartedButton.assertIsDisplayed() } } } @@ -91,8 +90,7 @@ class TermsOfServiceTest : BaseTestCase() { } step("Assert 'Stories' screen is opened") { onStoriesScreen { - scanButton.assertIsDisplayed() - orderButton.assertIsDisplayed() + getStartedButton.assertIsDisplayed() } } step("Stop app") { @@ -103,8 +101,7 @@ class TermsOfServiceTest : BaseTestCase() { } step("Assert 'Stories' screen is opened") { onStoriesScreen { - scanButton.assertIsDisplayed() - orderButton.assertIsDisplayed() + getStartedButton.assertIsDisplayed() } } } diff --git a/core/ui/src/main/java/com/tangem/core/ui/test/DetailsScreenTestTags.kt b/core/ui/src/main/java/com/tangem/core/ui/test/DetailsScreenTestTags.kt index 33f7b56ef3..bbbeb91dd5 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/test/DetailsScreenTestTags.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/test/DetailsScreenTestTags.kt @@ -3,4 +3,5 @@ package com.tangem.core.ui.test object DetailsScreenTestTags { const val SCREEN_CONTAINER = "DETAILS_SCREEN_CONTAINER" const val SCREEN_ITEM = "DETAILS_SCREEN_ITEM" + const val VERSION_NAME = "DETAILS_SCREEN_VERSION_NAME" } \ No newline at end of file diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/ui/DetailsScreen.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/ui/DetailsScreen.kt index 0bd950c5c8..6be90f525b 100644 --- a/features/details/impl/src/main/kotlin/com/tangem/features/details/ui/DetailsScreen.kt +++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/ui/DetailsScreen.kt @@ -185,7 +185,9 @@ private fun Footer(model: DetailsFooterUM, modifier: Modifier = Modifier) { } Text( - modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing6), + modifier = Modifier + .padding(horizontal = TangemTheme.dimens.spacing6) + .testTag(DetailsScreenTestTags.VERSION_NAME), text = model.appVersion, style = TangemTheme.typography.caption2, color = TangemTheme.colors.text.tertiary,