Updated on 2026-08-14
This commit is contained in:
parent
23ddf1a665
commit
8632680f20
13 changed files with 140 additions and 124 deletions
|
|
@ -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<String, Boolean>
|
||||
) : TestRule {
|
||||
|
||||
private val tangemApplication: TangemApplication
|
||||
get() = ApplicationProvider.getApplicationContext()
|
||||
|
||||
private var originalFeatureTogglesValues: Map<String, String>? = 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<String, String>
|
||||
} 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<String, String>)
|
||||
|
||||
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}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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") {
|
||||
|
|
|
|||
|
|
@ -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<CreateWalletStartPageObject>(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)
|
||||
|
|
@ -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) =
|
||||
|
|
|
|||
|
|
@ -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<StoriesPageObject>(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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue