How to find the `text` property of a Widget during testing in Flutter?

Viewed 7142

I have a piece of code that creates a Table of Text widgets, like this:

return Table(
  defaultColumnWidth: FixedColumnWidth(120.0),
  children: <TableRow>[
    TableRow(
      children: <Widget>[Text('toffee'), Text('potato')],
    ),
    TableRow(
      children: <Widget>[Text('cheese'), Text('pie')],
    ),
  ],
);

I want to test that the first item in the Table is indeed the word 'toffee'. I set up my test and get to this part:

var firstCell = find
      .descendant(
        of: find.byType(Table),
        matching: find.byType(Text),
      )
      .evaluate()
      .toList()[0].widget;

  expect(firstCell, 'toffee');

This definitely doesn't work because firstCell is of type Widget, which is not equal to the String toffee.

I only see a toString() function, like this:

'Text("toffee", inherit: true, color: Color(0xff616161), size: 16.0,
 textAlign: left)'

How do I extract the text property to get the word toffee?

Right now it seems like all I can do is check that the .toString().contains('toffee') which isn't ideal.

4 Answers

Rémi's example doesn't quite work - it may have worked at the time he answered, but at this time calling whereType<Text>() will always return an empty Iterable because evaluate() returns Iterable<Element>, not Iterable<Widget>. You can however get an Element's Widget by calling .widget on it, so the following code should work:

Text firstText = find
    .descendant(
      of: find.byType(Table),
      matching: find.byType(Text),
    )
    .evaluate()
    .first
    .widget;

expect(firstText.data, 'toffee');

The OP was very close to having working code - there were only 2 minor issues:

  • By using var instead of Text, the type of the variable was Widget
  • The Widget was compared to a String - this could never return true - the intent was to compare a property of the Widget to the String - in the case of a Text, the String it displays is obtained by calling .data on the Text

Edit:

The WidgetTester now has utility functions for retrieving widgets: widget(Finder), widgetList(Finder), firstWidget(Finder) and allWidgets. So for the OP's use case you would be using firstWidget like so:

Text firstText = tester.firstWidget(
    find.descendant(
      of: find.byType(Table),
      matching: find.byType(Text),
    ));

expect(firstText.data, 'toffee');

You can cast your firstCell to Text.

var firstCell = find
    .descendant(
      of: find.byType(Table),
      matching: find.byType(Text),
    )
    .evaluate()
    .whereType<Text>()
    .first;

Then test firstCell.data

expect(firstCell.data, 'toffee');

Find by text ?

expect(find.text('toffee'), findsOneWidget);

You can use short form for any type of widgets:

expect(
     (find.byType(InAppWebView).evaluate().single.widget as InAppWebView)
          .initialUrl,
          'https://www.google.com/');
Related