1*21373fa4SWill Schurman package host.exp.exponent.utils
2*21373fa4SWill Schurman 
3*21373fa4SWill Schurman import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner
4*21373fa4SWill Schurman import host.exp.exponent.annotations.ExpoAlwaysPassThroughFilter
5*21373fa4SWill Schurman import host.exp.exponent.annotations.ExpoDevModeTest
6*21373fa4SWill Schurman import host.exp.exponent.annotations.ExpoSdkVersionTest
7*21373fa4SWill Schurman import host.exp.exponent.annotations.ExpoTestSuiteTest
8*21373fa4SWill Schurman import org.json.JSONObject
9*21373fa4SWill Schurman import org.junit.runner.Description
10*21373fa4SWill Schurman import org.junit.runner.manipulation.Filter
11*21373fa4SWill Schurman import org.junit.runner.manipulation.NoTestsRemainException
12*21373fa4SWill Schurman 
13*21373fa4SWill Schurman class ExpoTestRunner(klass: Class<*>?) : AndroidJUnit4ClassRunner(klass) {
14*21373fa4SWill Schurman   class ExpoTestFilter : Filter() {
15*21373fa4SWill Schurman     private val testConfig: JSONObject = TestConfig.get()
16*21373fa4SWill Schurman 
shouldRunnull17*21373fa4SWill Schurman     override fun shouldRun(description: Description): Boolean {
18*21373fa4SWill Schurman       if (description.getAnnotation(ExpoAlwaysPassThroughFilter::class.java) != null) {
19*21373fa4SWill Schurman         return true
20*21373fa4SWill Schurman       }
21*21373fa4SWill Schurman       val testTypes = testConfig.optJSONArray(TEST_TYPES_KEY)
22*21373fa4SWill Schurman       if (testTypes != null) {
23*21373fa4SWill Schurman         var foundTestType = false
24*21373fa4SWill Schurman         for (i in 0 until testTypes.length()) {
25*21373fa4SWill Schurman           if (testTypes.optString(i) == TEST_SUITE_TEST_TYPE && description.getAnnotation(
26*21373fa4SWill Schurman               ExpoTestSuiteTest::class.java
27*21373fa4SWill Schurman             ) != null
28*21373fa4SWill Schurman           ) {
29*21373fa4SWill Schurman             foundTestType = true
30*21373fa4SWill Schurman           } else if (testTypes.optString(i) == DEV_MODE_TEST_TYPE && description.getAnnotation(
31*21373fa4SWill Schurman               ExpoDevModeTest::class.java
32*21373fa4SWill Schurman             ) != null
33*21373fa4SWill Schurman           ) {
34*21373fa4SWill Schurman             foundTestType = true
35*21373fa4SWill Schurman           }
36*21373fa4SWill Schurman         }
37*21373fa4SWill Schurman         if (!foundTestType) {
38*21373fa4SWill Schurman           return false
39*21373fa4SWill Schurman         }
40*21373fa4SWill Schurman       }
41*21373fa4SWill Schurman       val sdkVersions = testConfig.optJSONArray(SDK_VERSIONS_KEY)
42*21373fa4SWill Schurman       val sdkVersionAnnotation = description.getAnnotation(
43*21373fa4SWill Schurman         ExpoSdkVersionTest::class.java
44*21373fa4SWill Schurman       )
45*21373fa4SWill Schurman       if (sdkVersions != null && sdkVersionAnnotation != null) {
46*21373fa4SWill Schurman         var foundSdkVersion = false
47*21373fa4SWill Schurman         for (i in 0 until sdkVersions.length()) {
48*21373fa4SWill Schurman           if (sdkVersionAnnotation.value == sdkVersions.optString(i)) {
49*21373fa4SWill Schurman             foundSdkVersion = true
50*21373fa4SWill Schurman           }
51*21373fa4SWill Schurman         }
52*21373fa4SWill Schurman         if (!foundSdkVersion) {
53*21373fa4SWill Schurman           return false
54*21373fa4SWill Schurman         }
55*21373fa4SWill Schurman       }
56*21373fa4SWill Schurman       return true
57*21373fa4SWill Schurman     }
58*21373fa4SWill Schurman 
describenull59*21373fa4SWill Schurman     override fun describe(): String {
60*21373fa4SWill Schurman       return "Filters tests based on TEST_CONFIG env var"
61*21373fa4SWill Schurman     }
62*21373fa4SWill Schurman   }
63*21373fa4SWill Schurman 
64*21373fa4SWill Schurman   companion object {
65*21373fa4SWill Schurman     const val TEST_TYPES_KEY = "includeTestTypes"
66*21373fa4SWill Schurman     const val TEST_SUITE_TEST_TYPE = "test-suite"
67*21373fa4SWill Schurman     const val DEV_MODE_TEST_TYPE = "dev-mode"
68*21373fa4SWill Schurman     const val SDK_VERSIONS_KEY = "includeSdkVersions"
69*21373fa4SWill Schurman   }
70*21373fa4SWill Schurman 
71*21373fa4SWill Schurman   init {
72*21373fa4SWill Schurman     val filter = ExpoTestFilter()
73*21373fa4SWill Schurman     try {
74*21373fa4SWill Schurman       filter.apply(this)
75*21373fa4SWill Schurman     } catch (e: NoTestsRemainException) {
76*21373fa4SWill Schurman       throw RuntimeException(e)
77*21373fa4SWill Schurman     }
78*21373fa4SWill Schurman   }
79*21373fa4SWill Schurman }
80