Add a test for restoring compose content
This commit is contained in:
parent
2e97716b48
commit
47037d4bcd
3 changed files with 73 additions and 3 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
package org.fnives.test.showcase.ui
|
package org.fnives.test.showcase.ui
|
||||||
|
|
||||||
|
import androidx.compose.ui.test.junit4.StateRestorationTester
|
||||||
import androidx.compose.ui.test.junit4.createComposeRule
|
import androidx.compose.ui.test.junit4.createComposeRule
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import org.fnives.test.showcase.R
|
import org.fnives.test.showcase.R
|
||||||
|
|
@ -22,6 +23,7 @@ class AuthComposeInstrumentedTest : KoinTest {
|
||||||
|
|
||||||
@get:Rule
|
@get:Rule
|
||||||
val composeTestRule = createComposeRule()
|
val composeTestRule = createComposeRule()
|
||||||
|
private val stateRestorationTester = StateRestorationTester(composeTestRule)
|
||||||
|
|
||||||
private val mockServerScenarioSetupTestRule = MockServerScenarioSetupResetingTestRule()
|
private val mockServerScenarioSetupTestRule = MockServerScenarioSetupResetingTestRule()
|
||||||
private val mockServerScenarioSetup get() = mockServerScenarioSetupTestRule.mockServerScenarioSetup
|
private val mockServerScenarioSetup get() = mockServerScenarioSetupTestRule.mockServerScenarioSetup
|
||||||
|
|
@ -37,7 +39,7 @@ class AuthComposeInstrumentedTest : KoinTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
composeTestRule.setContent {
|
stateRestorationTester.setContent {
|
||||||
AppNavigation(isUserLogeInUseCase = IsUserLoggedInUseCase(FakeUserDataLocalStorage()))
|
AppNavigation(isUserLogeInUseCase = IsUserLoggedInUseCase(FakeUserDataLocalStorage()))
|
||||||
}
|
}
|
||||||
robot = ComposeLoginRobot(composeTestRule)
|
robot = ComposeLoginRobot(composeTestRule)
|
||||||
|
|
@ -152,4 +154,21 @@ class AuthComposeInstrumentedTest : KoinTest {
|
||||||
.assertNotLoading()
|
.assertNotLoading()
|
||||||
navigationRobot.assertAuthScreen()
|
navigationRobot.assertAuthScreen()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** GIVEN username and password WHEN restoring THEN username and password fields contain the same text */
|
||||||
|
@Test
|
||||||
|
fun restoringContentShowPreviousCredentials() {
|
||||||
|
composeTestRule.mainClock.advanceTimeUntil { anyResourceIdling() }
|
||||||
|
navigationRobot.assertAuthScreen()
|
||||||
|
robot.setUsername("alma")
|
||||||
|
.setPassword("banan")
|
||||||
|
.assertUsername("alma")
|
||||||
|
.assertPassword("banan")
|
||||||
|
|
||||||
|
stateRestorationTester.emulateSavedInstanceStateRestore()
|
||||||
|
|
||||||
|
navigationRobot.assertAuthScreen()
|
||||||
|
robot.assertUsername("alma")
|
||||||
|
.assertPassword("banan")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
package org.fnives.test.showcase.compose.screen.auth
|
package org.fnives.test.showcase.compose.screen.auth
|
||||||
|
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.platform.AndroidUiDispatcher
|
import androidx.compose.runtime.saveable.Saver
|
||||||
|
import androidx.compose.runtime.saveable.mapSaver
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
@ -17,7 +19,9 @@ fun rememberAuthScreenState(
|
||||||
loginUseCase: LoginUseCase = get(),
|
loginUseCase: LoginUseCase = get(),
|
||||||
onLoginSuccess: () -> Unit = {},
|
onLoginSuccess: () -> Unit = {},
|
||||||
): AuthScreenState {
|
): AuthScreenState {
|
||||||
return remember { AuthScreenState(stateScope, loginUseCase, onLoginSuccess) }
|
return rememberSaveable(saver = AuthScreenState.getSaver(stateScope, loginUseCase, onLoginSuccess)) {
|
||||||
|
AuthScreenState(stateScope, loginUseCase, onLoginSuccess)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AuthScreenState(
|
class AuthScreenState(
|
||||||
|
|
@ -80,4 +84,23 @@ class AuthScreenState(
|
||||||
UNSUPPORTED_USERNAME,
|
UNSUPPORTED_USERNAME,
|
||||||
UNSUPPORTED_PASSWORD
|
UNSUPPORTED_PASSWORD
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val USERNAME = "USERNAME"
|
||||||
|
private const val PASSWORD = "PASSWORD"
|
||||||
|
|
||||||
|
fun getSaver(
|
||||||
|
stateScope: CoroutineScope,
|
||||||
|
loginUseCase: LoginUseCase,
|
||||||
|
onLoginSuccess: () -> Unit,
|
||||||
|
): Saver<AuthScreenState, *> = mapSaver(
|
||||||
|
save = { mapOf(USERNAME to it.username, PASSWORD to it.password) },
|
||||||
|
restore = {
|
||||||
|
AuthScreenState(stateScope, loginUseCase, onLoginSuccess).apply {
|
||||||
|
onUsernameChanged(it.getOrElse(USERNAME) { "" } as String)
|
||||||
|
onPasswordChanged(it.getOrElse(PASSWORD) { "" } as String)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -324,3 +324,31 @@ robot.assertErrorIsShown(R.string.something_went_wrong)
|
||||||
.assertNotLoading()
|
.assertNotLoading()
|
||||||
navigationRobot.assertAuthScreen()
|
navigationRobot.assertAuthScreen()
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 6. `restoringContentShowPreviousCredentials`
|
||||||
|
|
||||||
|
Since we're writing apps for Android, we must handle state restoration so let's write a test for it.
|
||||||
|
|
||||||
|
For simulating the recreation of the UI, we first need a `StateRestorationTester`:
|
||||||
|
```kotlin
|
||||||
|
private val stateRestorationTester = StateRestorationTester(composeTestRule)
|
||||||
|
```
|
||||||
|
|
||||||
|
Then in `setup()`, we need to `setContent` on `stateRestorationTester` instead of on `composeTestRule`.
|
||||||
|
|
||||||
|
Now for the actual test, we first setup the content then we trigger restoration by calling `stateRestorationTester.emulateSavedInstanceStateRestore()`, afterwards we can verify that the content is recreated in the correct way:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
composeTestRule.mainClock.advanceTimeUntil { anyResourceIdling() }
|
||||||
|
navigationRobot.assertAuthScreen()
|
||||||
|
robot.setUsername("alma")
|
||||||
|
.setPassword("banan")
|
||||||
|
.assertUsername("alma")
|
||||||
|
.assertPassword("banan")
|
||||||
|
|
||||||
|
stateRestorationTester.emulateSavedInstanceStateRestore()
|
||||||
|
|
||||||
|
navigationRobot.assertAuthScreen()
|
||||||
|
robot.assertUsername("alma")
|
||||||
|
.assertPassword("banan")
|
||||||
|
```
|
||||||
Loading…
Add table
Add a link
Reference in a new issue