1 package com.expo.modules.devclient.scenarios 2 3 import android.app.Activity 4 import android.app.Application 5 import androidx.test.core.app.ActivityScenario 6 import androidx.test.core.app.launchActivity 7 import androidx.test.platform.app.InstrumentationRegistry 8 import com.expo.modules.devclient.interceptors.DevLauncherTestInterceptor 9 import com.expo.modules.devclient.interceptors.DevMenuTestInterceptor 10 import com.expo.modules.devclient.selectors.Views 11 import com.facebook.react.ReactNativeHost 12 import com.facebook.react.ReactPackage 13 import com.facebook.react.shell.MainReactPackage 14 import expo.modules.devlauncher.DevLauncherController 15 import expo.modules.devlauncher.koin.DevLauncherKoinContext 16 import expo.modules.devlauncher.launcher.DevLauncherActivity 17 import expo.modules.devlauncher.launcher.DevLauncherControllerInterface 18 import expo.modules.devmenu.DevMenuDefaultPreferences 19 import expo.modules.devmenu.DevMenuManager 20 import java.lang.ref.WeakReference 21 22 internal typealias ReactNativeHostCreator = (application: Application) -> ReactNativeHost 23 internal typealias DevMenuTestInterceptorCreator = () -> expo.modules.devmenu.tests.DevMenuTestInterceptor 24 internal typealias DevLauncherTestInterceptorCreator = () -> expo.modules.devlauncher.tests.DevLauncherTestInterceptor 25 internal typealias KoinDeclaration = () -> Unit 26 27 internal class DevLauncherBasicScenario( 28 private val reactNativeHostCreator: ReactNativeHostCreator? = null, 29 private val devMenuTestInterceptorCreator: DevMenuTestInterceptorCreator? = null, 30 private val devLauncherTestInterceptorCreator: DevLauncherTestInterceptorCreator? = null, 31 private val koinDeclaration: KoinDeclaration? = null, 32 private val launcherClass: Class<*>? = null 33 ) : AutoCloseable { 34 private var basicScenario: ActivityScenario<DevLauncherActivity>? = null 35 private var appHost: WeakReference<ReactNativeHost?> = WeakReference(null) 36 setUpnull37 fun setUp() { 38 DevLauncherKoinContext.reinitialize() 39 40 val appContext = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as Application 41 val rnHost = reactNativeHostCreator?.invoke(appContext) ?: defaultRNHost(appContext) 42 val devMenuTestInterceptor = devMenuTestInterceptorCreator?.invoke() 43 ?: defaultDevMenuTestInterceptor() 44 val devLauncherTestInterceptor = devLauncherTestInterceptorCreator?.invoke() 45 ?: defaultDevLauncherTestInterceptor() 46 47 DevMenuManager.testInterceptor = devMenuTestInterceptor 48 DevLauncherKoinContext.app.koin.declare(devLauncherTestInterceptor) 49 koinDeclaration?.invoke() 50 51 DevLauncherController.initialize(appContext, rnHost, launcherClass = launcherClass) 52 53 appHost = WeakReference(rnHost) 54 } 55 teardownnull56 fun teardown() { 57 basicScenario?.close() 58 } 59 launchnull60 fun launch() { 61 basicScenario = launchActivity() 62 63 Views.DevLauncher.main.isDisplayed() 64 } 65 66 @Suppress("UNCHECKED_CAST") onAppActivitynull67 fun <T : Activity> onAppActivity(activityAction: ActivityScenario.ActivityAction<T>) { 68 activityAction.perform( 69 appHost.get()!!.reactInstanceManager.currentReactContext!!.currentActivity as T 70 ) 71 } 72 onLauncherActivitynull73 fun onLauncherActivity(activityAction: ActivityScenario.ActivityAction<DevLauncherActivity>) { 74 basicScenario!!.onActivity(activityAction) 75 } 76 launcherControllernull77 fun launcherController(): DevLauncherControllerInterface { 78 return DevLauncherKoinContext.app.koin.get() 79 } 80 koinnull81 fun koin() = DevLauncherKoinContext.app.koin 82 83 private fun defaultRNHost(application: Application): ReactNativeHost { 84 return object : ReactNativeHost(application) { 85 override fun getUseDeveloperSupport(): Boolean { 86 return false 87 } 88 89 override fun getPackages(): List<ReactPackage> { 90 return listOf(MainReactPackage(null)) 91 } 92 } 93 } 94 defaultDevMenuTestInterceptornull95 private fun defaultDevMenuTestInterceptor(): expo.modules.devmenu.tests.DevMenuTestInterceptor { 96 return DevMenuTestInterceptor(object : DevMenuDefaultPreferences() { 97 override var showsAtLaunch: Boolean 98 get() = false 99 set(_) {} 100 101 override var isOnboardingFinished: Boolean 102 get() = true 103 set(_) {} 104 }) 105 } 106 defaultDevLauncherTestInterceptornull107 private fun defaultDevLauncherTestInterceptor(): expo.modules.devlauncher.tests.DevLauncherTestInterceptor { 108 return DevLauncherTestInterceptor() 109 } 110 closenull111 override fun close() { 112 teardown() 113 } 114 setUpAndLaunchnull115 inline fun <R> setUpAndLaunch(block: (DevLauncherBasicScenario) -> R) { 116 setUp() 117 launch() 118 (this as AutoCloseable).use { 119 block(this) 120 } 121 } 122 } 123