diff --git a/formula-android-tests/src/main/AndroidManifest.xml b/formula-android-tests/src/main/AndroidManifest.xml index c48ff6712..2a6798b73 100644 --- a/formula-android-tests/src/main/AndroidManifest.xml +++ b/formula-android-tests/src/main/AndroidManifest.xml @@ -13,26 +13,5 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/formula-android-tests/src/test/java/com/instacart/formula/ActivityLifecycleEventTest.kt b/formula-android-tests/src/test/java/com/instacart/formula/ActivityLifecycleEventTest.kt index 29c8569c5..0b7d6e02a 100644 --- a/formula-android-tests/src/test/java/com/instacart/formula/ActivityLifecycleEventTest.kt +++ b/formula-android-tests/src/test/java/com/instacart/formula/ActivityLifecycleEventTest.kt @@ -3,28 +3,24 @@ package com.instacart.formula import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle.State.* import androidx.test.core.app.ActivityScenario -import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 import com.google.common.truth.Truth.assertThat import com.instacart.formula.android.ActivityStore -import com.instacart.formula.android.FormulaAppCompatActivity -import org.junit.Before +import com.instacart.testutils.android.TestFormulaActivity +import com.instacart.testutils.android.activity import org.junit.Rule import org.junit.Test -import org.junit.rules.RuleChain import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class ActivityLifecycleEventTest { - - class TestActivity : FormulaAppCompatActivity() - private lateinit var events: MutableList - private val formulaRule = TestFormulaRule( + @get:Rule + val rule = TestFormulaRule( initFormula = { app -> FormulaAndroid.init(app) { - activity { + activity { events = mutableListOf() ActivityStore( streams = { @@ -37,18 +33,9 @@ class ActivityLifecycleEventTest { } }) - private val activityRule = ActivityScenarioRule(TestActivity::class.java) - - @get:Rule - val rule = RuleChain.outerRule(formulaRule).around(activityRule) - lateinit var scenario: ActivityScenario - - @Before - fun setup() { - scenario = activityRule.scenario - } - - @Test fun `full lifecycle`() { + @Test + fun `full lifecycle`() { + val scenario = ActivityScenario.launch(TestFormulaActivity::class.java) scenario.recreate() scenario.close() @@ -58,11 +45,13 @@ class ActivityLifecycleEventTest { assertThat(events).containsExactlyElementsIn(expected).inOrder() } - @Test fun `calling onPreCreate() twice will throw an exception`() { + @Test + fun `calling onPreCreate() twice will throw an exception`() { + val scenario = ActivityScenario.launch(TestFormulaActivity::class.java) val activity = scenario.activity() val result = runCatching { FormulaAndroid.onPreCreate(activity, null) } assertThat(result.exceptionOrNull()).hasMessageThat().contains( - "Activity TestActivity was already initialized. Did you call FormulaAndroid.onPreCreate() twice?" + "Activity TestFormulaActivity was already initialized. Did you call FormulaAndroid.onPreCreate() twice?" ) } } diff --git a/formula-android-tests/src/test/java/com/instacart/formula/ActivityUpdateTest.kt b/formula-android-tests/src/test/java/com/instacart/formula/ActivityUpdateTest.kt index 349d296a4..514a12c17 100644 --- a/formula-android-tests/src/test/java/com/instacart/formula/ActivityUpdateTest.kt +++ b/formula-android-tests/src/test/java/com/instacart/formula/ActivityUpdateTest.kt @@ -1,13 +1,15 @@ package com.instacart.formula -import android.os.Bundle +import android.app.Activity import androidx.test.core.app.ActivityScenario import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 import com.google.common.truth.Truth.assertThat import com.instacart.formula.android.ActivityStore -import com.instacart.formula.android.FormulaAppCompatActivity +import com.instacart.testutils.android.TestFormulaActivity +import com.instacart.testutils.android.get import com.jakewharton.rxrelay3.PublishRelay +import org.junit.After import org.junit.Before import org.junit.Rule import org.junit.Test @@ -17,43 +19,37 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class ActivityUpdateTest { - class TestActivity : FormulaAppCompatActivity() { - val updates = mutableListOf() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.test_activity) - } - - fun applyUpdate(update: String) { - updates.add(update) - } - } - + private val updates = mutableListOf>() private val updateRelay = PublishRelay.create() private val formulaRule = TestFormulaRule( initFormula = { app -> FormulaAndroid.init(app) { - activity { + activity { ActivityStore( streams = { - update(updateRelay, TestActivity::applyUpdate) + update(updateRelay) { activity, state -> + updates.add(activity to state) + } } ) } } }) - private val activityRule = ActivityScenarioRule(TestActivity::class.java) + private val activityRule = ActivityScenarioRule(TestFormulaActivity::class.java) @get:Rule val rule = RuleChain.outerRule(formulaRule).around(activityRule) - lateinit var scenario: ActivityScenario + lateinit var scenario: ActivityScenario @Before fun setup() { scenario = activityRule.scenario } + @After fun cleanup() { + updates.clear() + } + @Test fun `basic updates`() { updateRelay.accept("update-1") updateRelay.accept("update-2") @@ -78,5 +74,7 @@ class ActivityUpdateTest { assertThat(updateRelay.hasObservers()).isFalse() } - private fun updates() = scenario.get { updates } + private fun updates() = scenario.get { + updates.filter { it.first == this }.map { it.second } + } } diff --git a/formula-android-tests/src/test/java/com/instacart/formula/ActivityUpdateTimingTest.kt b/formula-android-tests/src/test/java/com/instacart/formula/ActivityUpdateTimingTest.kt index 1b3b2b5b1..cf5215d64 100644 --- a/formula-android-tests/src/test/java/com/instacart/formula/ActivityUpdateTimingTest.kt +++ b/formula-android-tests/src/test/java/com/instacart/formula/ActivityUpdateTimingTest.kt @@ -1,12 +1,13 @@ package com.instacart.formula -import android.os.Bundle +import android.app.Activity import androidx.test.core.app.ActivityScenario import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 import com.google.common.truth.Truth.assertThat import com.instacart.formula.android.ActivityStore -import com.instacart.formula.android.FormulaAppCompatActivity +import com.instacart.testutils.android.TestFormulaActivity +import com.instacart.testutils.android.get import io.reactivex.rxjava3.core.Observable import org.junit.Before import org.junit.Rule @@ -17,48 +18,37 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class ActivityUpdateTimingTest { - class TestActivity : FormulaAppCompatActivity() { - lateinit var updates: MutableList - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.test_activity) - - // we delay initialization after super.onCreate() to check that Formula timing doesn't break. - updates = mutableListOf() - } - - fun applyUpdate(update: String) { - updates.add(update) - } - } - + private val updates = mutableListOf>() private val updateRelay = Observable.just("update-1", "update-2") private val formulaRule = TestFormulaRule( initFormula = { app -> FormulaAndroid.init(app) { - activity { + activity { ActivityStore( streams = { - update(updateRelay, TestActivity::applyUpdate) + update(updateRelay) { activity, state -> + updates.add(activity to state) + } } ) } } }) - private val activityRule = ActivityScenarioRule(TestActivity::class.java) + private val activityRule = ActivityScenarioRule(TestFormulaActivity::class.java) @get:Rule val rule = RuleChain.outerRule(formulaRule).around(activityRule) - lateinit var scenario: ActivityScenario + lateinit var scenario: ActivityScenario @Before fun setup() { scenario = activityRule.scenario } @Test fun `last update arrives`() { - val updates = scenario.get { updates } + val updates = scenario.get { + updates.filter { it.first == this }.map { it.second } + } assertThat(updates).containsExactly("update-2").inOrder() } } diff --git a/formula-android-tests/src/test/java/com/instacart/formula/FormulaFragmentTest.kt b/formula-android-tests/src/test/java/com/instacart/formula/FormulaFragmentTest.kt index 7669b1274..0436a81d2 100644 --- a/formula-android-tests/src/test/java/com/instacart/formula/FormulaFragmentTest.kt +++ b/formula-android-tests/src/test/java/com/instacart/formula/FormulaFragmentTest.kt @@ -6,7 +6,6 @@ import androidx.lifecycle.Lifecycle import androidx.test.core.app.ActivityScenario import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 -import com.google.common.truth.Truth import com.google.common.truth.Truth.assertThat import com.instacart.formula.android.ActivityStore import com.instacart.formula.android.FragmentState @@ -21,6 +20,8 @@ import com.instacart.formula.test.TestKey import com.instacart.formula.test.TestKeyWithId import com.instacart.formula.test.TestFragmentActivity import com.instacart.formula.test.TestLifecycleKey +import com.instacart.testutils.android.activity +import com.instacart.testutils.android.get import com.jakewharton.rxrelay3.PublishRelay import io.reactivex.rxjava3.core.Observable import org.junit.Before diff --git a/formula-android-tests/src/test/java/com/instacart/formula/FragmentAndroidEventTest.kt b/formula-android-tests/src/test/java/com/instacart/formula/FragmentAndroidEventTest.kt index 9ea281719..16dbb7fdd 100644 --- a/formula-android-tests/src/test/java/com/instacart/formula/FragmentAndroidEventTest.kt +++ b/formula-android-tests/src/test/java/com/instacart/formula/FragmentAndroidEventTest.kt @@ -12,6 +12,7 @@ import com.instacart.formula.android.ViewFactory import com.instacart.formula.android.events.ActivityResult import com.instacart.formula.test.TestFragmentActivity import com.instacart.formula.test.TestLifecycleKey +import com.instacart.testutils.android.activity import io.reactivex.rxjava3.core.Observable import org.junit.Before import org.junit.Rule diff --git a/formula-android-tests/src/test/java/com/instacart/formula/NonBoundActivityTest.kt b/formula-android-tests/src/test/java/com/instacart/formula/NonBoundActivityTest.kt index aa313f125..0e0fd0614 100644 --- a/formula-android-tests/src/test/java/com/instacart/formula/NonBoundActivityTest.kt +++ b/formula-android-tests/src/test/java/com/instacart/formula/NonBoundActivityTest.kt @@ -1,14 +1,10 @@ package com.instacart.formula -import android.app.Activity import androidx.test.core.app.ActivityScenario -import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 import com.instacart.testutils.android.TestActivity -import org.junit.Before import org.junit.Rule import org.junit.Test -import org.junit.rules.RuleChain import org.junit.runner.RunWith /** @@ -17,25 +13,16 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class NonBoundActivityTest { - private val formulaRule = TestFormulaRule( + @get:Rule + val rule = TestFormulaRule( initFormula = { app -> FormulaAndroid.init(app) {} } ) - private val activityRule = ActivityScenarioRule(TestActivity::class.java) - - @get:Rule - val rule = RuleChain.outerRule(formulaRule).around(activityRule) - lateinit var scenario: ActivityScenario - - @Before - fun setup() { - scenario = activityRule.scenario - } - @Test fun `full lifecycle`() { + val scenario = ActivityScenario.launch(TestActivity::class.java) scenario.recreate() scenario.close() } diff --git a/formula-android-tests/src/test/java/com/instacart/formula/NonBoundFragmentActivityTest.kt b/formula-android-tests/src/test/java/com/instacart/formula/NonBoundFragmentActivityTest.kt index a48fadca7..367ceaa8a 100644 --- a/formula-android-tests/src/test/java/com/instacart/formula/NonBoundFragmentActivityTest.kt +++ b/formula-android-tests/src/test/java/com/instacart/formula/NonBoundFragmentActivityTest.kt @@ -1,13 +1,10 @@ package com.instacart.formula import androidx.test.core.app.ActivityScenario -import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 import com.instacart.testutils.android.TestFragmentActivity -import org.junit.Before import org.junit.Rule import org.junit.Test -import org.junit.rules.RuleChain import org.junit.runner.RunWith /** @@ -15,25 +12,17 @@ import org.junit.runner.RunWith */ @RunWith(AndroidJUnit4::class) class NonBoundFragmentActivityTest { - private val formulaRule = TestFormulaRule( + + @get:Rule + val rule = TestFormulaRule( initFormula = { app -> FormulaAndroid.init(app) {} } ) - private val activityRule = ActivityScenarioRule(TestFragmentActivity::class.java) - - @get:Rule - val rule = RuleChain.outerRule(formulaRule).around(activityRule) - lateinit var scenario: ActivityScenario - - @Before - fun setup() { - scenario = activityRule.scenario - } - @Test fun `full lifecycle`() { + val scenario = ActivityScenario.launch(TestFragmentActivity::class.java) scenario.recreate() scenario.close() } diff --git a/formula-android-tests/src/test/java/com/instacart/formula/TestExtensions.kt b/formula-android-tests/src/test/java/com/instacart/formula/TestExtensions.kt deleted file mode 100644 index 1c9e035e1..000000000 --- a/formula-android-tests/src/test/java/com/instacart/formula/TestExtensions.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.instacart.formula - -import android.app.Activity -import androidx.test.core.app.ActivityScenario - -fun ActivityScenario.activity(): A { - return get { this } -} - -fun ActivityScenario.get(select: A.() -> T): T { - val list: MutableList = mutableListOf() - onActivity { - list.add(it.select()) - } - return list.first() -} diff --git a/formula-android-tests/src/test/java/com/instacart/formula/FormulaAndroidTest.kt b/formula-android/src/test/java/com/instacart/formula/FormulaAndroidTest.kt similarity index 90% rename from formula-android-tests/src/test/java/com/instacart/formula/FormulaAndroidTest.kt rename to formula-android/src/test/java/com/instacart/formula/FormulaAndroidTest.kt index 065670930..2ee649117 100644 --- a/formula-android-tests/src/test/java/com/instacart/formula/FormulaAndroidTest.kt +++ b/formula-android/src/test/java/com/instacart/formula/FormulaAndroidTest.kt @@ -4,6 +4,7 @@ import android.app.Application import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.google.common.truth.Truth +import com.instacart.testutils.android.TestFormulaActivity import org.junit.Test import org.junit.runner.RunWith @@ -27,7 +28,7 @@ class FormulaAndroidTest { @Test fun `crashes if accessed before initialization`() { val result = runCatching { - FormulaAndroid.onBackPressed(ActivityUpdateTest.TestActivity()) + FormulaAndroid.onBackPressed(TestFormulaActivity()) } val errorMessage = result.exceptionOrNull()?.message Truth.assertThat(errorMessage).isEqualTo( diff --git a/formula-android-tests/src/test/java/com/instacart/formula/android/internal/AndroidUpdateSchedulerTest.kt b/formula-android/src/test/java/com/instacart/formula/android/internal/AndroidUpdateSchedulerTest.kt similarity index 100% rename from formula-android-tests/src/test/java/com/instacart/formula/android/internal/AndroidUpdateSchedulerTest.kt rename to formula-android/src/test/java/com/instacart/formula/android/internal/AndroidUpdateSchedulerTest.kt diff --git a/formula-android-tests/src/test/java/com/instacart/formula/android/utils/MainThreadDispatcherTest.kt b/formula-android/src/test/java/com/instacart/formula/android/utils/MainThreadDispatcherTest.kt similarity index 83% rename from formula-android-tests/src/test/java/com/instacart/formula/android/utils/MainThreadDispatcherTest.kt rename to formula-android/src/test/java/com/instacart/formula/android/utils/MainThreadDispatcherTest.kt index 923e1eb3f..929227c4e 100644 --- a/formula-android-tests/src/test/java/com/instacart/formula/android/utils/MainThreadDispatcherTest.kt +++ b/formula-android/src/test/java/com/instacart/formula/android/utils/MainThreadDispatcherTest.kt @@ -14,12 +14,14 @@ import java.util.concurrent.atomic.AtomicBoolean @RunWith(AndroidJUnit4::class) class MainThreadDispatcherTest { - @Test fun `isDispatchNeeded returns false when on main thread`() { + @Test + fun `isDispatchNeeded returns false when on main thread`() { val result = MainThreadDispatcher().isDispatchNeeded() Truth.assertThat(result).isFalse() } - @Test fun `isDispatchNeeded returns true when not on main thread`() { + @Test + fun `isDispatchNeeded returns true when not on main thread`() { val latch = CountDownLatch(1) val result = AtomicBoolean() Executors.newSingleThreadExecutor().execute { @@ -34,14 +36,16 @@ class MainThreadDispatcherTest { } } - @Test fun `if dispatch is called from main thread, executable is executed immediately`() { + @Test + fun `if dispatch is called from main thread, executable is executed immediately`() { val dispatcher = MainThreadDispatcher() val loopers = mutableSetOf() dispatcher.dispatch { loopers.add(Looper.myLooper()) } Truth.assertThat(loopers).containsExactly(Looper.getMainLooper()) } - @Test fun `if dispatch is called from background thread, executable is dispatched to main thread`() { + @Test + fun `if dispatch is called from background thread, executable is dispatched to main thread`() { val dispatcher = MainThreadDispatcher() val latch = CountDownLatch(1) diff --git a/test-utils/android/src/main/AndroidManifest.xml b/test-utils/android/src/main/AndroidManifest.xml index d9fd94f38..cc7d5d877 100644 --- a/test-utils/android/src/main/AndroidManifest.xml +++ b/test-utils/android/src/main/AndroidManifest.xml @@ -10,5 +10,10 @@ android:name="com.instacart.testutils.android.TestActivity" android:launchMode="standard" android:exported="false" /> + + diff --git a/test-utils/android/src/main/java/com/instacart/testutils/android/TestFormulaActivity.kt b/test-utils/android/src/main/java/com/instacart/testutils/android/TestFormulaActivity.kt new file mode 100644 index 000000000..3548b9bcd --- /dev/null +++ b/test-utils/android/src/main/java/com/instacart/testutils/android/TestFormulaActivity.kt @@ -0,0 +1,5 @@ +package com.instacart.testutils.android + +import com.instacart.formula.android.FormulaAppCompatActivity + +class TestFormulaActivity : FormulaAppCompatActivity()