I'm trying to write an integration test for an Android application entirely written in Compose that has a single Activity and uses the Compose Navigation to change the screen content.
I managed to properly interact and test the first screen that is shown by the navigation graph but, as soon as I navigate to a new destination, the test fails because it does not wait for the NavHost to load the new content.
@RunWith(AndroidJUnit4::class)
class MainActivityTest {
@get:Rule
val composeTestRule = createAndroidComposeRule<MainActivity>()
@Test
fun appStartsWithoutCrashing() {
composeTestRule.apply {
// Check Switch
onNodeWithTag(FirstScreen.CONSENT_SWITCH)
.assertIsDisplayed()
.assertIsOff()
.performClick()
.assertIsOn()
// Click accept button
onNodeWithTag(FirstScreen.ACCEPT_BUTTON)
.assertIsDisplayed()
.performClick()
// Check we are inside the second screen
onNodeWithTag(SecondScreen.USERNAME_TEXT_FIELD)
.assertIsDisplayed()
}
}
}
I'm sure that is a timing issue because if I add a Thread.sleep(500)
before the onNodeWithTag(SecondScreen.USERNAME_TEXT_FIELD).assertIsDisplayed()
, the test is successful. But I would like to avoid Thread.sleep()
s in my code.
Is there a better way to tell the composeTestRule
to wait for the NavHost to load the new content before executing the assertIsDisplayed()
?
PS I know that would be better to test the Composables in isolation, but I really want to simulate the user input on the App using Espresso and not only test the Composable behavior.