https://kotlinlang.org logo
#compose
Title
# compose
j

Jan Skrasek

03/14/2022, 4:25 PM
I have a high-level TextField component:
Copy code
fun OurTextField(modifier: Modifier) {
   Column(modifier) {
     Label()
     TextField()
     ErrorMessage()
   }
}
So when our devs use it in UI tests, they pass testTag that is in the Column's modifier. However, that breaks the bahavior, especially for setting a value to text field. (There is no SetText on Column). What is the best solution for those high-level components: • merge tree on column (something which will work nicely for SetText, worse for other texts; alternatively reexpose them - Text for input, new semantics for Label and Error) • exposing tag names which ui tests may reused to specify "child" of the OurTextField • do nothing and let ui tests to use onChildAt(1) to get access to TextField • some other approach?
i

ildar.i [Android]

03/14/2022, 5:34 PM
What we do is exposing a state object (actually, the whole list of them) and then mapping it to composable. that way you can set any parameter you want
Copy code
@Composable
fun CommonTextDisplay(item: CommonText, modifier: Modifier = Modifier) {
    Row(
        modifier then Modifier.fillMaxWidth(),
        if (item.gravityStart) Arrangement.Start else Arrangement.Center,
    ) {
        Text(
            item.text,
            Modifier.padding(vertical = 8.dp),
            CoreColors.textPrimary,
            item.textSize.sp,
            textAlign = if (item.gravityStart) TextAlign.Start else TextAlign.Center,
        )
    }
}
a

allan.conda

03/14/2022, 6:30 PM
Hoist the composable components. Define the expected composable in the param comments. That's how material Compose solve it
Copy code
fun OurTextField(
  modifier: Modifier,
  label: @Composable () -> Unit = { Label() }
  textField: @Composable () -> Unit = { TextField() }
  errorMessage: @Composable () -> Unit = { ErrorMessage() }
) {
   Column(modifier) {
     label()
     textField()
     errorMessage()
   }
}