[TestingCodelab] (Optional Exercise): How to access state in RallyApp
ktprograms opened this issue ยท 6 comments
Hi, in the hints for Step 7, it says
The scope of the test needs to include the state, which is owned by
RallyApp
.
I looked at the implementation of RallyApp
, and I can see that the state is stored inside the component, so I don't know how I can access it to assert on its value.
Am I supposed to modify the RallyApp
component to move the state elsewhere, and if so, where? In a ViewModel?
This Worked for me
fun rallyTopAppBarTest_tabSelectionChangesSelectedScreen() {
val allScreens = RallyScreen.values().toList()
var currentScreen by mutableStateOf(RallyScreen.Overview)
composeTestRule.setContent {
RallyTopAppBar(
allScreens = allScreens,
onTabSelected = {
currentScreen = it
},
currentScreen = currentScreen
)
}
composeTestRule.onNode(hasContentDescription(RallyScreen.Bills.name)).performClick()
assert(currentScreen.name == RallyScreen.Bills.name)
}
@gagandeep3458
Thank you give to me a nice idea, your solution is awesome ๐
I also thought another method too, that is to use parent composable RallyApp
composeTestRule.setContent {
RallyTheme {
RallyApp()
}
}
composeTestRule
.onNodeWithContentDescription(RallyScreen.Bills.name)
.performClick()
.assertIsSelected()
@juyeop03
That's a nice solution. But it can be improved so that the test verifies that clicking on any of the tabs will change the selection.
Like this:
composeTestRule.setContent {
RallyApp()
}
val allScreens = RallyScreen.values().toList()
for (screen in allScreens) {
composeTestRule
.onNodeWithContentDescription(screen.name)
.performClick()
.assertIsSelected()
}
@gagandeep3458 Thank you. I have enhanced your solution to handle any combination of screens:
val allScreens = RallyScreen.values().toList()
val selectedScreen = allScreens.random() //pick a random screen name
val anotherScreen = allScreens.filterNot { it == selectedScreen }.random() //pick a random screen excluding selectedScreen
var currentScreen by mutableStateOf(selectedScreen)
composeTestRule.setContent {
RallyTopAppBar(
allScreens = allScreens,
onTabSelected = {
currentScreen = it
},
currentScreen = currentScreen
)
}
composeTestRule.onNodeWithContentDescription(anotherScreen.name)
.performClick()
.assertIsSelected()
}
This is weird - I'm doing the following:
val allScreens = RallyScreen.entries //mock the screens
var selectedScreen: RallyScreen? = null
composeTestRule.setContent {
RallyTheme {
RallyTopAppBar(
allScreens = allScreens,
onTabSelected = { screen -> selectedScreen = screen},
currentScreen = RallyScreen.Accounts
)
}
}
composeTestRule.onNodeWithContentDescription(RallyScreen.Overview.name).performClick()
composeTestRule.onNodeWithContentDescription(RallyScreen.Overview.name).assertIsSelected()
assertEquals(RallyScreen.Overview, selectedScreen)
assertEquals is true, but the assertIsSelected fails.