From 0a39bb800b9aa56393b20756422594f87964e6ab Mon Sep 17 00:00:00 2001 From: Sebastian Lobato Genco Date: Thu, 26 Sep 2024 22:44:40 +0200 Subject: [PATCH] Add test for scoped object backstack survival with config change recreation --- .../KeysInScopeActivityRecreationTests.kt | 2 +- .../sample/ComposeNavigationTests.kt | 36 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/sample/src/androidTest/java/com/sebaslogen/resacaapp/sample/KeysInScopeActivityRecreationTests.kt b/sample/src/androidTest/java/com/sebaslogen/resacaapp/sample/KeysInScopeActivityRecreationTests.kt index 916b7914..3cf04f52 100644 --- a/sample/src/androidTest/java/com/sebaslogen/resacaapp/sample/KeysInScopeActivityRecreationTests.kt +++ b/sample/src/androidTest/java/com/sebaslogen/resacaapp/sample/KeysInScopeActivityRecreationTests.kt @@ -53,7 +53,7 @@ class KeysInScopeActivityRecreationTests : ComposeTestUtils { Thread.sleep(COMPOSITION_RESUMED_TIMEOUT_IN_SECONDS * 2 * 1000) // Wait for the ViewModel to be cleared composeTestRule.onNodeWithTag("LazyList").performScrollToIndex(0) - // Then the scoped ViewModel disappears + // Then the scoped ViewModel is still the same onNodeWithTestTag("FakeScopedViewModel 1 Scoped").assertIsDisplayed().assertTextEquals(initialFakeScopedViewModelText) } } \ No newline at end of file diff --git a/sample/src/test/java/com/sebaslogen/resacaapp/sample/ComposeNavigationTests.kt b/sample/src/test/java/com/sebaslogen/resacaapp/sample/ComposeNavigationTests.kt index 4ca9ee79..2856d294 100644 --- a/sample/src/test/java/com/sebaslogen/resacaapp/sample/ComposeNavigationTests.kt +++ b/sample/src/test/java/com/sebaslogen/resacaapp/sample/ComposeNavigationTests.kt @@ -1,15 +1,22 @@ package com.sebaslogen.resacaapp.sample +import android.content.Intent import androidx.compose.ui.test.assert import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.assertTextEquals import androidx.compose.ui.test.hasTextExactly import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.performClick import androidx.navigation.NavHostController import androidx.navigation.compose.rememberNavController +import androidx.test.core.app.ActivityScenario +import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.sebaslogen.resaca.COMPOSITION_RESUMED_TIMEOUT_IN_SECONDS +import com.sebaslogen.resacaapp.sample.ui.main.ComposeActivity import com.sebaslogen.resacaapp.sample.ui.main.ScreensWithNavigation import com.sebaslogen.resacaapp.sample.ui.main.rememberScopedDestination +import com.sebaslogen.resacaapp.sample.ui.main.viewModelScopedDestination import com.sebaslogen.resacaapp.sample.utils.ComposeTestUtils import org.junit.Rule import org.junit.Test @@ -78,4 +85,33 @@ class ComposeNavigationTests : ComposeTestUtils { // Then the text of the NOT scoped object is different from the original one because it's a new object onNodeWithTestTag("FakeRepo Not scoped").assertIsDisplayed().assert(hasTextExactly(initialFakeRepoText).not()) } + + @Test + fun `when I navigate to nested screen, produce an activity recreation and navigate back, then the scoped objects are the same`() { + // Given the starting screen with ViewModel scoped + val launchIntent = Intent(ApplicationProvider.getApplicationContext(), ComposeActivity::class.java).apply { + putExtra(ComposeActivity.START_DESTINATION, viewModelScopedDestination) + } + ActivityScenario.launch(launchIntent).use { scenario -> + scenario.onActivity { activity: ComposeActivity -> + // Find the scoped text fields and grab their texts + val initialFakeScopedViewModelText = retrieveTextFromNodeWithTestTag("FakeScopedViewModel Scoped") + printComposeUiTreeToLog() + + // When I navigate to a second screen I apply the configuration change by recreating the Activity + onNodeWithTestTag("Navigate to rememberScoped").performClick() + printComposeUiTreeToLog() + val newScenario: ActivityScenario = scenario.recreate() + Thread.sleep(COMPOSITION_RESUMED_TIMEOUT_IN_SECONDS * 2 * 1000) // Wait for the ViewModel to be cleared + printComposeUiTreeToLog() // Print is needed to push the main thread forward + + // And then I navigate back to the first screen + newScenario.onActivity { it.onBackPressedDispatcher.onBackPressed() } + printComposeUiTreeToLog() // Print is needed to push the main thread forward + + // Then the scoped ViewModel is still the same + onNodeWithTestTag("FakeScopedViewModel Scoped").assertIsDisplayed().assertTextEquals(initialFakeScopedViewModelText) + } + } + } } \ No newline at end of file