@@ -64,6 +64,75 @@ void main() {
64
64
expect (find.text ('Next' ), findsOneWidget);
65
65
});
66
66
67
+ testWidgets ('PopupMenuButton calls onOpened callback when the menu is opened' , (WidgetTester tester) async {
68
+ int opens = 0 ;
69
+ late BuildContext popupContext;
70
+ final Key noItemsKey = UniqueKey ();
71
+ final Key noCallbackKey = UniqueKey ();
72
+ final Key withCallbackKey = UniqueKey ();
73
+
74
+ await tester.pumpWidget (
75
+ MaterialApp (
76
+ home: Material (
77
+ child: Column (
78
+ children: < Widget > [
79
+ PopupMenuButton <int >(
80
+ key: noItemsKey,
81
+ itemBuilder: (BuildContext context) {
82
+ return < PopupMenuEntry <int >> [];
83
+ },
84
+ onOpened: () => opens++ ,
85
+ ),
86
+ PopupMenuButton <int >(
87
+ key: noCallbackKey,
88
+ itemBuilder: (BuildContext context) {
89
+ popupContext = context;
90
+ return < PopupMenuEntry <int >> [
91
+ const PopupMenuItem <int >(
92
+ value: 1 ,
93
+ child: Text ('Tap me please!' ),
94
+ ),
95
+ ];
96
+ },
97
+ ),
98
+ PopupMenuButton <int >(
99
+ key: withCallbackKey,
100
+ itemBuilder: (BuildContext context) {
101
+ return < PopupMenuEntry <int >> [
102
+ const PopupMenuItem <int >(
103
+ value: 1 ,
104
+ child: Text ('Tap me, too!' ),
105
+ ),
106
+ ];
107
+ },
108
+ onOpened: () => opens++ ,
109
+ ),
110
+ ],
111
+ ),
112
+ ),
113
+ ),
114
+ );
115
+
116
+ // Make sure callback is not called when the menu is not shown
117
+ await tester.tap (find.byKey (noItemsKey));
118
+ await tester.pump ();
119
+ expect (opens, equals (0 ));
120
+
121
+ // Make sure everything works if no callback is provided
122
+ await tester.tap (find.byKey (noCallbackKey));
123
+ await tester.pump ();
124
+ expect (opens, equals (0 ));
125
+
126
+ // Close the opened menu
127
+ Navigator .of (popupContext).pop ();
128
+ await tester.pump ();
129
+
130
+ // Make sure callback is called when the button is tapped
131
+ await tester.tap (find.byKey (withCallbackKey));
132
+ await tester.pump ();
133
+ expect (opens, equals (1 ));
134
+ });
135
+
67
136
testWidgets ('PopupMenuButton calls onCanceled callback when an item is not selected' , (WidgetTester tester) async {
68
137
int cancels = 0 ;
69
138
late BuildContext popupContext;
@@ -130,9 +199,10 @@ void main() {
130
199
expect (cancels, equals (2 ));
131
200
});
132
201
133
- testWidgets ('disabled PopupMenuButton will not call itemBuilder, onSelected or onCanceled' , (WidgetTester tester) async {
202
+ testWidgets ('disabled PopupMenuButton will not call itemBuilder, onOpened, onSelected or onCanceled' , (WidgetTester tester) async {
134
203
final GlobalKey popupButtonKey = GlobalKey ();
135
204
bool itemBuilderCalled = false ;
205
+ bool onOpenedCalled = false ;
136
206
bool onSelectedCalled = false ;
137
207
bool onCanceledCalled = false ;
138
208
@@ -158,6 +228,7 @@ void main() {
158
228
),
159
229
];
160
230
},
231
+ onOpened: ()=> onOpenedCalled = true ,
161
232
onSelected: (int selected) => onSelectedCalled = true ,
162
233
onCanceled: () => onCanceledCalled = true ,
163
234
),
@@ -177,6 +248,7 @@ void main() {
177
248
await tester.tap (find.byKey (popupButtonKey));
178
249
await tester.pumpAndSettle ();
179
250
expect (itemBuilderCalled, isFalse);
251
+ expect (onOpenedCalled, isFalse);
180
252
expect (onSelectedCalled, isFalse);
181
253
182
254
// Try to bring up the popup menu and tap outside it to cancel the menu
@@ -185,6 +257,7 @@ void main() {
185
257
await tester.tapAt (Offset .zero);
186
258
await tester.pumpAndSettle ();
187
259
expect (itemBuilderCalled, isFalse);
260
+ expect (onOpenedCalled, isFalse);
188
261
expect (onCanceledCalled, isFalse);
189
262
190
263
// Test again, with directional navigation mode and after focusing the button.
@@ -198,6 +271,7 @@ void main() {
198
271
await tester.tap (find.byKey (popupButtonKey));
199
272
await tester.pumpAndSettle ();
200
273
expect (itemBuilderCalled, isFalse);
274
+ expect (onOpenedCalled, isFalse);
201
275
expect (onSelectedCalled, isFalse);
202
276
203
277
// Try to bring up the popup menu and tap outside it to cancel the menu
@@ -206,13 +280,15 @@ void main() {
206
280
await tester.tapAt (Offset .zero);
207
281
await tester.pumpAndSettle ();
208
282
expect (itemBuilderCalled, isFalse);
283
+ expect (onOpenedCalled, isFalse);
209
284
expect (onCanceledCalled, isFalse);
210
285
});
211
286
212
287
testWidgets ('disabled PopupMenuButton is not focusable' , (WidgetTester tester) async {
213
288
final Key popupButtonKey = UniqueKey ();
214
289
final GlobalKey childKey = GlobalKey ();
215
290
bool itemBuilderCalled = false ;
291
+ bool onOpenedCalled = false ;
216
292
bool onSelectedCalled = false ;
217
293
218
294
await tester.pumpWidget (
@@ -233,6 +309,7 @@ void main() {
233
309
),
234
310
];
235
311
},
312
+ onOpened: () => onOpenedCalled = true ,
236
313
onSelected: (int selected) => onSelectedCalled = true ,
237
314
),
238
315
],
@@ -245,6 +322,7 @@ void main() {
245
322
246
323
expect (Focus .of (childKey.currentContext! ).hasPrimaryFocus, isFalse);
247
324
expect (itemBuilderCalled, isFalse);
325
+ expect (onOpenedCalled, isFalse);
248
326
expect (onSelectedCalled, isFalse);
249
327
});
250
328
0 commit comments