https://kotlinlang.org logo
#compose-desktop
Title
# compose-desktop
l

Lindsay Peters

12/12/2023, 5:45 AM
We are migrating a large Swing application to compose desktop and are intending to embed compose components within the existing Swing UI, e.g. a Composable component with TextFields into a Swing container like JPanel. We are using a ComposePanel to do this, and that works fine. The individual compose components can be unit-tested OK with ComposeTestRule. However, we need higher level tests of the application containing both the Swing components and the new components which means sending keyboard & mouse input to the "embedded" compose components and also reading their state. Does anyone know a way to do this? Ideally we'd like the matchers and assertions provided by ComposeTestRule, but which would be available even if the composable is contained in a ComposePanel or ComposeWindow.
a

Alexander Maryanovsky

12/12/2023, 10:52 AM
I don’t think that’s possible. In a test the compose content isn’t put in a real window, so you can’t have Swing there.
You could maybe do something via the accessibility API. I know there are testing frameworks which utilize that to find, affect and check the state of UI elements.
But I’m not 100% sure that accessibility will work correctly when mixing Swing and Compose.
l

Lindsay Peters

12/13/2023, 5:47 AM
Thanks very much for your response. However the examples I've seen using the accessibility API either all involve ComposeTestRule or are not applicable for Desktop. Below is a simple example of what we are trying to achieve. The state of MyTextField can be easily unit-tested using ComposeTestRule:
@get:Rule
val composeTestRule = createComposeRule() @Test fun `text field should be initialised to bar and also editable`() { with (composeTestRule) { setContent { MyTextField() } onNodeWithText("bar").assertExists() onNodeWithTag("myTextField").performTextInput("foo ") onNodeWithText("foo bar").assertExists() } }
@Composable
@Preview fun MyTextField() { var text by remember { mutableStateOf("bar") } MaterialTheme { TextField( value =text, onValueChange = { changedText -> text = changedText println("changedText = ${changedText}") }, modifier = Modifier.testTag("myTextField") ) } } but when it's embedded in a JFrame using ComposePanel, how does one programatically perform the same sort of interactions and checks?
fun main() {
SwingUtilities.invokeLater { val composePanel = ComposePanel().apply { setContent { MyTextField() } } with(JFrame("compose test")) { add(composePanel) setSize(400, 200) isVisible = true } } }
8 Views