Good afternoon all. I'm working in a hybrid xml v...
# compose
m
Good afternoon all. I'm working in a hybrid xml view / compose environment and we wrote some wrappers for our compose buttons so that they can be used in an xml layout. The one remaining issue we're having is that espresso matchers like
withText
do not work because we're not extending TextView. I can write explicit matchers on properties of that wrapper, but i'd like to be able to use the root view and execute any composed based matcher on that. Anyone have any idea if this is possible? Something like:
Copy code
onView(
  allOf(
    withId(R.id.button),
    withComposeText(buttonText)
  )
)
And someone internally look at the compose tree for that view and execute the text assertion there.
e
do you really need the view ID? you can match compose tags and text
m
Personally, i would love to just rid of all the xml view stuff, and live entirely in compose land. But i can't (for now), so we're stuck with these compat views. Sure we could this in multiple statements:
Copy code
onView(withId(R.id.button)).check(isDisplayed())
composeTestRule.onNodeWithTag("button").assertIsDisplayed()
but it's not really ensuring they're the same element. Honestly, for now i think i'm going to write some custom matchers. All the properties are controlled via attributes on the subclass of AbstractComposeView, so i can write matchers for those attributes that operate only on that subclass. Similar to what withText does for TextView.
I was just hoping to be able do some more complex stuff on the compose tree within an espresso type view matcher
j
Why do you need a hybrid environment? Why not just build your new screens in compose and wrap them in a ComposeView so that you can use them from XML?
m
One of the big reasons is that we have our own design system with custom styled controls (buttons, switches, etc...). We started with XML view based controls that are implemented as custom views since the underlying material controls couldn't be 100% styled the way our design system specified them. When compose was released, we built things from the ground up in compose, but the xml stuff is still there. We're a large dev org with a lot of product development and not all our teams have bandwidth to go rewrite things in compose. But over time, our capacity to support both compose and xml views has dwindled. So we built a few view wrappers that render themselves using compose as a bridge for teams to be able to visually get the proper changes, but not have to completely rewrite their screens in compose.
I sort of gave up on this idea anyway (mixing compose and view matchers), and i wrote a few custom matchers for what the particular team needed, and i added the ability to specify a test tag (falls back to the stringified view id) on these views that will be applied to the composable, and they can use createEmptyComposeRule() and do what they need to update their tests.
e
my team is also somewhat undecided over at what point do we switch existing screens from "view-based layout with ComposeView" to "compose-based layout with AndroidView", but we tend to avoid wrapping individual Compose components and instead migrate larger chunks at a time
m
I would have preferred to migrate the entire screens, but i don't own these screens or the mass of espresso and unit tests written around them.
Our disclaimer is "sure you can use this, but we recommend rewriting your screen in compose if at all possible"