0

I'm writing instrumented tests for a Jetpack Compose component. My composable uses rememberSaveable to remember between configuration changes (activity restarts):

@Composable
fun AddUserScreen() {
    Input(
        shouldRequestFocus = true,
        stringResource(R.string.user_first_name),
        stringResource(R.string.user_first_name_label),
        tag = "input-first-name"
    )
}

@Composable
fun Input(
    shouldRequestFocus: Boolean,
    text: String,
    label: String,
    tag: String
) {
    var value by rememberSaveable { mutableStateOf("") } // <-- Important part
    val focusRequester = FocusRequester()

    Row(verticalAlignment = Alignment.CenterVertically) {
        Text(text)
        Spacer(modifier = Modifier.width(10.dp))
        TextField(
            value = value,
            onValueChange = { value = it },
            label = { Text(label) },
            keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
            modifier = Modifier
                .focusRequester(focusRequester)
                .testTag(tag)
        )
    }

    if (shouldRequestFocus) {
        DisposableEffect(Unit) {
            focusRequester.requestFocus()
            onDispose { }
        }
    }
}

The input value is retained when I open the app myself and rotate the device. But in the following test the input is not retained on configuration change and the test fails:

@get:Rule val composeTestRule = createAndroidComposeRule<AddUserActivity>()

@Test fun whenAConfigChangeHappensTheFirstNameInputShouldRetainItsValue() {
    composeTestRule.setContent {
        WorkoutLoggerTheme {
            AddUserScreen()
        }
    }
    composeTestRule.onNodeWithTag("input-first-name").performTextInput("John")
    composeTestRule.activity.requestedOrientation = SCREEN_ORIENTATION_LANDSCAPE
    composeTestRule.waitForIdle()
    composeTestRule.onNodeWithTag("input-first-name").assertTextEquals("John")
}
Mahozad
  • 18,032
  • 13
  • 118
  • 133
  • 1
    The content you've set via `composeTestRule.setContent` doesn't persist across configuration changes - are you sure you have any content at all after your `waitForIdle()` call? I would have expected you to need to call `setContent` a second time. – ianhanniballake Apr 04 '22 at 19:49
  • @ianhanniballake Yes. When I debug the test, the content is available in the screen after rotation but the input is empty. After calling `setContent` a second time the test failed with this message: *... Cannot call setContent twice per test!* – Mahozad Apr 05 '22 at 06:19
  • By the way, sorry for the late response. I'm in a different time zone. – Mahozad Apr 05 '22 at 10:01

0 Answers0