S.D.
S.D.

Reputation: 5857

Testing text in TextSpan

If we have a TextSpan that is a child of a RichText widget, how would you test the text content.

new TextSpan(
  text: 'Hello world!',
  style: new TextStyle(color: Colors.black),
)

In your tests, with a Text widget, you can use expect(find.text('Hello world!'), findsOneWidget), but this doesn't work if you have a TextSpan.

expect(find.byType(TextSpan), findsOneWidget) also does not find any widgets of type TextSpan.

Upvotes: 21

Views: 6039

Answers (6)

Bienvenido David
Bienvenido David

Reputation: 4348

You can find the RichText widget instead. Here's the find.byWidgetPredicate call.

expect(find.byWidgetPredicate((widget) => fromRichTextToPlainText(widget) == 'Hello world!'), findsOneWidget);

Here's the fromRichTextToPlainText helper function. Pass it the RichText widget, it will return the plain text for all the underlying TextSpans.

String? fromRichTextToPlainText(final Widget widget) {
  if (widget is RichText) {
    if (widget.text is TextSpan) {
      final buffer = StringBuffer();
      (widget.text as TextSpan).computeToPlainText(buffer);
      return buffer.toString();
    }
  }
  return null;
}

Upvotes: 4

David Schneider
David Schneider

Reputation: 609

In case someone needs to not just find the widget, but also tap on it:

Finding a TextSpan to tap on with Flutter tests

Upvotes: 0

Sathish
Sathish

Reputation: 136

It can be achieved by using byWidgetPredicate

expect(
    find.byWidgetPredicate((widget) =>
        widget is RichText &&
        widget.text.toPlainText() ==
            'Hello World!.'),
    findsOneWidget);

Upvotes: 9

jignesh.world
jignesh.world

Reputation: 1446

From above snippets - I found below bit customised version helpful to me..

String? fromRichTextToPlainText(final Widget widget) {
  if (widget is RichText) {
    return widget.text.toPlainText();
  }
  return null;
}
expect(
          find.byWidgetPredicate(
              (widget) => fromRichTextToPlainText(widget) == 'My Rich Text'),
          findsOneWidget);

Upvotes: 0

sceee
sceee

Reputation: 2163

In addition to Rémi's answer, here is the way to find the text from a RichText. You set the key to the RichText and then you can do:

Finder widgetFinder = find.byKey(key);

Finder rtFinder =
   find.descendant(of: widgetFinder, matching: find.byType(RichText));
RichText richText = rtFinder.evaluate().first.widget as RichText;
String richTextText = richText.text.toPlainText();

print('Text from Text widget: $richTextText');
expect(richTextText, 'This is my text',
   reason: 'Text from found text widget do not match');

Upvotes: 9

Rémi Rousselet
Rémi Rousselet

Reputation: 276957

That's not possible. As TextSpan doesn't actually render anything. It is data information used by another object to actually render something.

What you can do instead is to find the widget to which you pass your TextSpan. And then verify it's correct

Upvotes: 10

Related Questions