About *testing*: how can I verify that a `Text()` ...
# compose
g
About testing: how can I verify that a
Text()
node has text with a certain style, e.g. bold? Is there such a matcher/assertion available? The testing cheat sheet doesn't seem to include something similar.
z
I’m not sure if there are higher level apis for this yet, but if you need to write your own assertion you could just read the
SemanticsProperties.Text
property which gives you a list of `AnnotatedString`s, and check those strings for the styles you expect. You can look at the implementation of the existing assertions, eg
assertTextContains
, as a starting point.
g
Thanks for your suggestion, @Zach Klippenstein (he/him) [MOD]! Unfortunately,
SemanticsProperties.Text
's
AnnotatedString
s have no spanStyles nor paragraphStyles (both are empty lists). However, the node also contained a
SemanticsActions.GetTextLayoutResult
property, which is a lambda whose enclosing class is a
TextController
which contains a
TextState
which contains a
TextDelegate
which contains a
TextStyle
which contains the desired
FontWeight
. Since half of those classes are internal, I had to do a fair amount of reflection to come up with this matcher:
Copy code
@OptIn(InternalFoundationTextApi::class)
fun hasFontWeight(
    weight: FontWeight,
): SemanticsMatcher {
    val propertyName = SemanticsActions.GetTextLayoutResult
    return SemanticsMatcher(
        "$propertyName contains $weight text"
    ) {
        val actualWeight = it.config.getOrNull(propertyName)
            ?.action
            ?.javaPrivateField("this$0")
            ?.javaPrivateField("state")
            ?.javaPrivateField("textDelegate")
            ?.run { this as TextDelegate }
            ?.style
            ?.fontWeight
        actualWeight == weight
    }
}
where
Copy code
fun Any.javaPrivateField(fieldName: String): Any? =
    this.javaClass
        .getDeclaredField(fieldName)
        .also { it.isAccessible = true }
        .get(this)
I am certain this is NOT the proper way to do this, but until the framework supports this officially I guess it will have to do.
z
Huh, I thought the whole point of exposing annotated strings in the semantics api was to allow access to spans - eg TtsSpan or whatever it’s called in compose is purely for accessibility. Maybe it’s just not implemented yet? I would file a bug.
👍 1
(please post the bug here if you file so i can star/follow it!)
g
@Zach Klippenstein (he/him) [MOD] https://issuetracker.google.com/issues/195668156
1
Can't say that I am thrilled with the solution proposed in the issue, especially since the resolved text style differs slightly from the text style I set in the code, but it's an improvement over my reflection-heavy solution.