Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TestingCodelab] (Optional Exercise): How to access state in RallyApp #238

Open
ktprograms opened this issue Feb 8, 2022 · 6 comments
Open
Assignees

Comments

@ktprograms
Copy link

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?

@gagandeep3458
Copy link

gagandeep3458 commented Apr 20, 2022

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)
}

@wnduqrla
Copy link

wnduqrla commented Oct 15, 2022

@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()

@vkatzyn
Copy link

vkatzyn commented Dec 1, 2022

@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()
}

@machado001
Copy link

machado001 commented Jul 10, 2023

@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()
    }

@ambageo
Copy link

ambageo commented Apr 22, 2024

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.

@BojanLozanovski
Copy link

@ambageo ,
I think that assertIsSelected fails for you, because you are not managing the state.
You have to either:

  1. call RallyApp(), and RallyApp() will manage the correct state on its own for current screen.
  2. or, if you call RallyTopAppBar() directly, you are responsible for managing the state. So, for currentScreen, you shouldn't pass currentScreen = RallyScreen.Accounts, rather, you should manage the state and pass the value of the state.

I might be wrong, but, this is my first guess.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants