I'm having an issue with ModalBottomSheet that I d...
# compose
m
I'm having an issue with ModalBottomSheet that I don't quite understand. It's happening with an upgrade from compose bom 2024.06.00 to 2024.11.00. I have this function:
Copy code
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ModalBottomSheetExample(
    visible: Boolean,
    onVisibleChange: (Boolean) -> Unit
) {
    if (visible) {
        ModalBottomSheet(
            onDismissRequest = {
                onVisibleChange(false)
            },
            dragHandle = {
                Row {
                    IconButton(onClick = {
                        onVisibleChange(false)
                    }) {
                        Icon(imageVector = Icons.Default.Close, contentDescription = "close")
                    }
                }
            }
        ) {
            Text("Content")
        }
    }
}
If i put this in a preview function, everything works just fine. However, when i try to use this in a compose unit test, the "onClick" of the IconButton is never triggered, and as a result, the "onVisibleChange" function is never called and i can't get the dialog to go away
Test code for reference:
Copy code
@RunWith(AndroidJUnit4::class)
class ModalBottomSheetTest {
    @OptIn(ExperimentalTestApi::class)
    @Test
    fun x() {
        runComposeUiTest {
            var visible by mutableStateOf(true)
            val mockOnClose = mock<() -> Unit>()

            setContent {
                ModalBottomSheetExample(
                    visible = visible,
                    onVisibleChange = {
                        mockOnClose()
                        visible = it
                    }
                )
            }

            onNodeWithContentDescription("close")
                .assertExists()
                .performClick()

            waitForIdle()

            verify(mockOnClose)()
        }
    }
}
w
You should wrap your
mutableStateOf(true)
in a
remember { ... }
sorry 1
🚫 1
m
@Wout Werkman This is a unit test, and remember isn't really needed because the state doesn't live inside the composition. I tend to create state outside of the composition in these cases so i can check that they are updated as i excercise my test. that condition isn't in here, but it wll be in the final test. I was trying to boil down my test to as simple as i could using the stock control.
Also, i did try that and it doesn't help. The bottom line is that even when i debug the test, i put a breakpoint in the "onClick" of the IconButton, and the breakpoint is never hit.
It's the same for a standard Button as well, never drops into the onClick callback
I have a fully standalone test to illustrate the issue:
Copy code
@Test
    fun modalDialogClickIssue() {
        runComposeUiTest {
            setContent {
                var visible by remember { mutableStateOf(true) }
                if (visible) {
                    ModalBottomSheet(
                        onDismissRequest = {
                            visible = false
                        },
                    ) {
                        Button(
                            modifier = Modifier.testTag("hide"),
                            onClick = {
                                visible = false

                            }
                        ) {
                            Text("Hide")
                        }
                    }
                }
            }

            waitUntilNodeCount(isDialog(), 1)

            // This does not trigger the onClick callbacks of the button
            onNodeWithTag("hide", useUnmergedTree = true)
                .assertExists()
                .performClick()

            // This works though
            /*
            onNode(keyIsDefined(SemanticsActions.Dismiss))
                .performSemanticsAction(SemanticsActions.Dismiss)
             */

            waitUntilNodeCount(isDialog(), 0)

        }
    }
I also have submitted a bug ticket as well. https://issuetracker.google.com/issues/382094416
@Ian Lake Sorry for the direct tag, but i'm wondering if this is a known issue