tangem-app-android-audited/app/src/androidTest/kotlin/com/tangem/common/BaseTestCase.kt
2026-02-02 16:12:25 +07:00

158 lines
No EOL
6.1 KiB
Kotlin
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.tangem.common
import android.Manifest
import androidx.compose.ui.test.isRoot
import androidx.compose.ui.test.junit4.createEmptyComposeRule
import androidx.compose.ui.test.printToLog
import androidx.test.core.app.ActivityScenario
import androidx.test.espresso.intent.Intents
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.GrantPermissionRule
import com.kaspersky.components.alluresupport.interceptors.step.ScreenshotStepInterceptor
import com.kaspersky.components.alluresupport.withForcedAllureSupport
import com.kaspersky.components.composesupport.config.addComposeSupport
import com.kaspersky.kaspresso.kaspresso.Kaspresso
import com.kaspersky.kaspresso.testcases.api.testcase.TestCase
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.datasource.api.common.config.managers.ApiConfigsManager
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys
import com.tangem.datasource.utils.WireMockRedirectInterceptor
import com.tangem.domain.promo.PromoRepository
import com.tangem.domain.promo.models.PromoId
import com.tangem.tap.MainActivity
import dagger.hilt.android.testing.HiltAndroidRule
import io.qameta.allure.kotlin.Allure
import kotlinx.coroutines.runBlocking
import org.junit.Rule
import org.junit.rules.RuleChain
import org.junit.rules.TestRule
import javax.inject.Inject
abstract class BaseTestCase : TestCase(
kaspressoBuilder = Kaspresso.Builder.withForcedAllureSupport(
shouldRecordVideo = false
).apply {
stepWatcherInterceptors = stepWatcherInterceptors.filter {
it !is ScreenshotStepInterceptor
}.toMutableList()
stepWatcherInterceptors.addAll(
listOf(
FailedStepScreenshotInterceptor(screenshots)
)
)
}.addComposeSupport()
) {
@Inject
lateinit var apiConfigsManager: ApiConfigsManager
@Inject
lateinit var appPreferencesStore: AppPreferencesStore
@Inject
lateinit var promoRepository: PromoRepository
private val hiltRule = HiltAndroidRule(this)
private val apiEnvironmentRule = ApiEnvironmentRule()
private val permissionRule = GrantPermissionRule.grant(
Manifest.permission.POST_NOTIFICATIONS,
)
/**
* It is important to use `ComposeRule` without specifying an activity to ensure that the initialization order of
* all test rules is fully controlled.
*/
val composeTestRule = createEmptyComposeRule()
@Rule
@JvmField
val ruleChain: TestRule = RuleChain
.outerRule(hiltRule)
.around(applicationInjectionRule())
.around(permissionRule)
.around(apiEnvironmentRule)
.around(composeTestRule)
/**
* Initialization order is important:
* DI dependencies must be injected first,
* then the API environment should be set up,
* and only after that the activity should be launched.
*/
protected fun setupHooks(
additionalBeforeSection: () -> Unit = {},
additionalAfterSection: () -> Unit = {},
) = before {
Allure.label(ALLURE_LABEL_NAME, ALLURE_LABEL_VALUE)
// Setup WireMock redirect for CI with local WireMock instances
val wiremockUrl = InstrumentationRegistry.getArguments().getString(WIREMOCK_BASE_URL_ARG)
WireMockRedirectInterceptor.overriddenBaseUrl = wiremockUrl
hiltRule.inject()
runBlocking {
appPreferencesStore.editData { mutablePreferences ->
mutablePreferences.set(
key = PreferencesKeys.NOTIFICATIONS_USER_ALLOW_SEND_ADDRESSES_KEY,
value = false
)
}
appPreferencesStore.editData { mutablePreferences ->
mutablePreferences.set(
key = PreferencesKeys.getShouldShowNotificationKey("EnablePushesReminderNotification"),
value = false
)
}
promoRepository.setNeverToShowWalletPromo(PromoId.Sepa)
}
apiEnvironmentRule.setup(apiConfigsManager)
ActivityScenario.launch(MainActivity::class.java)
Intents.init()
additionalBeforeSection()
}.after {
additionalAfterSection()
Intents.release()
}
/**
* Prints the Compose semantics tree to logcat for debugging UI tests.
*
* @param rootIndex Use rootIndex > 0, if you need to print semantics tree for bottom sheet.
* Default: 0.
* @param useUnmergedTree When true, shows unmerged tree with all individual nodes.
* Use for accessing inner elements of compound components.
* Default: false (merged tree - accessibility view).
* @param tag Log tag for filtering in logcat. Default: "SEMANTIC_TREE".
* @param maxDepth Maximum nesting level to print. Use to avoid log overflow.
* Default: Int.MAX_VALUE (unlimited depth).
*/
fun printSemanticTree(
rootIndex: Int = 0,
useUnmergedTree: Boolean = false,
tag: String = "SEMANTIC_TREE",
maxDepth: Int = Int.MAX_VALUE
) {
composeTestRule.onAllNodes(isRoot(), useUnmergedTree = useUnmergedTree)[rootIndex]
.printToLog(tag, maxDepth)
}
fun waitForIdle() = composeTestRule.waitForIdle()
private fun applicationInjectionRule(): ApplicationInjectionExecutionRule {
return ApplicationInjectionExecutionRule(
toggleStates = mapOf(
"SWAP_REDESIGN_ENABLED" to false,
"NEW_ONRAMP_MAIN_ENABLED" to true,
"HOT_WALLET_ENABLED" to true,
"YIELD_SUPPLY_FEATURE_ENABLED" to true,
"ACCOUNTS_FEATURE_ENABLED" to true
)
)
}
private companion object {
const val WIREMOCK_BASE_URL_ARG = "wiremockBaseUrl"
}
}