Updated on 2026-08-14

This commit is contained in:
Tangem 2024-04-12 08:59:52 +02:00
parent 625277f518
commit d32b504a80
28 changed files with 400 additions and 155 deletions

View file

@ -0,0 +1,28 @@
package com.tangem.common
import androidx.test.core.app.ApplicationProvider
import com.tangem.tap.ApplicationEntryPoint
import com.tangem.tap.TangemApplication
import dagger.hilt.android.testing.OnComponentReadyRunner
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
class ApplicationInjectionExecutionRule : TestRule {
private val tangemApplication: TangemApplication
get() = ApplicationProvider.getApplicationContext()
override fun apply(base: Statement, description: Description): Statement {
return object : Statement() {
override fun evaluate() {
OnComponentReadyRunner.addListener(
tangemApplication, ApplicationEntryPoint::class.java
) { _: ApplicationEntryPoint ->
tangemApplication.init()
}
base.evaluate()
}
}
}
}

View file

@ -0,0 +1,56 @@
package com.tangem.common
import android.Manifest
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.test.espresso.intent.Intents
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.rule.GrantPermissionRule
import com.kaspersky.components.composesupport.config.withComposeSupport
import com.kaspersky.kaspresso.kaspresso.Kaspresso
import com.kaspersky.kaspresso.testcases.api.testcase.TestCase
import com.tangem.tap.MainActivity
import com.tangem.tap.domain.sdk.TangemSdkManager
import dagger.hilt.android.testing.HiltAndroidRule
import org.junit.Rule
import org.junit.rules.RuleChain
import org.junit.runner.RunWith
import javax.inject.Inject
@RunWith(AndroidJUnit4::class)
abstract class BaseTestCase : TestCase(
kaspressoBuilder = Kaspresso.Builder.withComposeSupport()
) {
@Inject
lateinit var tangemSdkManager: TangemSdkManager
@get:Rule
open val composeTestRule = createAndroidComposeRule<MainActivity>()
@get:Rule
val grantPermissionRule: GrantPermissionRule = GrantPermissionRule.grant(
Manifest.permission.POST_NOTIFICATIONS,
Manifest.permission.CAMERA
)
private val hiltRule = HiltAndroidRule(this)
@Rule
@JvmField
val ruleChain = RuleChain
.outerRule(hiltRule)
.around(ApplicationInjectionExecutionRule())
protected fun setupHooks(
additionalBeforeSection: () -> Unit = {},
additionalAfterSection: () -> Unit = {},
) = before {
hiltRule.inject()
Intents.init()
additionalBeforeSection()
}.after {
additionalAfterSection()
Intents.release()
}
}

View file

@ -0,0 +1,17 @@
package com.tangem.common
import android.app.Application
import android.content.Context
import androidx.test.runner.AndroidJUnitRunner
import com.tangem.common.di.TangemMockedApplication_Application
class HiltTestRunner : AndroidJUnitRunner() {
override fun newApplication(
cl: ClassLoader?,
className: String?,
context: Context?
): Application {
return super.newApplication(cl, TangemMockedApplication_Application::class.java.name, context)
}
}

View file

@ -0,0 +1,11 @@
package com.tangem.common
import com.tangem.tap.TangemApplication
open class TangemEmptyApplication : TangemApplication() {
override fun onCreate() {
// super.onCreate() is not called intentionally
}
}

View file

@ -0,0 +1,7 @@
package com.tangem.common.di
import com.tangem.common.TangemEmptyApplication
import dagger.hilt.android.testing.CustomTestApplication
@CustomTestApplication(TangemEmptyApplication::class)
internal class TangemMockedApplication

View file

@ -0,0 +1,28 @@
package com.tangem.common.di
import android.content.Context
import com.tangem.tap.di.TangemSdkManagerModule
import com.tangem.tap.domain.sdk.impl.MockTangemSdkManager
import com.tangem.tap.domain.sdk.TangemSdkManager
import dagger.Module
import dagger.Provides
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import dagger.hilt.testing.TestInstallIn
import javax.inject.Singleton
@Module
@TestInstallIn(
components = [SingletonComponent::class],
replaces = [TangemSdkManagerModule::class]
)
object TestModule {
@Provides
@Singleton
fun provideTangemSdkManager(
@ApplicationContext context: Context
): TangemSdkManager {
return MockTangemSdkManager(resources = context.resources)
}
}

View file

@ -1,27 +0,0 @@
package com.tangem.helpers.base
import android.Manifest
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.rule.GrantPermissionRule
import com.kaspersky.components.composesupport.config.withComposeSupport
import com.kaspersky.kaspresso.kaspresso.Kaspresso
import com.kaspersky.kaspresso.testcases.api.testcase.TestCase
import com.tangem.tap.MainActivity
import org.junit.Rule
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
open class BaseAutoTestCase : TestCase(
kaspressoBuilder = Kaspresso.Builder.withComposeSupport()
) {
@get:Rule
open val composeTestRule = createAndroidComposeRule<MainActivity>()
@get: Rule
val grantPermissionRule: GrantPermissionRule = GrantPermissionRule.grant(
Manifest.permission.POST_NOTIFICATIONS,
Manifest.permission.CAMERA
)
}

View file

@ -1,45 +1,43 @@
package com.tangem.tests
import android.content.Intent.ACTION_VIEW
import androidx.test.espresso.intent.Intents
import com.tangem.helpers.base.BaseAutoTestCase
import com.tangem.common.BaseTestCase
import com.tangem.screens.StoriesScreen
import com.tangem.tap.features.home.redux.HomeMiddleware.NEW_BUY_WALLET_URL
import dagger.hilt.android.testing.HiltAndroidTest
import io.github.kakaocup.compose.node.element.ComposeScreen
import io.github.kakaocup.kakao.intent.KIntent
import org.junit.Test
class StoriesTest : BaseAutoTestCase() {
@HiltAndroidTest
class StoriesTest : BaseTestCase() {
@Test
fun clickOnButtons() = before {
Intents.init()
}.after {
Intents.release()
}.run {
ComposeScreen.onComposeScreen<StoriesScreen>(composeTestRule) {
step("Click on \"Scan\" button") {
scanButton {
assertIsDisplayed()
performClick()
fun clickOnButtons() =
setupHooks().run {
ComposeScreen.onComposeScreen<StoriesScreen>(composeTestRule) {
step("Click on \"Scan\" button") {
scanButton {
assertIsDisplayed()
performClick()
}
}
}
step("Assert: \"Scan card\" popup opened") {
enableNFCAlert.isDisplayed()
cancelButton.click()
device.uiDevice.pressBack()
}
step("Click on \"Order\" button") {
orderButton.performClick()
}
step("Assert: browser opened") {
val expectedIntent = KIntent {
hasAction(ACTION_VIEW)
hasData(NEW_BUY_WALLET_URL)
step("Assert: \"Scan card\" popup opened") {
enableNFCAlert.isDisplayed()
cancelButton.click()
device.uiDevice.pressBack()
}
step("Click on \"Order\" button") {
orderButton.performClick()
}
step("Assert: browser opened") {
val expectedIntent = KIntent {
hasAction(ACTION_VIEW)
hasData(NEW_BUY_WALLET_URL)
}
expectedIntent.intended()
device.uiDevice.pressBack()
}
expectedIntent.intended()
device.uiDevice.pressBack()
}
}
}
}