Flutter: Get a PopupMenuButton's PopupMenuItem text in unit tests


I have a PaginatedDataTable that has a DataCell with a PopupMenuButton. WidgetTester can find each DataCell no problem but I cant seem to reference the PopupMenuButton’s items to try to select one.

How can i get a PopupMenuButton’s PopupMenuItem text in unit tests? Am I using await tester.pump(); correctly to allow the menu to appear?

Here is how im doing it now:

expect(find.byIcon(Icons.more_horiz).first, findsOneWidget); // works!

await tester.tap(find.byIcon(Icons.more_horiz).first);
await tester.pump();

var byType = find.text('Quote');
expect(byType, findsOneWidget); // fails!

Which fails with

zero widgets with text "Quote" (ignoring offstage widgets)...

And here is the DataCell markup

new DataCell(...),
new DataCell(new PopupMenuButton<quickActions>(
      icon: new Icon(Icons.more_horiz),
      onSelected: (quickActions action) {
      itemBuilder: (BuildContext context) => <PopupMenuEntry<quickActions>>[
            new PopupMenuItem<quickActions>(
              value: quickActions.edit,
              child: new Text('Edit'),
            new PopupMenuItem<quickActions>(
              value: quickActions.remove,
              child: new Text('Remove'),
            new PopupMenuItem<quickActions>(
              value: quickActions.reschedule,
              child: new Text('Re-schedule'),
            new PopupMenuItem<quickActions>(
              value: quickActions.bid,
              child: new Text('Quote'),


I know this is an old question but I found myself in this same problem and I have solved it.

For those having this same problem, I am posting my answer. My test is a little different than yours.

What is Pump

Triggers a frame after duration amount of time.

This makes the framework act as if the application had janked (missed
frames) for duration amount of time, and then received a v-sync signal
to paint the application.

What is PumpAndSettle

Repeatedly calls pump with the given duration
until there are no longer any frames scheduled. This will call pump at
least once, even if no frames are scheduled when the function is
called, to flush any pending microtasks which may themselves schedule
a frame.

//My Code
//await tester.tap(find.byIcon(Icons.text_fields));
//await tester.pumpAndSettle();

//await tester.tap(find.text(expectedFontSize + ' px'));
//expect(fontSize, expectedFontSize);

//call again if you want to do testing again or something again 
//await tester.pumpAndSettle();

 var mainButton = find.byIcon(Icons.more_horiz); 
 expect(mainButton, findsOneWidget);

 await tester.tap(mainButton);
 await tester.pumpAndSettle();

 var childButton = find.text('Quote');
 expect(childButton , findsOneWidget); //

For me the code worked only after calling PumpAndSettle Method

Answered By – Hey24sheep

Answer Checked By – Robin (FlutterFixes Admin)

Leave a Reply

Your email address will not be published.