I have a composable Text()
inside a detail screen, which is containing an annotated String, which includes a fragment where I indicate that it must be clicked to execute an internal action within the same buildAnnotatedString screen, like this:
val context = LocalContext.current
buildAnnotatedString {
append("Check the ")
withLink(
LinkAnnotation.Clickable(
tag = "read_terms_and_conditions",
styles = TextLinkStyles(
SpanStyle(
color = MaterialTheme.colorScheme.secondary,
fontWeight = FontWeight.Bold,
textDecoration = TextDecoration.Underline,
)
),
linkInteractionListener = {
onClicked(
context.getString(R.string.terms_conditions_url),
)
},
),
) {
append("Terms and Conditions")
}
append(".")
}.also {
Text(
modifier = Modifier.fillMaxWidth().padding(top = 20.dp),
text = it,
textAlign = TextAlign.Start,
)
}
Question: How do I verify the click on the 'Terms and Conditions' text?
Yes, there is a callback for when the text fragment is clicked onClicked: (String) -> Unit, which is executed using a string as a parameter. However, for some reason, when implementing the Android UI tests and using this code to locate the text (the fragment annotated as AnnotationLink.Clickable), the test doesn't verify the visibility of the text or the click on the text:
var termsConditionsUrl = ""
setContent { InformativeText(onClicked= { termsConditionsUrl = it })}
...
onNodeWithText("Terms and Conditions", substring = true).assertIsDisplayed().performClick()
assertThat(termsConditionsUrl).isNotEmpty()
Any help is appreciated :)
I have a composable Text()
inside a detail screen, which is containing an annotated String, which includes a fragment where I indicate that it must be clicked to execute an internal action within the same buildAnnotatedString screen, like this:
val context = LocalContext.current
buildAnnotatedString {
append("Check the ")
withLink(
LinkAnnotation.Clickable(
tag = "read_terms_and_conditions",
styles = TextLinkStyles(
SpanStyle(
color = MaterialTheme.colorScheme.secondary,
fontWeight = FontWeight.Bold,
textDecoration = TextDecoration.Underline,
)
),
linkInteractionListener = {
onClicked(
context.getString(R.string.terms_conditions_url),
)
},
),
) {
append("Terms and Conditions")
}
append(".")
}.also {
Text(
modifier = Modifier.fillMaxWidth().padding(top = 20.dp),
text = it,
textAlign = TextAlign.Start,
)
}
Question: How do I verify the click on the 'Terms and Conditions' text?
Yes, there is a callback for when the text fragment is clicked onClicked: (String) -> Unit, which is executed using a string as a parameter. However, for some reason, when implementing the Android UI tests and using this code to locate the text (the fragment annotated as AnnotationLink.Clickable), the test doesn't verify the visibility of the text or the click on the text:
var termsConditionsUrl = ""
setContent { InformativeText(onClicked= { termsConditionsUrl = it })}
...
onNodeWithText("Terms and Conditions", substring = true).assertIsDisplayed().performClick()
assertThat(termsConditionsUrl).isNotEmpty()
Any help is appreciated :)
Share Improve this question asked Mar 13 at 21:27 Marlon LópezMarlon López 4909 silver badges24 bronze badges1 Answer
Reset to default 0.performClick() isn't clicking the annotated text. Perform click is just
.performTouchInput {
down(center)
move()
up()
}
which can make your test flakey depending on the size of your layout and "center"'s value.
Instead you can calculate the hyperlink's location and perform a click yourself.
composeTestRule.onNodeWithText("Terms and Conditions", substring = true).apply {
val textLayoutResults = mutableListOf<TextLayoutResult>()
performSemanticsAction(SemanticsActions.GetTextLayoutResult) { getLayouts ->
getLayouts(textLayoutResults)
}
val layoutResult = textLayoutResults.find { textLayoutResult ->
textLayoutResult.layoutInput.text.text.contains("Terms and Conditions")
}!!
val link = layoutResult.layoutInput.text.getLinkAnnotations(
start = layoutResult.layoutInput.text.text.indexOf("Terms and Conditions"),
end = "Terms and Conditions".length,
).first()
val linkCenterCharBoundingBox = layoutResult.getBoundingBox(
offset = link.start + ((link.end - link.start) / 2),
)
performTouchInput {
click(
position = linkCenterCharBoundingBox.center,
)
}
}