最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

unit testing - Verify in android ui test that a text annotated with annotationlink.clickable is clicked - Stack Overflow

programmeradmin1浏览0评论

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 badges
Add a comment  | 

1 Answer 1

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,
        )
    }
}

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论