Hi, is there a way to use composeTestRule to find ...
# compose
y
Hi, is there a way to use composeTestRule to find a AndroidView wrapped Button and click on it? It appears that
composeTestRule.onNodeWithText(xxx).performClick()
doesn't work for an AndroidView wrapped Button I also tried using a Modifier.testTag for the AndroidView wrapped Button, it can find the Button but won't be clickable
d
Can you find the View with Espresso? Like you would typically find a View using
onView
?
y
Copy code
Espresso.onView(ViewMatchers.withText(xxx)).perform(click())
Unfortunately Espresso doesn't work for both pure Compose case or AndroidView wrapped Button case
d
Hmm.
My initial thought is to make the Composable using the AndroidView Composable use a
Modifier.clickable
.
y
emm the value of using the AndroidView wrapped Composable is to reuse the previous XML based Button set up?
y
otherwise the pure compose version will be better 😛
d
This doc says that
Copy code
Espresso.onView(ViewMatchers.withText(xxx)).perform(click())
Should work.
What does
composeTestRule.onNodeWithTestTag(YOUR_TEST_TAG).printToString()
produce?
y
if use the AndroidView wrapped component:
|-Node #9 at (l=136.0, t=57.0, r=184.0, b=116.0)px, Tag: 'xxx'
if pure compose:
|-Node #9 at (l=136.0, t=57.0, r=200.0, b=114.0)px Role = 'Button' Focused = 'false' Actions = [OnClick, RequestFocus] MergeDescendants = 'true' MergeDescendants = 'true' |-Node #11 at (l=166.0, t=65.0, r=170.0, b=106.0)px Text = '[xxx]' Actions = [GetTextLayoutResult]
I was scanning the way how we pass the text and clickListener to the AndroidWrappedButton right now
AndroidWrappedButton() {
it.text = "xxx"
it.setOnClickListener { onClick.invoke() }
}
wonder if use Modifier to input the text and click event would work🤔, as you suggested
d
Try it?
Like, do you have to click the View, or can the whole Composable be clickable?
y
trying now : ) It is ok to pass in the clickable how do we use modifier to pass in text?👀 I saw this:
Copy code
Modifier.semantics { text = ... }
and it requires a annotated string instead of a string
String.toAnnotatedString can not work because @Composable invocations can only happen from the context of a @Composable function
d
Node #9
Should be clickable, no?
y
> Node #9
Should be clickable, no?
AndroidView wrapped component, no so it can be "clicked" but the click event is not triggered 😕
Thank you for suggestions! I will try some simple example when I get a chance I figured can use
Copy code
.semantics { text = AnnotatedString("xxx") })
d
Can you propagate the click from the Composable to the View manually?
y
@dewildte This simple example illustrate the issue. func testAndroidWrappedButton won't print "onClick called" from the lambda
val onClick
, no matter use modifier.clickable or it.setOnClickListener
Copy code
@Composable
    fun AndroidWrappedButton(
        modifier: Modifier = Modifier,
        setup: (Button) -> Unit = {}
    ) {
        AndroidView(modifier = modifier, factory = { context -> Button(context) }, update = setup)
    }

    @Test
    fun testAndroidWrappedButton() {
        val onClick: () -> Unit = {
            println("onClick called")
        }
        composeTestRule.setContent {
            AndroidWrappedButton(
                Modifier
                    .semantics { text = AnnotatedString("AndroidButton") }
                    .clickable { onClick }
            ) {
//                it.setOnClickListener {
//                    onClick
//                }
            }
        }
        val androidButtonViewText = composeTestRule.onNodeWithText("AndroidButton")
        androidButtonViewText.assertExists()
        androidButtonViewText.performClick()
    }
And another find is clickable is not working at all but setOnClickListener will work if print directly in it. The following test will only print setOnClickListener
Copy code
@Test
fun testAndroidWrappedButton() {
    val onClick: () -> Unit = {
        println("onClick called")
    }
    composeTestRule.setContent {
        AndroidWrappedButton(
            Modifier
                .semantics { text = AnnotatedString("AndroidButton") }
                .clickable {
                    println("print clickable")
                    onClick
                }
        ) {
            it.setOnClickListener {
                println("print setOnClickListener")
                onClick
            }
        }
    }
    val androidButtonViewText = composeTestRule.onNodeWithText("AndroidButton")
    androidButtonViewText.assertExists()
    androidButtonViewText.performClick()
}
137 Views