@@ -48,8 +48,9 @@ void main() {
4848 );
4949 });
5050
51- testWidgets ('Can open and close search' , (WidgetTester tester) async {
51+ testWidgetsWithLeakTracking ('Can open and close search' , (WidgetTester tester) async {
5252 final _TestSearchDelegate delegate = _TestSearchDelegate ();
53+ addTearDown (() => delegate.dispose ());
5354 final List <String > selectedResults = < String > [];
5455
5556 await tester.pumpWidget (TestHomePage (
@@ -84,10 +85,11 @@ void main() {
8485 expect (selectedResults, < String > ['Result' ]);
8586 });
8687
87- testWidgets ('Can close search with system back button to return null' , (WidgetTester tester) async {
88+ testWidgetsWithLeakTracking ('Can close search with system back button to return null' , (WidgetTester tester) async {
8889 // regression test for https://github.com/flutter/flutter/issues/18145
8990
9091 final _TestSearchDelegate delegate = _TestSearchDelegate ();
92+ addTearDown (() => delegate.dispose ());
9193 final List <String ?> selectedResults = < String ? > [];
9294
9395 await tester.pumpWidget (TestHomePage (
@@ -130,9 +132,10 @@ void main() {
130132 expect (find.text ('Suggestions' ), findsOneWidget);
131133 });
132134
133- testWidgets ('Hint text color overridden' , (WidgetTester tester) async {
135+ testWidgetsWithLeakTracking ('Hint text color overridden' , (WidgetTester tester) async {
134136 const String searchHintText = 'Enter search terms' ;
135137 final _TestSearchDelegate delegate = _TestSearchDelegate (searchHint: searchHintText);
138+ addTearDown (() => delegate.dispose ());
136139
137140 await tester.pumpWidget (TestHomePage (
138141 delegate: delegate,
@@ -144,8 +147,9 @@ void main() {
144147 expect (hintText.style! .color, _TestSearchDelegate .hintTextColor);
145148 });
146149
147- testWidgets ('Requests suggestions' , (WidgetTester tester) async {
150+ testWidgetsWithLeakTracking ('Requests suggestions' , (WidgetTester tester) async {
148151 final _TestSearchDelegate delegate = _TestSearchDelegate ();
152+ addTearDown (() => delegate.dispose ());
149153
150154 await tester.pumpWidget (TestHomePage (
151155 delegate: delegate,
@@ -173,8 +177,9 @@ void main() {
173177 expect (delegate.queriesForResults, hasLength (0 ));
174178 });
175179
176- testWidgets ('Shows Results and closes search' , (WidgetTester tester) async {
180+ testWidgetsWithLeakTracking ('Shows Results and closes search' , (WidgetTester tester) async {
177181 final _TestSearchDelegate delegate = _TestSearchDelegate ();
182+ addTearDown (() => delegate.dispose ());
178183 final List <String > selectedResults = < String > [];
179184
180185 await tester.pumpWidget (TestHomePage (
@@ -209,8 +214,9 @@ void main() {
209214 expect (selectedResults, < String > ['Result' ]);
210215 });
211216
212- testWidgets ('Can switch between results and suggestions' , (WidgetTester tester) async {
217+ testWidgetsWithLeakTracking ('Can switch between results and suggestions' , (WidgetTester tester) async {
213218 final _TestSearchDelegate delegate = _TestSearchDelegate ();
219+ addTearDown (() => delegate.dispose ());
214220
215221 await tester.pumpWidget (TestHomePage (
216222 delegate: delegate,
@@ -279,8 +285,9 @@ void main() {
279285 expect (textField.focusNode! .hasFocus, isFalse);
280286 });
281287
282- testWidgets ('Fresh search always starts with empty query' , (WidgetTester tester) async {
288+ testWidgetsWithLeakTracking ('Fresh search always starts with empty query' , (WidgetTester tester) async {
283289 final _TestSearchDelegate delegate = _TestSearchDelegate ();
290+ addTearDown (() => delegate.dispose ());
284291
285292 await tester.pumpWidget (TestHomePage (
286293 delegate: delegate,
@@ -299,8 +306,9 @@ void main() {
299306 expect (delegate.query, '' );
300307 });
301308
302- testWidgets ('Initial queries are honored' , (WidgetTester tester) async {
309+ testWidgetsWithLeakTracking ('Initial queries are honored' , (WidgetTester tester) async {
303310 final _TestSearchDelegate delegate = _TestSearchDelegate ();
311+ addTearDown (() => delegate.dispose ());
304312
305313 expect (delegate.query, '' );
306314
@@ -315,8 +323,9 @@ void main() {
315323 expect (delegate.query, 'Foo' );
316324 });
317325
318- testWidgets ('Initial query null re-used previous query' , (WidgetTester tester) async {
326+ testWidgetsWithLeakTracking ('Initial query null re-used previous query' , (WidgetTester tester) async {
319327 final _TestSearchDelegate delegate = _TestSearchDelegate ();
328+ addTearDown (() => delegate.dispose ());
320329
321330 delegate.query = 'Foo' ;
322331
@@ -330,8 +339,9 @@ void main() {
330339 expect (delegate.query, 'Foo' );
331340 });
332341
333- testWidgets ('Changing query shows up in search field' , (WidgetTester tester) async {
342+ testWidgetsWithLeakTracking ('Changing query shows up in search field' , (WidgetTester tester) async {
334343 final _TestSearchDelegate delegate = _TestSearchDelegate ();
344+ addTearDown (() => delegate.dispose ());
335345
336346 await tester.pumpWidget (TestHomePage (
337347 delegate: delegate,
@@ -351,8 +361,9 @@ void main() {
351361 expect (find.text ('Bar' ), findsOneWidget);
352362 });
353363
354- testWidgets ('transitionAnimation runs while search fades in/out' , (WidgetTester tester) async {
364+ testWidgetsWithLeakTracking ('transitionAnimation runs while search fades in/out' , (WidgetTester tester) async {
355365 final _TestSearchDelegate delegate = _TestSearchDelegate ();
366+ addTearDown (() => delegate.dispose ());
356367
357368 await tester.pumpWidget (TestHomePage (
358369 delegate: delegate,
@@ -379,12 +390,13 @@ void main() {
379390 expect (delegate.transitionAnimation.status, AnimationStatus .dismissed);
380391 });
381392
382- testWidgets ('Closing nested search returns to search' , (WidgetTester tester) async {
393+ testWidgetsWithLeakTracking ('Closing nested search returns to search' , (WidgetTester tester) async {
383394 final List <String ?> nestedSearchResults = < String ? > [];
384395 final _TestSearchDelegate nestedSearchDelegate = _TestSearchDelegate (
385396 suggestions: 'Nested Suggestions' ,
386397 result: 'Nested Result' ,
387398 );
399+ addTearDown (nestedSearchDelegate.dispose);
388400
389401 final List <String > selectedResults = < String > [];
390402 final _TestSearchDelegate delegate = _TestSearchDelegate (
@@ -406,6 +418,7 @@ void main() {
406418 ),
407419 ],
408420 );
421+ addTearDown (() => delegate.dispose ());
409422
410423 await tester.pumpWidget (TestHomePage (
411424 delegate: delegate,
@@ -443,8 +456,9 @@ void main() {
443456 expect (selectedResults, < String > ['Result' ]);
444457 });
445458
446- testWidgets ('Closing search with nested search shown goes back to underlying route' , (WidgetTester tester) async {
459+ testWidgetsWithLeakTracking ('Closing search with nested search shown goes back to underlying route' , (WidgetTester tester) async {
447460 late _TestSearchDelegate delegate;
461+ addTearDown (() => delegate.dispose ());
448462 final List <String ?> nestedSearchResults = < String ? > [];
449463 final _TestSearchDelegate nestedSearchDelegate = _TestSearchDelegate (
450464 suggestions: 'Nested Suggestions' ,
@@ -463,6 +477,7 @@ void main() {
463477 ),
464478 ],
465479 );
480+ addTearDown (nestedSearchDelegate.dispose);
466481
467482 final List <String > selectedResults = < String > [];
468483 delegate = _TestSearchDelegate (
@@ -515,11 +530,12 @@ void main() {
515530 expect (selectedResults, < String > ['Result Foo' ]);
516531 });
517532
518- testWidgets ('Custom searchFieldLabel value' , (WidgetTester tester) async {
533+ testWidgetsWithLeakTracking ('Custom searchFieldLabel value' , (WidgetTester tester) async {
519534 const String searchHint = 'custom search hint' ;
520535 final String defaultSearchHint = const DefaultMaterialLocalizations ().searchFieldLabel;
521536
522537 final _TestSearchDelegate delegate = _TestSearchDelegate (searchHint: searchHint);
538+ addTearDown (() => delegate.dispose ());
523539
524540 await tester.pumpWidget (TestHomePage (
525541 delegate: delegate,
@@ -531,10 +547,11 @@ void main() {
531547 expect (find.text (defaultSearchHint), findsNothing);
532548 });
533549
534- testWidgets ('Default searchFieldLabel is used when it is set to null' , (WidgetTester tester) async {
550+ testWidgetsWithLeakTracking ('Default searchFieldLabel is used when it is set to null' , (WidgetTester tester) async {
535551 final String searchHint = const DefaultMaterialLocalizations ().searchFieldLabel;
536552
537553 final _TestSearchDelegate delegate = _TestSearchDelegate ();
554+ addTearDown (() => delegate.dispose ());
538555
539556 await tester.pumpWidget (TestHomePage (
540557 delegate: delegate,
@@ -545,11 +562,12 @@ void main() {
545562 expect (find.text (searchHint), findsOneWidget);
546563 });
547564
548- testWidgets ('Custom searchFieldStyle value' , (WidgetTester tester) async {
565+ testWidgetsWithLeakTracking ('Custom searchFieldStyle value' , (WidgetTester tester) async {
549566 const String searchHintText = 'Enter search terms' ;
550567 const TextStyle searchFieldStyle = TextStyle (color: Colors .red, fontSize: 3 );
551568
552569 final _TestSearchDelegate delegate = _TestSearchDelegate (searchHint: searchHintText, searchFieldStyle: searchFieldStyle);
570+ addTearDown (() => delegate.dispose ());
553571
554572 await tester.pumpWidget (TestHomePage (delegate: delegate));
555573 await tester.tap (find.byTooltip ('Search' ));
@@ -565,8 +583,9 @@ void main() {
565583
566584 });
567585
568- testWidgets ('keyboard show search button by default' , (WidgetTester tester) async {
586+ testWidgetsWithLeakTracking ('keyboard show search button by default' , (WidgetTester tester) async {
569587 final _TestSearchDelegate delegate = _TestSearchDelegate ();
588+ addTearDown (() => delegate.dispose ());
570589
571590 await tester.pumpWidget (TestHomePage (
572591 delegate: delegate,
@@ -579,8 +598,9 @@ void main() {
579598 expect (tester.testTextInput.setClientArgs! ['inputAction' ], TextInputAction .search.toString ());
580599 });
581600
582- testWidgets ('Custom textInputAction results in keyboard with corresponding button' , (WidgetTester tester) async {
601+ testWidgetsWithLeakTracking ('Custom textInputAction results in keyboard with corresponding button' , (WidgetTester tester) async {
583602 final _TestSearchDelegate delegate = _TestSearchDelegate (textInputAction: TextInputAction .done);
603+ addTearDown (() => delegate.dispose ());
584604
585605 await tester.pumpWidget (TestHomePage (
586606 delegate: delegate,
@@ -591,9 +611,10 @@ void main() {
591611 expect (tester.testTextInput.setClientArgs! ['inputAction' ], TextInputAction .done.toString ());
592612 });
593613
594- testWidgets ('Custom flexibleSpace value' , (WidgetTester tester) async {
614+ testWidgetsWithLeakTracking ('Custom flexibleSpace value' , (WidgetTester tester) async {
595615 const Widget flexibleSpace = Text ('custom flexibleSpace' );
596616 final _TestSearchDelegate delegate = _TestSearchDelegate (flexibleSpace: flexibleSpace);
617+ addTearDown (() => delegate.dispose ());
597618
598619 await tester.pumpWidget (TestHomePage (delegate: delegate));
599620 await tester.tap (find.byTooltip ('Search' ));
@@ -710,9 +731,11 @@ void main() {
710731 );
711732 }
712733
713- testWidgets ('includes routeName on Android' , (WidgetTester tester) async {
734+ testWidgetsWithLeakTracking ('includes routeName on Android' , (WidgetTester tester) async {
714735 final SemanticsTester semantics = SemanticsTester (tester);
715736 final _TestSearchDelegate delegate = _TestSearchDelegate (flexibleSpace: flexibleSpace);
737+ addTearDown (() => delegate.dispose ());
738+
716739 await tester.pumpWidget (TestHomePage (
717740 delegate: delegate,
718741 ));
@@ -730,9 +753,11 @@ void main() {
730753 semantics.dispose ();
731754 });
732755
733- testWidgets ('does not include routeName' , (WidgetTester tester) async {
756+ testWidgetsWithLeakTracking ('does not include routeName' , (WidgetTester tester) async {
734757 final SemanticsTester semantics = SemanticsTester (tester);
735758 final _TestSearchDelegate delegate = _TestSearchDelegate (flexibleSpace: flexibleSpace);
759+ addTearDown (() => delegate.dispose ());
760+
736761 await tester.pumpWidget (TestHomePage (
737762 delegate: delegate,
738763 ));
@@ -842,9 +867,11 @@ void main() {
842867 );
843868 }
844869
845- testWidgets ('includes routeName on Android' , (WidgetTester tester) async {
870+ testWidgetsWithLeakTracking ('includes routeName on Android' , (WidgetTester tester) async {
846871 final SemanticsTester semantics = SemanticsTester (tester);
847872 final _TestSearchDelegate delegate = _TestSearchDelegate ();
873+ addTearDown (() => delegate.dispose ());
874+
848875 await tester.pumpWidget (TestHomePage (
849876 delegate: delegate,
850877 ));
@@ -862,9 +889,11 @@ void main() {
862889 semantics.dispose ();
863890 });
864891
865- testWidgets ('does not include routeName' , (WidgetTester tester) async {
892+ testWidgetsWithLeakTracking ('does not include routeName' , (WidgetTester tester) async {
866893 final SemanticsTester semantics = SemanticsTester (tester);
867894 final _TestSearchDelegate delegate = _TestSearchDelegate ();
895+ addTearDown (() => delegate.dispose ());
896+
868897 await tester.pumpWidget (TestHomePage (
869898 delegate: delegate,
870899 ));
@@ -883,13 +912,14 @@ void main() {
883912 }, variant: const TargetPlatformVariant (< TargetPlatform > { TargetPlatform .iOS, TargetPlatform .macOS }));
884913 });
885914
886- testWidgets ('Custom searchFieldDecorationTheme value' , (WidgetTester tester) async {
915+ testWidgetsWithLeakTracking ('Custom searchFieldDecorationTheme value' , (WidgetTester tester) async {
887916 const InputDecorationTheme searchFieldDecorationTheme = InputDecorationTheme (
888917 hintStyle: TextStyle (color: _TestSearchDelegate .hintTextColor),
889918 );
890919 final _TestSearchDelegate delegate = _TestSearchDelegate (
891920 searchFieldDecorationTheme: searchFieldDecorationTheme,
892921 );
922+ addTearDown (() => delegate.dispose ());
893923
894924 await tester.pumpWidget (TestHomePage (delegate: delegate));
895925 await tester.tap (find.byTooltip ('Search' ));
@@ -900,12 +930,12 @@ void main() {
900930 });
901931
902932 // Regression test for: https://github.com/flutter/flutter/issues/66781
903- testWidgets ('text in search bar contrasts background (light mode)' , (WidgetTester tester) async {
933+ testWidgetsWithLeakTracking ('text in search bar contrasts background (light mode)' , (WidgetTester tester) async {
904934 final ThemeData themeData = ThemeData (useMaterial3: false );
905- final _TestSearchDelegate delegate = _TestSearchDelegate (
906- defaultAppBarTheme: true ,
907- );
935+ final _TestSearchDelegate delegate = _TestSearchDelegate (defaultAppBarTheme: true );
936+ addTearDown (() => delegate.dispose ());
908937 const String query = 'search query' ;
938+
909939 await tester.pumpWidget (TestHomePage (
910940 delegate: delegate,
911941 passInInitialQuery: true ,
@@ -928,12 +958,12 @@ void main() {
928958 });
929959
930960 // Regression test for: https://github.com/flutter/flutter/issues/66781
931- testWidgets ('text in search bar contrasts background (dark mode)' , (WidgetTester tester) async {
961+ testWidgetsWithLeakTracking ('text in search bar contrasts background (dark mode)' , (WidgetTester tester) async {
932962 final ThemeData themeData = ThemeData .dark (useMaterial3: false );
933- final _TestSearchDelegate delegate = _TestSearchDelegate (
934- defaultAppBarTheme: true ,
935- );
963+ final _TestSearchDelegate delegate = _TestSearchDelegate (defaultAppBarTheme: true );
964+ addTearDown (() => delegate.dispose ());
936965 const String query = 'search query' ;
966+
937967 await tester.pumpWidget (TestHomePage (
938968 delegate: delegate,
939969 passInInitialQuery: true ,
@@ -956,10 +986,11 @@ void main() {
956986 });
957987
958988 // Regression test for: https://github.com/flutter/flutter/issues/78144
959- testWidgets ('`Leading`, `Actions` and `FlexibleSpace` nullable test' , (WidgetTester tester) async {
989+ testWidgetsWithLeakTracking ('`Leading`, `Actions` and `FlexibleSpace` nullable test' , (WidgetTester tester) async {
960990 // The search delegate page is displayed with no issues
961991 // even with a null return values for [buildLeading], [buildActions] and [flexibleSpace].
962992 final _TestEmptySearchDelegate delegate = _TestEmptySearchDelegate ();
993+ addTearDown (delegate.dispose);
963994 final List <String > selectedResults = < String > [];
964995
965996 await tester.pumpWidget (TestHomePage (
@@ -994,11 +1025,12 @@ void main() {
9941025 expect (selectedResults, < String > ['Result' ]);
9951026 });
9961027
997- testWidgets ('showSearch with useRootNavigator' , (WidgetTester tester) async {
1028+ testWidgetsWithLeakTracking ('showSearch with useRootNavigator' , (WidgetTester tester) async {
9981029 final _MyNavigatorObserver rootObserver = _MyNavigatorObserver ();
9991030 final _MyNavigatorObserver localObserver = _MyNavigatorObserver ();
10001031
10011032 final _TestEmptySearchDelegate delegate = _TestEmptySearchDelegate ();
1033+ addTearDown (delegate.dispose);
10021034
10031035 await tester.pumpWidget (MaterialApp (
10041036 navigatorObservers: < NavigatorObserver > [rootObserver],
@@ -1051,10 +1083,11 @@ void main() {
10511083 expect (localObserver.pushCount, 1 );
10521084 });
10531085
1054- testWidgets ('Query text field shows toolbar initially' , (WidgetTester tester) async {
1086+ testWidgetsWithLeakTracking ('Query text field shows toolbar initially' , (WidgetTester tester) async {
10551087 // This is a regression test for https://github.com/flutter/flutter/issues/95588
10561088
10571089 final _TestSearchDelegate delegate = _TestSearchDelegate ();
1090+ addTearDown (() => delegate.dispose ());
10581091 final List <String > selectedResults = < String > [];
10591092
10601093 await tester.pumpWidget (TestHomePage (
0 commit comments