From 219efce7f16dab9bb9eb361721cffd206af5a29f Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 11 Sep 2023 09:42:27 -0700 Subject: [PATCH] Cover more tests with leak tracking. (#134363) --- .../flutter/test/material/about_test.dart | 8 +- .../test/material/bottom_sheet_test.dart | 110 +++++++------- .../material/bottom_sheet_theme_test.dart | 4 +- .../test/material/button_theme_test.dart | 3 +- .../flutter/test/material/drawer_test.dart | 10 +- .../material/dropdown_form_field_test.dart | 62 ++++---- .../material/dropdown_menu_theme_test.dart | 6 +- .../test/material/elevated_button_test.dart | 2 +- .../test/material/filled_button_test.dart | 4 +- .../floating_action_button_location_test.dart | 48 +++--- .../material/floating_action_button_test.dart | 10 +- .../test/material/icon_button_test.dart | 2 +- .../flutter/test/material/ink_well_test.dart | 2 +- .../test/material/input_decorator_test.dart | 2 +- .../test/material/list_tile_theme_test.dart | 2 +- .../test/material/material_button_test.dart | 2 +- .../test/material/outlined_button_test.dart | 6 +- .../test/material/page_selector_test.dart | 2 +- packages/flutter/test/material/page_test.dart | 2 +- .../material/paginated_data_table_test.dart | 95 ++++++------ .../persistent_bottom_sheet_test.dart | 18 +-- .../test/material/popup_menu_test.dart | 2 +- .../material/progress_indicator_test.dart | 8 +- .../flutter/test/material/scaffold_test.dart | 12 +- .../test/material/search_bar_theme_test.dart | 12 +- .../test/material/segmented_button_test.dart | 22 +-- .../material/segmented_button_theme_test.dart | 8 +- .../test/material/selection_area_test.dart | 28 ++-- .../flutter/test/material/snack_bar_test.dart | 138 +++++++++--------- .../flutter/test/material/switch_test.dart | 2 +- .../test/material/text_button_test.dart | 14 +- .../material/text_field_restoration_test.dart | 5 +- .../text_form_field_restoration_test.dart | 9 +- .../test/material/text_form_field_test.dart | 2 +- .../material/text_selection_toolbar_test.dart | 4 +- .../flutter/test/material/theme_test.dart | 2 +- packages/flutter/test/material/time_test.dart | 6 +- 37 files changed, 349 insertions(+), 325 deletions(-) diff --git a/packages/flutter/test/material/about_test.dart b/packages/flutter/test/material/about_test.dart index 044a58970419..4af66cc40b84 100644 --- a/packages/flutter/test/material/about_test.dart +++ b/packages/flutter/test/material/about_test.dart @@ -1460,7 +1460,7 @@ void main() { expect(find.text('Exception: Injected failure'), findsOneWidget); }); - testWidgets('Material2 - LicensePage master view layout position - ltr', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material2 - LicensePage master view layout position - ltr', (WidgetTester tester) async { const TextDirection textDirection = TextDirection.ltr; const Size defaultSize = Size(800.0, 600.0); const Size wideSize = Size(1200.0, 600.0); @@ -1592,7 +1592,7 @@ void main() { expect(tester.getCenter(find.byType(ListView)), const Offset(160, 356)); }); - testWidgets('Material2 - LicensePage master view layout position - rtl', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material2 - LicensePage master view layout position - rtl', (WidgetTester tester) async { const TextDirection textDirection = TextDirection.rtl; const Size defaultSize = Size(800.0, 600.0); const Size wideSize = Size(1200.0, 600.0); @@ -1657,7 +1657,7 @@ void main() { expect(tester.getCenter(find.byType(ListView)), const Offset(1040.0, 356.0)); }); - testWidgets('Material3 - LicensePage master view layout position - rtl', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material3 - LicensePage master view layout position - rtl', (WidgetTester tester) async { const TextDirection textDirection = TextDirection.rtl; const Size defaultSize = Size(800.0, 600.0); const Size wideSize = Size(1200.0, 600.0); @@ -1724,7 +1724,7 @@ void main() { expect(tester.getCenter(find.byType(ListView)), const Offset(1040.0, 356.0)); }); - testWidgets('License page title in lateral UI does not use AppBarTheme.foregroundColor', (WidgetTester tester) async { + testWidgetsWithLeakTracking('License page title in lateral UI does not use AppBarTheme.foregroundColor', (WidgetTester tester) async { // This is a regression test for https://github.com/flutter/flutter/issues/108991 final ThemeData theme = ThemeData( appBarTheme: const AppBarTheme(foregroundColor: Color(0xFFFFFFFF)), diff --git a/packages/flutter/test/material/bottom_sheet_test.dart b/packages/flutter/test/material/bottom_sheet_test.dart index 886b3d1efa17..fa5e91d1a9ca 100644 --- a/packages/flutter/test/material/bottom_sheet_test.dart +++ b/packages/flutter/test/material/bottom_sheet_test.dart @@ -27,7 +27,7 @@ void main() { expect(dyDelta1, isNot(moreOrLessEquals(dyDelta2, epsilon: 0.1))); } - testWidgets('Throw if enable drag without an animation controller', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Throw if enable drag without an animation controller', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/89168 await tester.pumpWidget( MaterialApp( @@ -54,7 +54,7 @@ void main() { FlutterError.onError = handler; }); - testWidgets('Disposing app while bottom sheet is disappearing does not crash', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Disposing app while bottom sheet is disappearing does not crash', (WidgetTester tester) async { late BuildContext savedContext; await tester.pumpWidget( @@ -91,7 +91,7 @@ void main() { await tester.pumpWidget(Container()); }); - testWidgets('Swiping down a BottomSheet should dismiss it by default', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Swiping down a BottomSheet should dismiss it by default', (WidgetTester tester) async { final GlobalKey scaffoldKey = GlobalKey(); bool showBottomSheetThenCalled = false; @@ -126,7 +126,7 @@ void main() { expect(find.text('BottomSheet'), findsNothing); }); - testWidgets('Swiping down a BottomSheet should not dismiss it when enableDrag is false', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Swiping down a BottomSheet should not dismiss it when enableDrag is false', (WidgetTester tester) async { final GlobalKey scaffoldKey = GlobalKey(); bool showBottomSheetThenCalled = false; @@ -163,7 +163,7 @@ void main() { expect(find.text('BottomSheet'), findsOneWidget); }); - testWidgets('Swiping down a BottomSheet should dismiss it when enableDrag is true', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Swiping down a BottomSheet should dismiss it when enableDrag is true', (WidgetTester tester) async { final GlobalKey scaffoldKey = GlobalKey(); bool showBottomSheetThenCalled = false; @@ -200,7 +200,7 @@ void main() { expect(find.text('BottomSheet'), findsNothing); }); - testWidgets('Tapping on a BottomSheet should not trigger a rebuild when enableDrag is true', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Tapping on a BottomSheet should not trigger a rebuild when enableDrag is true', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/126833. final GlobalKey scaffoldKey = GlobalKey(); int buildCount = 0; @@ -237,7 +237,7 @@ void main() { expect(find.text('BottomSheet'), findsOneWidget); }); - testWidgets('Modal BottomSheet builder should only be called once', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Modal BottomSheet builder should only be called once', (WidgetTester tester) async { late BuildContext savedContext; await tester.pumpWidget(MaterialApp( @@ -268,7 +268,7 @@ void main() { expect(numBuilderCalls, 1); }); - testWidgets('Tapping on a modal BottomSheet should not dismiss it', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Tapping on a modal BottomSheet should not dismiss it', (WidgetTester tester) async { late BuildContext savedContext; await tester.pumpWidget( @@ -304,7 +304,7 @@ void main() { expect(showBottomSheetThenCalled, isFalse); }); - testWidgets('Tapping outside a modal BottomSheet should dismiss it by default', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Tapping outside a modal BottomSheet should dismiss it by default', (WidgetTester tester) async { late BuildContext savedContext; await tester.pumpWidget(MaterialApp( @@ -338,7 +338,7 @@ void main() { expect(find.text('BottomSheet'), findsNothing); }); - testWidgets('Tapping outside a modal BottomSheet should dismiss it when isDismissible=true', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Tapping outside a modal BottomSheet should dismiss it when isDismissible=true', (WidgetTester tester) async { late BuildContext savedContext; await tester.pumpWidget(MaterialApp( @@ -372,7 +372,7 @@ void main() { expect(find.text('BottomSheet'), findsNothing); }); - testWidgets('Verify that the BottomSheet animates non-linearly', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Verify that the BottomSheet animates non-linearly', (WidgetTester tester) async { late BuildContext savedContext; await tester.pumpWidget(MaterialApp( @@ -405,7 +405,7 @@ void main() { }); // Regression test for https://github.com/flutter/flutter/issues/121098 - testWidgets('Verify that accessibleNavigation has no impact on the BottomSheet animation', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Verify that accessibleNavigation has no impact on the BottomSheet animation', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( builder: (BuildContext context, Widget? child) { return MediaQuery( @@ -430,7 +430,7 @@ void main() { await tester.pumpAndSettle(); }); - testWidgets('Tapping outside a modal BottomSheet should not dismiss it when isDismissible=false', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Tapping outside a modal BottomSheet should not dismiss it when isDismissible=false', (WidgetTester tester) async { late BuildContext savedContext; await tester.pumpWidget( @@ -467,7 +467,7 @@ void main() { expect(find.text('BottomSheet'), findsOneWidget); }); - testWidgets('Swiping down a modal BottomSheet should dismiss it by default', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Swiping down a modal BottomSheet should dismiss it by default', (WidgetTester tester) async { late BuildContext savedContext; await tester.pumpWidget(MaterialApp( @@ -502,7 +502,7 @@ void main() { expect(find.text('BottomSheet'), findsNothing); }); - testWidgets('Swiping down a modal BottomSheet should not dismiss it when enableDrag is false', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Swiping down a modal BottomSheet should not dismiss it when enableDrag is false', (WidgetTester tester) async { late BuildContext savedContext; await tester.pumpWidget(MaterialApp( @@ -538,7 +538,7 @@ void main() { expect(find.text('BottomSheet'), findsOneWidget); }); - testWidgets('Swiping down a modal BottomSheet should dismiss it when enableDrag is true', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Swiping down a modal BottomSheet should dismiss it when enableDrag is true', (WidgetTester tester) async { late BuildContext savedContext; await tester.pumpWidget(MaterialApp( @@ -573,7 +573,7 @@ void main() { expect(find.text('BottomSheet'), findsNothing); }); - testWidgets('Modal BottomSheet builder should only be called once', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Modal BottomSheet builder should only be called once', (WidgetTester tester) async { late BuildContext savedContext; await tester.pumpWidget(MaterialApp( @@ -604,7 +604,7 @@ void main() { expect(numBuilderCalls, 1); }); - testWidgets('Verify that a downwards fling dismisses a persistent BottomSheet', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Verify that a downwards fling dismisses a persistent BottomSheet', (WidgetTester tester) async { final GlobalKey scaffoldKey = GlobalKey(); bool showBottomSheetThenCalled = false; @@ -661,7 +661,7 @@ void main() { expect(find.text('BottomSheet'), findsNothing); }); - testWidgets('Verify that dragging past the bottom dismisses a persistent BottomSheet', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Verify that dragging past the bottom dismisses a persistent BottomSheet', (WidgetTester tester) async { // This is a regression test for https://github.com/flutter/flutter/issues/5528 final GlobalKey scaffoldKey = GlobalKey(); @@ -691,7 +691,7 @@ void main() { expect(find.text('BottomSheet'), findsNothing); }); - testWidgets('modal BottomSheet has no top MediaQuery', (WidgetTester tester) async { + testWidgetsWithLeakTracking('modal BottomSheet has no top MediaQuery', (WidgetTester tester) async { late BuildContext outerContext; late BuildContext innerContext; @@ -742,7 +742,7 @@ void main() { ); }); - testWidgets('modal BottomSheet can insert a SafeArea', (WidgetTester tester) async { + testWidgetsWithLeakTracking('modal BottomSheet can insert a SafeArea', (WidgetTester tester) async { late BuildContext outerContext; late BuildContext innerContext; @@ -814,7 +814,7 @@ void main() { expect(MediaQuery.of(innerContext).padding, const EdgeInsets.fromLTRB(0, 0, 0, 50.0)); }); - testWidgets('modal BottomSheet has semantics', (WidgetTester tester) async { + testWidgetsWithLeakTracking('modal BottomSheet has semantics', (WidgetTester tester) async { final SemanticsTester semantics = SemanticsTester(tester); final GlobalKey scaffoldKey = GlobalKey(); @@ -871,7 +871,7 @@ void main() { semantics.dispose(); }); - testWidgets('Verify that visual properties are passed through', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Verify that visual properties are passed through', (WidgetTester tester) async { final GlobalKey scaffoldKey = GlobalKey(); const Color color = Colors.pink; const double elevation = 9.0; @@ -911,7 +911,7 @@ void main() { expect(modalBarrier.color, barrierColor); }); - testWidgets('BottomSheet uses fallback values in material3', + testWidgetsWithLeakTracking('BottomSheet uses fallback values in material3', (WidgetTester tester) async { const Color surfaceColor = Colors.pink; const Color surfaceTintColor = Colors.blue; @@ -951,7 +951,7 @@ void main() { expect(tester.getSize(finder).width, 640); }); - testWidgets('BottomSheet has transparent shadow in material3', (WidgetTester tester) async { + testWidgetsWithLeakTracking('BottomSheet has transparent shadow in material3', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData( useMaterial3: true, @@ -975,7 +975,7 @@ void main() { expect(material.shadowColor, Colors.transparent); }); - testWidgets('modal BottomSheet with scrollController has semantics', (WidgetTester tester) async { + testWidgetsWithLeakTracking('modal BottomSheet with scrollController has semantics', (WidgetTester tester) async { final SemanticsTester semantics = SemanticsTester(tester); final GlobalKey scaffoldKey = GlobalKey(); @@ -1048,7 +1048,7 @@ void main() { semantics.dispose(); }); - testWidgets('modal BottomSheet with drag handle has semantics', (WidgetTester tester) async { + testWidgetsWithLeakTracking('modal BottomSheet with drag handle has semantics', (WidgetTester tester) async { final SemanticsTester semantics = SemanticsTester(tester); final GlobalKey scaffoldKey = GlobalKey(); @@ -1117,7 +1117,7 @@ void main() { semantics.dispose(); }); - testWidgets('Drag handle color can take MaterialStateProperty', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Drag handle color can take MaterialStateProperty', (WidgetTester tester) async { final GlobalKey scaffoldKey = GlobalKey(); const Color defaultColor=Colors.blue; const Color hoveringColor=Colors.green; @@ -1180,7 +1180,7 @@ void main() { expect(boxDecoration.color, hoveringColor); }); - testWidgets('showModalBottomSheet does not use root Navigator by default', (WidgetTester tester) async { + testWidgetsWithLeakTracking('showModalBottomSheet does not use root Navigator by default', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: false), home: Scaffold( @@ -1210,7 +1210,7 @@ void main() { expect(tester.getBottomLeft(find.byType(BottomSheet)).dy, 544.0); }); - testWidgets('showModalBottomSheet uses root Navigator when specified', (WidgetTester tester) async { + testWidgetsWithLeakTracking('showModalBottomSheet uses root Navigator when specified', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( home: Scaffold( body: Navigator(onGenerateRoute: (RouteSettings settings) => MaterialPageRoute(builder: (_) { @@ -1239,7 +1239,7 @@ void main() { expect(tester.getBottomLeft(find.byType(BottomSheet)).dy, 600.0); }); - testWidgets('Verify that route settings can be set in the showModalBottomSheet', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Verify that route settings can be set in the showModalBottomSheet', (WidgetTester tester) async { final GlobalKey scaffoldKey = GlobalKey(); const RouteSettings routeSettings = RouteSettings(name: 'route_name', arguments: 'route_argument'); @@ -1267,7 +1267,7 @@ void main() { expect(retrievedRouteSettings, routeSettings); }); - testWidgets('Verify showModalBottomSheet use AnimationController if provided.', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Verify showModalBottomSheet use AnimationController if provided.', (WidgetTester tester) async { const Key tapTarget = Key('tap-target'); await tester.pumpWidget(MaterialApp( home: Scaffold( @@ -1324,7 +1324,7 @@ void main() { }); // Regression test for https://github.com/flutter/flutter/issues/87592 - testWidgets('the framework do not dispose the transitionAnimationController provided by user.', (WidgetTester tester) async { + testWidgetsWithLeakTracking('the framework do not dispose the transitionAnimationController provided by user.', (WidgetTester tester) async { const Key tapTarget = Key('tap-target'); final AnimationController controller = AnimationController( vsync: const TestVSync(), @@ -1386,7 +1386,7 @@ void main() { expect(tester.takeException(), isNull); }); - testWidgets('Verify persistence BottomSheet use AnimationController if provided.', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Verify persistence BottomSheet use AnimationController if provided.', (WidgetTester tester) async { const Key tapTarget = Key('tap-target'); const Key tapTargetToClose = Key('tap-target-to-close'); await tester.pumpWidget(MaterialApp( @@ -1448,7 +1448,7 @@ void main() { }); // Regression test for https://github.com/flutter/flutter/issues/87708 - testWidgets('Each of the internal animation controllers should be disposed by the framework.', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Each of the internal animation controllers should be disposed by the framework.', (WidgetTester tester) async { final GlobalKey scaffoldKey = GlobalKey(); await tester.pumpWidget(MaterialApp( home: Scaffold( @@ -1491,7 +1491,7 @@ void main() { }); // Regression test for https://github.com/flutter/flutter/issues/99627 - testWidgets('The old route entry should be removed when a new sheet popup', (WidgetTester tester) async { + testWidgetsWithLeakTracking('The old route entry should be removed when a new sheet popup', (WidgetTester tester) async { final GlobalKey scaffoldKey = GlobalKey(); PersistentBottomSheetController? sheetController; @@ -1535,7 +1535,7 @@ void main() { }); // Regression test for https://github.com/flutter/flutter/issues/87708 - testWidgets('The framework does not dispose of the transitionAnimationController provided by user.', (WidgetTester tester) async { + testWidgetsWithLeakTracking('The framework does not dispose of the transitionAnimationController provided by user.', (WidgetTester tester) async { const Key tapTarget = Key('tap-target'); const Key tapTargetToClose = Key('tap-target-to-close'); final AnimationController controller = AnimationController( @@ -1591,7 +1591,7 @@ void main() { expect(tester.takeException(), isNull); }); - testWidgets('Calling PersistentBottomSheetController.close does not crash when it is not the current bottom sheet', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Calling PersistentBottomSheetController.close does not crash when it is not the current bottom sheet', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/93717 PersistentBottomSheetController? sheetController1; await tester.pumpWidget(MaterialApp( @@ -1643,7 +1643,7 @@ void main() { expect(find.text('BottomSheet 2'), findsOneWidget); }); - testWidgets('ModalBottomSheetRoute shows BottomSheet correctly', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ModalBottomSheetRoute shows BottomSheet correctly', (WidgetTester tester) async { late BuildContext savedContext; await tester.pumpWidget( @@ -1717,7 +1717,7 @@ void main() { notDisposedAllowList: {'ValueNotifier': 1} )); - testWidgets('positioning using Directionality', (WidgetTester tester) async { + testWidgetsWithLeakTracking('positioning using Directionality', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( builder: (BuildContext context, Widget? child) { @@ -1757,7 +1757,7 @@ void main() { expect(tester.getBottomRight(find.byType(Placeholder)).dx, 800); }); - testWidgets('default positioning', (WidgetTester tester) async { + testWidgetsWithLeakTracking('default positioning', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( builder: (BuildContext context, Widget? child) { @@ -1796,7 +1796,7 @@ void main() { }); group('constraints', () { - testWidgets('default constraints are max width 640 in material 3', (WidgetTester tester) async { + testWidgetsWithLeakTracking('default constraints are max width 640 in material 3', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( theme: ThemeData.light(useMaterial3: true), @@ -1812,7 +1812,7 @@ void main() { expect(tester.getSize(find.byType(Placeholder)).width, 640); }); - testWidgets('No constraints by default for bottomSheet property', (WidgetTester tester) async { + testWidgetsWithLeakTracking('No constraints by default for bottomSheet property', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: false), home: const Scaffold( @@ -1827,7 +1827,7 @@ void main() { ); }); - testWidgets('No constraints by default for showBottomSheet', (WidgetTester tester) async { + testWidgetsWithLeakTracking('No constraints by default for showBottomSheet', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: false), home: Scaffold( @@ -1855,7 +1855,7 @@ void main() { ); }); - testWidgets('No constraints by default for showModalBottomSheet', (WidgetTester tester) async { + testWidgetsWithLeakTracking('No constraints by default for showModalBottomSheet', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: false), home: Scaffold( @@ -1884,7 +1884,7 @@ void main() { ); }); - testWidgets('Theme constraints used for bottomSheet property', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Theme constraints used for bottomSheet property', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData( useMaterial3: false, @@ -1912,7 +1912,7 @@ void main() { ); }); - testWidgets('Theme constraints used for showBottomSheet', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Theme constraints used for showBottomSheet', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData( useMaterial3: false, @@ -1946,7 +1946,7 @@ void main() { ); }); - testWidgets('Theme constraints used for showModalBottomSheet', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Theme constraints used for showModalBottomSheet', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData( useMaterial3: false, @@ -1981,7 +1981,7 @@ void main() { ); }); - testWidgets('constraints param overrides theme for showBottomSheet', (WidgetTester tester) async { + testWidgetsWithLeakTracking('constraints param overrides theme for showBottomSheet', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData( useMaterial3: false, @@ -2016,7 +2016,7 @@ void main() { ); }); - testWidgets('constraints param overrides theme for showModalBottomSheet', (WidgetTester tester) async { + testWidgetsWithLeakTracking('constraints param overrides theme for showModalBottomSheet', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData( useMaterial3: false, @@ -2094,20 +2094,20 @@ void main() { ); } - testWidgets('works at 9 / 16', (WidgetTester tester) { + testWidgetsWithLeakTracking('works at 9 / 16', (WidgetTester tester) { return test(tester, false, 9.0 / 16.0); }); - testWidgets('works at 8 / 16', (WidgetTester tester) { + testWidgetsWithLeakTracking('works at 8 / 16', (WidgetTester tester) { return test(tester, false, 8.0 / 16.0); }); - testWidgets('works at isScrollControlled', (WidgetTester tester) { + testWidgetsWithLeakTracking('works at isScrollControlled', (WidgetTester tester) { return test(tester, true, 8.0 / 16.0); }); }); }); group('showModalBottomSheet modalBarrierDismissLabel', () { - testWidgets('Verify that modalBarrierDismissLabel is used if provided', + testWidgetsWithLeakTracking('Verify that modalBarrierDismissLabel is used if provided', (WidgetTester tester) async { final GlobalKey scaffoldKey = GlobalKey(); const String customLabel = 'custom label'; @@ -2133,7 +2133,7 @@ void main() { expect(modalBarrier.semanticsLabel, customLabel); }); - testWidgets('Verify that modalBarrierDismissLabel from context is used if barrierLabel is not provided', + testWidgetsWithLeakTracking('Verify that modalBarrierDismissLabel from context is used if barrierLabel is not provided', (WidgetTester tester) async { final GlobalKey scaffoldKey = GlobalKey(); await tester.pumpWidget(MaterialApp( diff --git a/packages/flutter/test/material/bottom_sheet_theme_test.dart b/packages/flutter/test/material/bottom_sheet_theme_test.dart index 9d203e5ceff7..6b9b526c732b 100644 --- a/packages/flutter/test/material/bottom_sheet_theme_test.dart +++ b/packages/flutter/test/material/bottom_sheet_theme_test.dart @@ -170,7 +170,7 @@ void main() { expect(material.clipBehavior, clipBehavior); }); - testWidgets('Modal bottom sheet-specific parameters are used for modal bottom sheets', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Modal bottom sheet-specific parameters are used for modal bottom sheets', (WidgetTester tester) async { const double modalElevation = 5.0; const double persistentElevation = 7.0; const Color modalBackgroundColor = Colors.yellow; @@ -249,7 +249,7 @@ void main() { expect(material.color, null); }); - testWidgets('Modal bottom sheets respond to theme changes', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Modal bottom sheets respond to theme changes', (WidgetTester tester) async { const double lightElevation = 5.0; const double darkElevation = 3.0; const Color lightBackgroundColor = Colors.green; diff --git a/packages/flutter/test/material/button_theme_test.dart b/packages/flutter/test/material/button_theme_test.dart index 4657e1b5f4b1..1b8f3689e237 100644 --- a/packages/flutter/test/material/button_theme_test.dart +++ b/packages/flutter/test/material/button_theme_test.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; void main() { @@ -67,7 +68,7 @@ void main() { expect(theme.colorScheme, const ColorScheme.dark()); }); - testWidgets('ButtonTheme alignedDropdown', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ButtonTheme alignedDropdown', (WidgetTester tester) async { final Key dropdownKey = UniqueKey(); Widget buildFrame({ required bool alignedDropdown, required TextDirection textDirection }) { diff --git a/packages/flutter/test/material/drawer_test.dart b/packages/flutter/test/material/drawer_test.dart index e4d0475bbdea..a83b1bef962b 100644 --- a/packages/flutter/test/material/drawer_test.dart +++ b/packages/flutter/test/material/drawer_test.dart @@ -213,7 +213,7 @@ void main() { expect(state.isEndDrawerOpen, equals(false)); }); - testWidgets('Scaffold.drawer - null restorationId ', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Scaffold.drawer - null restorationId ', (WidgetTester tester) async { final GlobalKey scaffoldKey = GlobalKey(); await tester.pumpWidget( MaterialApp( @@ -236,7 +236,7 @@ void main() { expect(find.text('drawer'), findsNothing); }); - testWidgets('Scaffold.endDrawer - null restorationId ', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Scaffold.endDrawer - null restorationId ', (WidgetTester tester) async { final GlobalKey scaffoldKey = GlobalKey(); await tester.pumpWidget( MaterialApp( @@ -259,7 +259,7 @@ void main() { expect(find.text('endDrawer'), findsNothing); }); - testWidgets('Scaffold.drawer state restoration test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Scaffold.drawer state restoration test', (WidgetTester tester) async { final GlobalKey scaffoldKey = GlobalKey(); await tester.pumpWidget( MaterialApp( @@ -290,7 +290,7 @@ void main() { expect(find.text('drawer'), findsOneWidget); }); - testWidgets('Scaffold.endDrawer state restoration test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Scaffold.endDrawer state restoration test', (WidgetTester tester) async { final GlobalKey scaffoldKey = GlobalKey(); await tester.pumpWidget( MaterialApp( @@ -321,7 +321,7 @@ void main() { expect(find.text('endDrawer'), findsOneWidget); }); - testWidgets('Both drawer and endDrawer state restoration test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Both drawer and endDrawer state restoration test', (WidgetTester tester) async { final GlobalKey scaffoldKey = GlobalKey(); await tester.pumpWidget( MaterialApp( diff --git a/packages/flutter/test/material/dropdown_form_field_test.dart b/packages/flutter/test/material/dropdown_form_field_test.dart index 582f0e88882c..094c8cb30e73 100644 --- a/packages/flutter/test/material/dropdown_form_field_test.dart +++ b/packages/flutter/test/material/dropdown_form_field_test.dart @@ -7,6 +7,7 @@ import 'dart:math' as math; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; const List menuItems = ['one', 'two', 'three', 'four']; void onChanged(T _) { } @@ -148,7 +149,7 @@ void verifyPaintedShadow(Finder customPaint, int elevation) { void main() { // Regression test for https://github.com/flutter/flutter/issues/87102 - testWidgets('label position test - show hint', (WidgetTester tester) async { + testWidgetsWithLeakTracking('label position test - show hint', (WidgetTester tester) async { int? value; await tester.pumpWidget( @@ -199,7 +200,7 @@ void main() { expect(hintEmptyLabel, oneValueLabel); }); - testWidgets('label position test - show disabledHint: disable', (WidgetTester tester) async { + testWidgetsWithLeakTracking('label position test - show disabledHint: disable', (WidgetTester tester) async { int? value; await tester.pumpWidget( @@ -237,7 +238,7 @@ void main() { expect(hintEmptyLabel, const Offset(0.0, 12.0)); }); - testWidgets('label position test - show disabledHint: enable + null item', (WidgetTester tester) async { + testWidgetsWithLeakTracking('label position test - show disabledHint: enable + null item', (WidgetTester tester) async { int? value; await tester.pumpWidget( @@ -262,7 +263,7 @@ void main() { expect(hintEmptyLabel, const Offset(0.0, 12.0)); }); - testWidgets('label position test - show disabledHint: enable + empty item', (WidgetTester tester) async { + testWidgetsWithLeakTracking('label position test - show disabledHint: enable + empty item', (WidgetTester tester) async { int? value; await tester.pumpWidget( @@ -287,7 +288,7 @@ void main() { expect(hintEmptyLabel, const Offset(0.0, 12.0)); }); - testWidgets('label position test - show hint: enable + empty item', (WidgetTester tester) async { + testWidgetsWithLeakTracking('label position test - show hint: enable + empty item', (WidgetTester tester) async { int? value; await tester.pumpWidget( @@ -312,7 +313,7 @@ void main() { expect(hintEmptyLabel, const Offset(0.0, 12.0)); }); - testWidgets('label position test - no hint shown: enable + no selected + disabledHint', (WidgetTester tester) async { + testWidgetsWithLeakTracking('label position test - no hint shown: enable + no selected + disabledHint', (WidgetTester tester) async { int? value; await tester.pumpWidget( @@ -350,7 +351,7 @@ void main() { expect(hintEmptyLabel, const Offset(0.0, 24.0)); }); - testWidgets('label position test - show selected item: disabled + hint + disabledHint', (WidgetTester tester) async { + testWidgetsWithLeakTracking('label position test - show selected item: disabled + hint + disabledHint', (WidgetTester tester) async { const int value = 1; await tester.pumpWidget( @@ -390,7 +391,7 @@ void main() { }); // Regression test for https://github.com/flutter/flutter/issues/82910 - testWidgets('null value test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('null value test', (WidgetTester tester) async { int? value = 1; await tester.pumpWidget( @@ -442,7 +443,7 @@ void main() { expect(nonEmptyLabel, nullValueLabel); }); - testWidgets('DropdownButtonFormField with autovalidation test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('DropdownButtonFormField with autovalidation test', (WidgetTester tester) async { String? value = 'one'; int validateCalled = 0; @@ -491,7 +492,7 @@ void main() { expect(value, equals('three')); }); - testWidgets('DropdownButtonFormField arrow icon aligns with the edge of button when expanded', (WidgetTester tester) async { + testWidgetsWithLeakTracking('DropdownButtonFormField arrow icon aligns with the edge of button when expanded', (WidgetTester tester) async { final Key buttonKey = UniqueKey(); // There shouldn't be overflow when expanded although list contains longer items. @@ -526,7 +527,7 @@ void main() { ); }); - testWidgets('DropdownButtonFormField with isDense:true aligns selected menu item', (WidgetTester tester) async { + testWidgetsWithLeakTracking('DropdownButtonFormField with isDense:true aligns selected menu item', (WidgetTester tester) async { final Key buttonKey = UniqueKey(); await tester.pumpWidget( @@ -566,7 +567,7 @@ void main() { } }); - testWidgets('DropdownButtonFormField with isDense:true does not clip large scale text', + testWidgetsWithLeakTracking('DropdownButtonFormField with isDense:true does not clip large scale text', (WidgetTester tester) async { final Key buttonKey = UniqueKey(); const String value = 'two'; @@ -605,7 +606,7 @@ void main() { expect(box.size.height, 72.0); }); - testWidgets('DropdownButtonFormField.isDense is true by default', (WidgetTester tester) async { + testWidgetsWithLeakTracking('DropdownButtonFormField.isDense is true by default', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/46844 final Key buttonKey = UniqueKey(); const String value = 'two'; @@ -636,7 +637,7 @@ void main() { expect(box.size.height, 48.0); }); - testWidgets('DropdownButtonFormField - custom text style', (WidgetTester tester) async { + testWidgetsWithLeakTracking('DropdownButtonFormField - custom text style', (WidgetTester tester) async { const String value = 'foo'; final UniqueKey itemKey = UniqueKey(); @@ -674,7 +675,7 @@ void main() { expect(richText.text.style!.fontSize, 20.0); }); - testWidgets('DropdownButtonFormField - disabledHint displays when the items list is empty, when items is null', (WidgetTester tester) async { + testWidgetsWithLeakTracking('DropdownButtonFormField - disabledHint displays when the items list is empty, when items is null', (WidgetTester tester) async { final Key buttonKey = UniqueKey(); Widget build({ List? items }) { @@ -721,7 +722,7 @@ void main() { }, ); - testWidgets('DropdownButtonFormField - disabledHint is null by default', (WidgetTester tester) async { + testWidgetsWithLeakTracking('DropdownButtonFormField - disabledHint is null by default', (WidgetTester tester) async { final Key buttonKey = UniqueKey(); Widget build({ List? items }) { @@ -741,7 +742,7 @@ void main() { expect(find.text('hint used when disabled'), findsOneWidget); }); - testWidgets('DropdownButtonFormField - disabledHint is null by default', (WidgetTester tester) async { + testWidgetsWithLeakTracking('DropdownButtonFormField - disabledHint is null by default', (WidgetTester tester) async { final Key buttonKey = UniqueKey(); Widget build({ List? items }) { @@ -761,7 +762,7 @@ void main() { expect(find.text('hint used when disabled'), findsOneWidget); }); - testWidgets('DropdownButtonFormField - disabledHint displays when onChanged is null', (WidgetTester tester) async { + testWidgetsWithLeakTracking('DropdownButtonFormField - disabledHint displays when onChanged is null', (WidgetTester tester) async { final Key buttonKey = UniqueKey(); Widget build({ List? items, ValueChanged? onChanged }) { @@ -779,7 +780,7 @@ void main() { expect(find.text('disabled'), findsOneWidget); }); - testWidgets('DropdownButtonFormField - disabled hint should be of same size as enabled hint', (WidgetTester tester) async { + testWidgetsWithLeakTracking('DropdownButtonFormField - disabled hint should be of same size as enabled hint', (WidgetTester tester) async { final Key buttonKey = UniqueKey(); Widget build({ List? items}) { @@ -804,7 +805,7 @@ void main() { expect(enabledHintBox.size, equals(disabledHintBox.size)); }); - testWidgets('DropdownButtonFormField - Custom icon size and colors', (WidgetTester tester) async { + testWidgetsWithLeakTracking('DropdownButtonFormField - Custom icon size and colors', (WidgetTester tester) async { final Key iconKey = UniqueKey(); final Icon customIcon = Icon(Icons.assessment, key: iconKey); @@ -837,7 +838,7 @@ void main() { expect(disabledRichText.text.style!.color, Colors.orange); }); - testWidgets('DropdownButtonFormField - default elevation', (WidgetTester tester) async { + testWidgetsWithLeakTracking('DropdownButtonFormField - default elevation', (WidgetTester tester) async { final Key buttonKey = UniqueKey(); debugDisableShadows = false; await tester.pumpWidget(buildFormFrame( @@ -857,7 +858,7 @@ void main() { debugDisableShadows = true; }); - testWidgets('DropdownButtonFormField - custom elevation', (WidgetTester tester) async { + testWidgetsWithLeakTracking('DropdownButtonFormField - custom elevation', (WidgetTester tester) async { debugDisableShadows = false; final Key buttonKeyOne = UniqueKey(); final Key buttonKeyTwo = UniqueKey(); @@ -894,7 +895,7 @@ void main() { debugDisableShadows = true; }); - testWidgets('DropdownButtonFormField does not allow duplicate item values', (WidgetTester tester) async { + testWidgetsWithLeakTracking('DropdownButtonFormField does not allow duplicate item values', (WidgetTester tester) async { final List> itemsWithDuplicateValues = ['a', 'b', 'c', 'c'] .map>((String value) { return DropdownMenuItem( @@ -923,7 +924,7 @@ void main() { ); }); - testWidgets('DropdownButtonFormField value should only appear in one menu item', (WidgetTester tester) async { + testWidgetsWithLeakTracking('DropdownButtonFormField value should only appear in one menu item', (WidgetTester tester) async { final List> itemsWithDuplicateValues = ['a', 'b', 'c', 'd'] .map>((String value) { return DropdownMenuItem( @@ -952,7 +953,7 @@ void main() { ); }); - testWidgets('DropdownButtonFormField - selectedItemBuilder builds custom buttons', (WidgetTester tester) async { + testWidgetsWithLeakTracking('DropdownButtonFormField - selectedItemBuilder builds custom buttons', (WidgetTester tester) async { const List items = [ 'One', 'Two', @@ -996,7 +997,7 @@ void main() { expect(find.text('Two as an Arabic numeral: 2'), findsOneWidget); }); - testWidgets('DropdownButton onTap callback is called when defined', (WidgetTester tester) async { + testWidgetsWithLeakTracking('DropdownButton onTap callback is called when defined', (WidgetTester tester) async { int dropdownButtonTapCounter = 0; String? value = 'one'; void onChanged(String? newValue) { @@ -1042,7 +1043,7 @@ void main() { expect(dropdownButtonTapCounter, 2); // Should not change. }); - testWidgets('DropdownButtonFormField should re-render if value param changes', (WidgetTester tester) async { + testWidgetsWithLeakTracking('DropdownButtonFormField should re-render if value param changes', (WidgetTester tester) async { String currentValue = 'two'; await tester.pumpWidget( @@ -1088,7 +1089,7 @@ void main() { expect(find.text(currentValue), findsOneWidget); }); - testWidgets('autovalidateMode is passed to super', (WidgetTester tester) async { + testWidgetsWithLeakTracking('autovalidateMode is passed to super', (WidgetTester tester) async { int validateCalled = 0; await tester.pumpWidget( @@ -1117,7 +1118,7 @@ void main() { expect(validateCalled, 1); }); - testWidgets('DropdownButtonFormField - Custom button alignment', (WidgetTester tester) async { + testWidgetsWithLeakTracking('DropdownButtonFormField - Custom button alignment', (WidgetTester tester) async { await tester.pumpWidget(buildFormFrame( buttonAlignment: AlignmentDirectional.center, items: ['one'], @@ -1134,13 +1135,14 @@ void main() { ); }); - testWidgets('InputDecoration borders are used for clipping', (WidgetTester tester) async { + testWidgetsWithLeakTracking('InputDecoration borders are used for clipping', (WidgetTester tester) async { const BorderRadius errorBorderRadius = BorderRadius.all(Radius.circular(5.0)); const BorderRadius focusedErrorBorderRadius = BorderRadius.all(Radius.circular(6.0)); const BorderRadius focusedBorder = BorderRadius.all(Radius.circular(7.0)); const BorderRadius enabledBorder = BorderRadius.all(Radius.circular(9.0)); final FocusNode focusNode = FocusNode(); + addTearDown(focusNode.dispose); const String errorText = 'This is an error'; bool showError = false; diff --git a/packages/flutter/test/material/dropdown_menu_theme_test.dart b/packages/flutter/test/material/dropdown_menu_theme_test.dart index f0c0f1796232..279f60256a28 100644 --- a/packages/flutter/test/material/dropdown_menu_theme_test.dart +++ b/packages/flutter/test/material/dropdown_menu_theme_test.dart @@ -43,7 +43,7 @@ void main() { expect(description, []); }); - testWidgets('With no other configuration, defaults are used', (WidgetTester tester) async { + testWidgetsWithLeakTracking('With no other configuration, defaults are used', (WidgetTester tester) async { final ThemeData themeData = ThemeData(); await tester.pumpWidget( MaterialApp( @@ -179,7 +179,7 @@ void main() { expect(material.textStyle?.color, theme.colorScheme.onSurface); }); - testWidgets('DropdownMenuTheme overrides ThemeData and defaults', (WidgetTester tester) async { + testWidgetsWithLeakTracking('DropdownMenuTheme overrides ThemeData and defaults', (WidgetTester tester) async { final DropdownMenuThemeData global = DropdownMenuThemeData( textStyle: TextStyle( color: Colors.orange, @@ -282,7 +282,7 @@ void main() { expect(material.textStyle?.color, theme.colorScheme.onSurface); }); - testWidgets('Widget parameters overrides DropdownMenuTheme, ThemeData and defaults', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Widget parameters overrides DropdownMenuTheme, ThemeData and defaults', (WidgetTester tester) async { final DropdownMenuThemeData global = DropdownMenuThemeData( textStyle: TextStyle( color: Colors.orange, diff --git a/packages/flutter/test/material/elevated_button_test.dart b/packages/flutter/test/material/elevated_button_test.dart index 89b2fe6308fa..0f3796c87f7e 100644 --- a/packages/flutter/test/material/elevated_button_test.dart +++ b/packages/flutter/test/material/elevated_button_test.dart @@ -160,7 +160,7 @@ void main() { expect(material.type, MaterialType.button); }); - testWidgets('Default ElevatedButton meets a11y contrast guidelines', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Default ElevatedButton meets a11y contrast guidelines', (WidgetTester tester) async { final FocusNode focusNode = FocusNode(); await tester.pumpWidget( diff --git a/packages/flutter/test/material/filled_button_test.dart b/packages/flutter/test/material/filled_button_test.dart index 0b2062a7fab5..5c71f5395f10 100644 --- a/packages/flutter/test/material/filled_button_test.dart +++ b/packages/flutter/test/material/filled_button_test.dart @@ -237,7 +237,7 @@ void main() { expect(material.type, MaterialType.button); }); - testWidgets('Default FilledButton meets a11y contrast guidelines', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Default FilledButton meets a11y contrast guidelines', (WidgetTester tester) async { final FocusNode focusNode = FocusNode(); addTearDown(focusNode.dispose); @@ -1750,7 +1750,7 @@ void main() { expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); }); - testWidgets('FilledButton in SelectionArea changes mouse cursor when hovered', (WidgetTester tester) async { + testWidgetsWithLeakTracking('FilledButton in SelectionArea changes mouse cursor when hovered', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/104595. await tester.pumpWidget(MaterialApp( home: SelectionArea( diff --git a/packages/flutter/test/material/floating_action_button_location_test.dart b/packages/flutter/test/material/floating_action_button_location_test.dart index b43449f2435d..a94253aa2e99 100644 --- a/packages/flutter/test/material/floating_action_button_location_test.dart +++ b/packages/flutter/test/material/floating_action_button_location_test.dart @@ -184,7 +184,7 @@ void main() { await tester.pumpAndSettle(); }); - testWidgets('interrupting motion towards the StartTop location.', (WidgetTester tester) async { + testWidgetsWithLeakTracking('interrupting motion towards the StartTop location.', (WidgetTester tester) async { await tester.pumpWidget(_buildFrame(location: FloatingActionButtonLocation.centerFloat, listener: geometryListener)); setupListener(tester); @@ -197,7 +197,7 @@ void main() { await tester.pumpAndSettle(); }); - testWidgets('interrupting entrance to remove the fab.', (WidgetTester tester) async { + testWidgetsWithLeakTracking('interrupting entrance to remove the fab.', (WidgetTester tester) async { await tester.pumpWidget(_buildFrame(fab: null, location: FloatingActionButtonLocation.centerFloat, listener: geometryListener)); setupListener(tester); @@ -216,7 +216,7 @@ void main() { await tester.pumpAndSettle(); }); - testWidgets('interrupting entrance of a new fab.', (WidgetTester tester) async { + testWidgetsWithLeakTracking('interrupting entrance of a new fab.', (WidgetTester tester) async { await tester.pumpWidget( _buildFrame( fab: null, @@ -409,7 +409,7 @@ void main() { expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_rightOffsetX, _topOffsetY)); }); - testWidgets('startFloat', (WidgetTester tester) async { + testWidgetsWithLeakTracking('startFloat', (WidgetTester tester) async { await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.startFloat)); expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_leftOffsetX, _floatOffsetY)); @@ -421,25 +421,25 @@ void main() { expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_centerOffsetX, _floatOffsetY)); }); - testWidgets('endFloat', (WidgetTester tester) async { + testWidgetsWithLeakTracking('endFloat', (WidgetTester tester) async { await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.endFloat)); expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_rightOffsetX, _floatOffsetY)); }); - testWidgets('startDocked', (WidgetTester tester) async { + testWidgetsWithLeakTracking('startDocked', (WidgetTester tester) async { await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.startDocked)); expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_leftOffsetX, _dockedOffsetY)); }); - testWidgets('centerDocked', (WidgetTester tester) async { + testWidgetsWithLeakTracking('centerDocked', (WidgetTester tester) async { await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.centerDocked)); expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_centerOffsetX, _dockedOffsetY)); }); - testWidgets('endDocked', (WidgetTester tester) async { + testWidgetsWithLeakTracking('endDocked', (WidgetTester tester) async { await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.endDocked)); expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_rightOffsetX, _dockedOffsetY)); @@ -463,31 +463,31 @@ void main() { expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_miniRightOffsetX, _topOffsetY)); }); - testWidgets('miniStartFloat', (WidgetTester tester) async { + testWidgetsWithLeakTracking('miniStartFloat', (WidgetTester tester) async { await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.miniStartFloat)); expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_miniLeftOffsetX, _miniFloatOffsetY)); }); - testWidgets('miniCenterFloat', (WidgetTester tester) async { + testWidgetsWithLeakTracking('miniCenterFloat', (WidgetTester tester) async { await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.miniCenterFloat)); expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_centerOffsetX, _miniFloatOffsetY)); }); - testWidgets('miniEndFloat', (WidgetTester tester) async { + testWidgetsWithLeakTracking('miniEndFloat', (WidgetTester tester) async { await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.miniEndFloat)); expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_miniRightOffsetX, _miniFloatOffsetY)); }); - testWidgets('miniStartDocked', (WidgetTester tester) async { + testWidgetsWithLeakTracking('miniStartDocked', (WidgetTester tester) async { await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.miniStartDocked)); expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_miniLeftOffsetX, _dockedOffsetY)); }); - testWidgets('miniEndDocked', (WidgetTester tester) async { + testWidgetsWithLeakTracking('miniEndDocked', (WidgetTester tester) async { await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.miniEndDocked)); expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_miniRightOffsetX, _dockedOffsetY)); @@ -1000,7 +1000,7 @@ void main() { ); } - testWidgets('startFloat', (WidgetTester tester) async { + testWidgetsWithLeakTracking('startFloat', (WidgetTester tester) async { const Rect defaultRect = Rect.fromLTRB(16.0, 478.0, 72.0, 534.0); // Positioned relative to BottomNavigationBar const Rect bottomNavigationBarRect = Rect.fromLTRB(16.0, 422.0, 72.0, 478.0); @@ -1018,7 +1018,7 @@ void main() { ); }); - testWidgets('miniStartFloat', (WidgetTester tester) async { + testWidgetsWithLeakTracking('miniStartFloat', (WidgetTester tester) async { const Rect defaultRect = Rect.fromLTRB(12.0, 490.0, 60.0, 538.0); // Positioned relative to BottomNavigationBar const Rect bottomNavigationBarRect = Rect.fromLTRB(12.0, 434.0, 60.0, 482.0); @@ -1055,7 +1055,7 @@ void main() { ); }); - testWidgets('miniCenterFloat', (WidgetTester tester) async { + testWidgetsWithLeakTracking('miniCenterFloat', (WidgetTester tester) async { const Rect defaultRect = Rect.fromLTRB(376.0, 490.0, 424.0, 538.0); // Positioned relative to BottomNavigationBar const Rect bottomNavigationBarRect = Rect.fromLTRB(376.0, 434.0, 424.0, 482.0); @@ -1074,7 +1074,7 @@ void main() { ); }); - testWidgets('endFloat', (WidgetTester tester) async { + testWidgetsWithLeakTracking('endFloat', (WidgetTester tester) async { const Rect defaultRect = Rect.fromLTRB(728.0, 478.0, 784.0, 534.0); // Positioned relative to BottomNavigationBar const Rect bottomNavigationBarRect = Rect.fromLTRB(728.0, 422.0, 784.0, 478.0); @@ -1092,7 +1092,7 @@ void main() { ); }); - testWidgets('miniEndFloat', (WidgetTester tester) async { + testWidgetsWithLeakTracking('miniEndFloat', (WidgetTester tester) async { const Rect defaultRect = Rect.fromLTRB(740.0, 490.0, 788.0, 538.0); // Positioned relative to BottomNavigationBar const Rect bottomNavigationBarRect = Rect.fromLTRB(740.0, 434.0, 788.0, 482.0); @@ -1363,7 +1363,7 @@ void main() { ); } - testWidgets('startDocked', (WidgetTester tester) async { + testWidgetsWithLeakTracking('startDocked', (WidgetTester tester) async { const Rect defaultRect = Rect.fromLTRB(16.0, 494.0, 72.0, 550.0); // Positioned relative to BottomNavigationBar const Rect bottomNavigationBarRect = Rect.fromLTRB(16.0, 466.0, 72.0, 522.0); @@ -1381,7 +1381,7 @@ void main() { ); }); - testWidgets('miniStartDocked', (WidgetTester tester) async { + testWidgetsWithLeakTracking('miniStartDocked', (WidgetTester tester) async { const Rect defaultRect = Rect.fromLTRB(12.0, 502.0, 60.0, 550.0); // Positioned relative to BottomNavigationBar const Rect bottomNavigationBarRect = Rect.fromLTRB(12.0, 470.0, 60.0, 518.0); @@ -1400,7 +1400,7 @@ void main() { ); }); - testWidgets('centerDocked', (WidgetTester tester) async { + testWidgetsWithLeakTracking('centerDocked', (WidgetTester tester) async { const Rect defaultRect = Rect.fromLTRB(372.0, 494.0, 428.0, 550.0); // Positioned relative to BottomNavigationBar const Rect bottomNavigationBarRect = Rect.fromLTRB(372.0, 466.0, 428.0, 522.0); @@ -1418,7 +1418,7 @@ void main() { ); }); - testWidgets('miniCenterDocked', (WidgetTester tester) async { + testWidgetsWithLeakTracking('miniCenterDocked', (WidgetTester tester) async { const Rect defaultRect = Rect.fromLTRB(376.0, 502.0, 424.0, 550.0); // Positioned relative to BottomNavigationBar const Rect bottomNavigationBarRect = Rect.fromLTRB(376.0, 470.0, 424.0, 518.0); @@ -1437,7 +1437,7 @@ void main() { ); }); - testWidgets('endDocked', (WidgetTester tester) async { + testWidgetsWithLeakTracking('endDocked', (WidgetTester tester) async { const Rect defaultRect = Rect.fromLTRB(728.0, 494.0, 784.0, 550.0); // Positioned relative to BottomNavigationBar const Rect bottomNavigationBarRect = Rect.fromLTRB(728.0, 466.0, 784.0, 522.0); @@ -1455,7 +1455,7 @@ void main() { ); }); - testWidgets('miniEndDocked', (WidgetTester tester) async { + testWidgetsWithLeakTracking('miniEndDocked', (WidgetTester tester) async { const Rect defaultRect = Rect.fromLTRB(740.0, 502.0, 788.0, 550.0); // Positioned relative to BottomNavigationBar const Rect bottomNavigationBarRect = Rect.fromLTRB(740.0, 470.0, 788.0, 518.0); diff --git a/packages/flutter/test/material/floating_action_button_test.dart b/packages/flutter/test/material/floating_action_button_test.dart index 7cda152c9e05..7c286f442396 100644 --- a/packages/flutter/test/material/floating_action_button_test.dart +++ b/packages/flutter/test/material/floating_action_button_test.dart @@ -325,7 +325,7 @@ void main() { expect(tester.widget(find.byType(PhysicalShape)).elevation, 6.0); }); - testWidgets('Floating Action Button states elevation', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Floating Action Button states elevation', (WidgetTester tester) async { final FocusNode focusNode = FocusNode(); await tester.pumpWidget( @@ -720,7 +720,7 @@ void main() { semantics.dispose(); }); - testWidgets('extended FAB hero transitions succeed', (WidgetTester tester) async { + testWidgetsWithLeakTracking('extended FAB hero transitions succeed', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/18782 await tester.pumpWidget( @@ -786,7 +786,7 @@ void main() { }); // This test prevents https://github.com/flutter/flutter/issues/20483 - testWidgets('Floating Action Button clips ink splash and highlight', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Floating Action Button clips ink splash and highlight', (WidgetTester tester) async { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MaterialApp( @@ -1167,7 +1167,7 @@ void main() { expect(tester.widget(find.byType(PhysicalShape)).elevation, 6.0); }); - testWidgets('Floating Action Button states elevation', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Floating Action Button states elevation', (WidgetTester tester) async { final FocusNode focusNode = FocusNode(); await tester.pumpWidget( @@ -1332,7 +1332,7 @@ void main() { // This test prevents https://github.com/flutter/flutter/issues/20483 - testWidgets('Floating Action Button clips ink splash and highlight', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Floating Action Button clips ink splash and highlight', (WidgetTester tester) async { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MaterialApp( diff --git a/packages/flutter/test/material/icon_button_test.dart b/packages/flutter/test/material/icon_button_test.dart index 949a2b1295ed..611a62cdfef8 100644 --- a/packages/flutter/test/material/icon_button_test.dart +++ b/packages/flutter/test/material/icon_button_test.dart @@ -2023,7 +2023,7 @@ void main() { expect(iconColor(), colorScheme.onSurface.withOpacity(0.38)); }); - testWidgets('Default IconButton meets a11y contrast guidelines - M3', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Default IconButton meets a11y contrast guidelines - M3', (WidgetTester tester) async { final FocusNode focusNode = FocusNode(); await tester.pumpWidget( diff --git a/packages/flutter/test/material/ink_well_test.dart b/packages/flutter/test/material/ink_well_test.dart index b0f2a59d9e9e..e2ffd3f116b7 100644 --- a/packages/flutter/test/material/ink_well_test.dart +++ b/packages/flutter/test/material/ink_well_test.dart @@ -1041,7 +1041,7 @@ testWidgetsWithLeakTracking('InkResponse radius can be updated', (WidgetTester t expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); }); - testWidgets('InkResponse containing selectable text changes mouse cursor when hovered', (WidgetTester tester) async { + testWidgetsWithLeakTracking('InkResponse containing selectable text changes mouse cursor when hovered', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/104595. await tester.pumpWidget(MaterialApp( home: SelectionArea( diff --git a/packages/flutter/test/material/input_decorator_test.dart b/packages/flutter/test/material/input_decorator_test.dart index dbcca1b8197b..edf9bec88c35 100644 --- a/packages/flutter/test/material/input_decorator_test.dart +++ b/packages/flutter/test/material/input_decorator_test.dart @@ -1668,7 +1668,7 @@ void runAllTests({ required bool useMaterial3 }) { expect(find.text('errorText'), findsOneWidget); }); - testWidgets('InputDecoration shows error border for errorText and error widget', (WidgetTester tester) async { + testWidgetsWithLeakTracking('InputDecoration shows error border for errorText and error widget', (WidgetTester tester) async { const InputBorder errorBorder = OutlineInputBorder( borderSide: BorderSide(color: Colors.red, width: 1.5), ); diff --git a/packages/flutter/test/material/list_tile_theme_test.dart b/packages/flutter/test/material/list_tile_theme_test.dart index f779e489b93f..4be26d698df1 100644 --- a/packages/flutter/test/material/list_tile_theme_test.dart +++ b/packages/flutter/test/material/list_tile_theme_test.dart @@ -746,7 +746,7 @@ void main() { expect(find.byType(Material), paints..rect(color: selectedTileColor)); }); - testWidgets('ListTile uses ListTileTheme shape in a drawer', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListTile uses ListTileTheme shape in a drawer', (WidgetTester tester) async { // This is a regression test for https://github.com/flutter/flutter/issues/106303 final GlobalKey scaffoldKey = GlobalKey(); diff --git a/packages/flutter/test/material/material_button_test.dart b/packages/flutter/test/material/material_button_test.dart index 3ef6687f05f9..e68e9d851180 100644 --- a/packages/flutter/test/material/material_button_test.dart +++ b/packages/flutter/test/material/material_button_test.dart @@ -243,7 +243,7 @@ void main() { expect(material.color, const Color(0xff00ff00)); }); - testWidgets('Default MaterialButton meets a11y contrast guidelines', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Default MaterialButton meets a11y contrast guidelines', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( diff --git a/packages/flutter/test/material/outlined_button_test.dart b/packages/flutter/test/material/outlined_button_test.dart index 6a8f62607411..cc6ec12f4fcf 100644 --- a/packages/flutter/test/material/outlined_button_test.dart +++ b/packages/flutter/test/material/outlined_button_test.dart @@ -322,7 +322,7 @@ void main() { focusNode.dispose(); }); - testWidgets('Default OutlinedButton meets a11y contrast guidelines', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Default OutlinedButton meets a11y contrast guidelines', (WidgetTester tester) async { final FocusNode focusNode = FocusNode(); await tester.pumpWidget( @@ -371,7 +371,7 @@ void main() { skip: isBrowser, // https://github.com/flutter/flutter/issues/44115 ); - testWidgets('OutlinedButton with colored theme meets a11y contrast guidelines', (WidgetTester tester) async { + testWidgetsWithLeakTracking('OutlinedButton with colored theme meets a11y contrast guidelines', (WidgetTester tester) async { final FocusNode focusNode = FocusNode(); Color getTextColor(Set states) { @@ -1837,7 +1837,7 @@ void main() { expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); }); - testWidgets('OutlinedButton in SelectionArea changes mouse cursor when hovered', (WidgetTester tester) async { + testWidgetsWithLeakTracking('OutlinedButton in SelectionArea changes mouse cursor when hovered', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/104595. await tester.pumpWidget(MaterialApp( home: SelectionArea( diff --git a/packages/flutter/test/material/page_selector_test.dart b/packages/flutter/test/material/page_selector_test.dart index 431770fd6460..b1bf60008c4d 100644 --- a/packages/flutter/test/material/page_selector_test.dart +++ b/packages/flutter/test/material/page_selector_test.dart @@ -206,7 +206,7 @@ void main() { expect(indicatorColors(tester), const [kBlue, kRed, kRed]); }); - testWidgets('PageSelector indicatorSize', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageSelector indicatorSize', (WidgetTester tester) async { final TabController tabController = TabController( vsync: const TestVSync(), initialIndex: 1, diff --git a/packages/flutter/test/material/page_test.dart b/packages/flutter/test/material/page_test.dart index 56b2d40642a3..8b130928a9ab 100644 --- a/packages/flutter/test/material/page_test.dart +++ b/packages/flutter/test/material/page_test.dart @@ -1041,7 +1041,7 @@ void main() { expect(pageTapCount, 1); }, variant: const TargetPlatformVariant({ TargetPlatform.iOS, TargetPlatform.macOS })); - testWidgets('A MaterialPageRoute should slide out with CupertinoPageTransition when a compatible PageRoute is pushed on top of it', (WidgetTester tester) async { + testWidgetsWithLeakTracking('A MaterialPageRoute should slide out with CupertinoPageTransition when a compatible PageRoute is pushed on top of it', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/44864. await tester.pumpWidget( diff --git a/packages/flutter/test/material/paginated_data_table_test.dart b/packages/flutter/test/material/paginated_data_table_test.dart index 88fd469a93ee..8004dc531276 100644 --- a/packages/flutter/test/material/paginated_data_table_test.dart +++ b/packages/flutter/test/material/paginated_data_table_test.dart @@ -67,10 +67,11 @@ class TestDataSource extends DataTableSource { void main() { final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); - testWidgetsWithLeakTracking('PaginatedDataTable paging', (WidgetTester tester) async { - final TestDataSource source = TestDataSource(); - addTearDown(source.dispose); + late TestDataSource source; + setUp(() => source = TestDataSource()); + tearDown(() => source.dispose()); + testWidgetsWithLeakTracking('PaginatedDataTable paging', (WidgetTester tester) async { final List log = []; await tester.pumpWidget(MaterialApp( @@ -172,8 +173,7 @@ void main() { log.clear(); }); - testWidgets('PaginatedDataTable footer page number', (WidgetTester tester) async { - final TestDataSource source = TestDataSource(); + testWidgetsWithLeakTracking('PaginatedDataTable footer page number', (WidgetTester tester) async { int rowsPerPage = 2; Widget buildTable(TestDataSource source, int rowsPerPage) { @@ -303,9 +303,10 @@ void main() { expect(find.text('497–500 of 500'), findsOneWidget); }); - testWidgets('PaginatedDataTable control test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PaginatedDataTable control test', (WidgetTester tester) async { TestDataSource source = TestDataSource() ..generation = 42; + addTearDown(source.dispose); final List log = []; @@ -369,6 +370,7 @@ void main() { source = TestDataSource() ..generation = 15; + addTearDown(source.dispose); await tester.pumpWidget(MaterialApp( home: buildTable(source), @@ -396,11 +398,11 @@ void main() { log.clear(); }); - testWidgets('PaginatedDataTable text alignment', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PaginatedDataTable text alignment', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( home: PaginatedDataTable( header: const Text('HEADER'), - source: TestDataSource(), + source: source, rowsPerPage: 8, availableRowsPerPage: const [ 8, 9, @@ -418,17 +420,20 @@ void main() { expect(tester.getTopRight(find.text('8')).dx, tester.getTopRight(find.text('Rows per page:')).dx + 40.0); // per spec }); - testWidgets('PaginatedDataTable with and without header and actions', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PaginatedDataTable with and without header and actions', (WidgetTester tester) async { await binding.setSurfaceSize(const Size(800, 800)); const String headerText = 'HEADER'; final List actions = [ IconButton(onPressed: () {}, icon: const Icon(Icons.add)), ]; + final TestDataSource source = TestDataSource(allowSelection: true); + addTearDown(source.dispose); + Widget buildTable({String? header, List? actions}) => MaterialApp( home: PaginatedDataTable( header: header != null ? Text(header) : null, actions: actions, - source: TestDataSource(allowSelection: true), + source: source, columns: const [ DataColumn(label: Text('Name')), DataColumn(label: Text('Calories'), numeric: true), @@ -454,8 +459,7 @@ void main() { await binding.setSurfaceSize(null); }); - testWidgets('PaginatedDataTable with large text', (WidgetTester tester) async { - final TestDataSource source = TestDataSource(); + testWidgetsWithLeakTracking('PaginatedDataTable with large text', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( home: MediaQuery( data: const MediaQueryData( @@ -491,8 +495,7 @@ void main() { expect(tester.getTopRight(find.text('501')).dx, greaterThanOrEqualTo(tester.getTopRight(find.text('Rows per page:')).dx + 40.0)); }, skip: isBrowser); // https://github.com/flutter/flutter/issues/43433 - testWidgets('PaginatedDataTable footer scrolls', (WidgetTester tester) async { - final TestDataSource source = TestDataSource(); + testWidgetsWithLeakTracking('PaginatedDataTable footer scrolls', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Align( @@ -527,9 +530,7 @@ void main() { expect(tester.getTopLeft(find.text('Rows per page:')).dx, 18.0); // 14 padding in the footer row, 4 padding from the card }); - testWidgets('PaginatedDataTable custom row height', (WidgetTester tester) async { - final TestDataSource source = TestDataSource(); - + testWidgetsWithLeakTracking('PaginatedDataTable custom row height', (WidgetTester tester) async { Widget buildCustomHeightPaginatedTable({ double? dataRowHeight, double? dataRowMinHeight, @@ -619,7 +620,7 @@ void main() { ).size.height, 51.0); }); - testWidgets('PaginatedDataTable custom horizontal padding - checkbox', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PaginatedDataTable custom horizontal padding - checkbox', (WidgetTester tester) async { const double defaultHorizontalMargin = 24.0; const double defaultColumnSpacing = 56.0; const double customHorizontalMargin = 10.0; @@ -635,6 +636,7 @@ void main() { await binding.setSurfaceSize(const Size(width, height)); final TestDataSource source = TestDataSource(allowSelection: true); + addTearDown(source.dispose); Finder cellContent; Finder checkbox; Finder padding; @@ -782,12 +784,11 @@ void main() { await binding.setSurfaceSize(originalSize); }); - testWidgets('PaginatedDataTable custom horizontal padding - no checkbox', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PaginatedDataTable custom horizontal padding - no checkbox', (WidgetTester tester) async { const double defaultHorizontalMargin = 24.0; const double defaultColumnSpacing = 56.0; const double customHorizontalMargin = 10.0; const double customColumnSpacing = 15.0; - final TestDataSource source = TestDataSource(); Finder cellContent; Finder padding; @@ -905,9 +906,7 @@ void main() { ); }); - testWidgets('PaginatedDataTable table fills Card width', (WidgetTester tester) async { - final TestDataSource source = TestDataSource(); - + testWidgetsWithLeakTracking('PaginatedDataTable table fills Card width', (WidgetTester tester) async { // 800 is wide enough to ensure that all of the columns fit in the // Card. The test makes sure that the DataTable is exactly as wide // as the Card, minus the Card's margin. @@ -969,14 +968,16 @@ void main() { await binding.setSurfaceSize(originalSize); }); - testWidgets('PaginatedDataTable with optional column checkbox', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PaginatedDataTable with optional column checkbox', (WidgetTester tester) async { await binding.setSurfaceSize(const Size(800, 800)); addTearDown(() => binding.setSurfaceSize(null)); + final TestDataSource source = TestDataSource(allowSelection: true); + addTearDown(source.dispose); Widget buildTable(bool checkbox) => MaterialApp( home: PaginatedDataTable( header: const Text('Test table'), - source: TestDataSource(allowSelection: true), + source: source, showCheckboxColumn: checkbox, columns: const [ DataColumn(label: Text('Name')), @@ -993,11 +994,14 @@ void main() { expect(find.byType(Checkbox), findsNothing); }); - testWidgets('Table should not use decoration from DataTableTheme', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Table should not use decoration from DataTableTheme', (WidgetTester tester) async { final Size originalSize = binding.renderView.size; await binding.setSurfaceSize(const Size(800, 800)); Widget buildTable() { + final TestDataSource source = TestDataSource(allowSelection: true); + addTearDown(source.dispose); + return MaterialApp( theme: ThemeData.light().copyWith( dataTableTheme: const DataTableThemeData( @@ -1006,7 +1010,7 @@ void main() { ), home: PaginatedDataTable( header: const Text('Test table'), - source: TestDataSource(allowSelection: true), + source: source, columns: const [ DataColumn(label: Text('Name')), DataColumn(label: Text('Calories'), numeric: true), @@ -1024,12 +1028,15 @@ void main() { await binding.setSurfaceSize(originalSize); }); - testWidgets('dataRowMinHeight & dataRowMaxHeight if not set will use DataTableTheme', (WidgetTester tester) async { + testWidgetsWithLeakTracking('dataRowMinHeight & dataRowMaxHeight if not set will use DataTableTheme', (WidgetTester tester) async { addTearDown(() => binding.setSurfaceSize(null)); await binding.setSurfaceSize(const Size(800, 800)); const double minMaxDataRowHeight = 30.0; + final TestDataSource source = TestDataSource(allowSelection: true); + addTearDown(source.dispose); + await tester.pumpWidget(MaterialApp( theme: ThemeData( dataTableTheme: const DataTableThemeData( @@ -1039,7 +1046,7 @@ void main() { ), home: PaginatedDataTable( header: const Text('Test table'), - source: TestDataSource(allowSelection: true), + source: source, columns: const [ DataColumn(label: Text('Name')), DataColumn(label: Text('Calories'), numeric: true), @@ -1056,7 +1063,7 @@ void main() { expect(rowContainer.constraints?.maxHeight, minMaxDataRowHeight); }); - testWidgets('PaginatedDataTable custom checkboxHorizontalMargin properly applied', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PaginatedDataTable custom checkboxHorizontalMargin properly applied', (WidgetTester tester) async { const double customCheckboxHorizontalMargin = 15.0; const double customHorizontalMargin = 10.0; @@ -1070,6 +1077,8 @@ void main() { await binding.setSurfaceSize(const Size(width, height)); final TestDataSource source = TestDataSource(allowSelection: true); + addTearDown(source.dispose); + Finder cellContent; Finder checkbox; Finder padding; @@ -1122,17 +1131,20 @@ void main() { await binding.setSurfaceSize(originalSize); }); - testWidgets('Items selected text uses secondary color', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Items selected text uses secondary color', (WidgetTester tester) async { const Color selectedTextColor = Color(0xff00ddff); final ColorScheme colors = const ColorScheme.light().copyWith(secondary: selectedTextColor); final ThemeData theme = ThemeData.from(colorScheme: colors); + final TestDataSource source = TestDataSource(allowSelection: true); + addTearDown(source.dispose); + Widget buildTable() { return MaterialApp( theme: theme, home: PaginatedDataTable( header: const Text('Test table'), - source: TestDataSource(allowSelection: true), + source: source, columns: const [ DataColumn(label: Text('Name')), DataColumn(label: Text('Calories'), numeric: true), @@ -1161,7 +1173,7 @@ void main() { await binding.setSurfaceSize(null); }); - testWidgets('PaginatedDataTable arrowHeadColor set properly', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PaginatedDataTable arrowHeadColor set properly', (WidgetTester tester) async { await binding.setSurfaceSize(const Size(800, 800)); addTearDown(() => binding.setSurfaceSize(null)); const Color arrowHeadColor = Color(0xFFE53935); @@ -1172,7 +1184,7 @@ void main() { arrowHeadColor: arrowHeadColor, showFirstLastButtons: true, header: const Text('Test table'), - source: TestDataSource(), + source: source, columns: const [ DataColumn(label: Text('Name')), DataColumn(label: Text('Calories'), numeric: true), @@ -1190,7 +1202,7 @@ void main() { expect(icons.elementAt(3).color, arrowHeadColor); }); - testWidgets('OverflowBar header left alignment', (WidgetTester tester) async { + testWidgetsWithLeakTracking('OverflowBar header left alignment', (WidgetTester tester) async { // Test an old special case that tried to align the first child of a ButtonBar // and the left edge of a Text header widget. Still possible with OverflowBar // albeit without any special case in the implementation's build method. @@ -1199,7 +1211,7 @@ void main() { home: PaginatedDataTable( header: header, rowsPerPage: 2, - source: TestDataSource(), + source: source, columns: const [ DataColumn(label: Text('Name')), DataColumn(label: Text('Calories'), numeric: true), @@ -1218,9 +1230,7 @@ void main() { expect(headerX, tester.getTopLeft(find.byType(ElevatedButton)).dx); }); - testWidgets('PaginatedDataTable can be scrolled using ScrollController', (WidgetTester tester) async { - final TestDataSource source = TestDataSource(); - addTearDown(source.dispose); + testWidgetsWithLeakTracking('PaginatedDataTable can be scrolled using ScrollController', (WidgetTester tester) async { final ScrollController scrollController = ScrollController(); addTearDown(scrollController.dispose); @@ -1269,11 +1279,9 @@ void main() { expect(scrollController.offset, 50.0); }); - testWidgets('PaginatedDataTable uses PrimaryScrollController when primary ', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PaginatedDataTable uses PrimaryScrollController when primary ', (WidgetTester tester) async { final ScrollController primaryScrollController = ScrollController(); addTearDown(primaryScrollController.dispose); - final TestDataSource source = TestDataSource(); - addTearDown(source.dispose); await tester.pumpWidget( MaterialApp( @@ -1303,9 +1311,8 @@ void main() { expect(footerScrollView.controller, null); }); - testWidgets('PaginatedDataTable custom heading row color', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PaginatedDataTable custom heading row color', (WidgetTester tester) async { const MaterialStateProperty headingRowColor = MaterialStatePropertyAll(Color(0xffFF0000)); - final TestDataSource source = TestDataSource(); await tester.pumpWidget( MaterialApp( diff --git a/packages/flutter/test/material/persistent_bottom_sheet_test.dart b/packages/flutter/test/material/persistent_bottom_sheet_test.dart index cb8025e14f91..8254715db181 100644 --- a/packages/flutter/test/material/persistent_bottom_sheet_test.dart +++ b/packages/flutter/test/material/persistent_bottom_sheet_test.dart @@ -23,7 +23,7 @@ void main() { expect(dyDelta1, isNot(moreOrLessEquals(dyDelta2, epsilon: 0.1))); } - testWidgets('Persistent draggableScrollableSheet localHistoryEntries test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Persistent draggableScrollableSheet localHistoryEntries test', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/110123 Widget buildFrame(Widget? bottomSheet) { return MaterialApp( @@ -79,7 +79,7 @@ void main() { }); // Regression test for https://github.com/flutter/flutter/issues/83668 - testWidgets('Scaffold.bottomSheet update test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Scaffold.bottomSheet update test', (WidgetTester tester) async { Widget buildFrame(Widget? bottomSheet) { return MaterialApp( home: Scaffold( @@ -123,7 +123,7 @@ void main() { expect(buildCount, equals(2)); }); - testWidgets('Verify that a persistent BottomSheet cannot be dismissed', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Verify that a persistent BottomSheet cannot be dismissed', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( home: Scaffold( body: const Center(child: Text('body')), @@ -186,7 +186,7 @@ void main() { expect(find.text('Two'), findsNothing); }); - testWidgets('Verify DraggableScrollableSheet.shouldCloseOnMinExtent == false prevents dismissal', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Verify DraggableScrollableSheet.shouldCloseOnMinExtent == false prevents dismissal', (WidgetTester tester) async { final GlobalKey scaffoldKey = GlobalKey(); await tester.pumpWidget(MaterialApp( @@ -259,7 +259,7 @@ void main() { expect(find.text('Two'), findsNothing); }); - testWidgets('Verify that a scrollControlled BottomSheet can be dismissed', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Verify that a scrollControlled BottomSheet can be dismissed', (WidgetTester tester) async { final GlobalKey scaffoldKey = GlobalKey(); await tester.pumpWidget(MaterialApp( @@ -298,7 +298,7 @@ void main() { expect(find.text('Two'), findsNothing); }); - testWidgets('Verify that a persistent BottomSheet can fling up and hide the fab', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Verify that a persistent BottomSheet can fling up and hide the fab', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -348,7 +348,7 @@ void main() { expect(find.byType(FloatingActionButton).hitTestable(), findsNothing); }); - testWidgets('Verify that a back button resets a persistent BottomSheet', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Verify that a back button resets a persistent BottomSheet', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -409,7 +409,7 @@ void main() { expect(find.text('Item 22'), findsNothing); }); - testWidgets('Verify that a scrollable BottomSheet hides the fab when scrolled up', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Verify that a scrollable BottomSheet hides the fab when scrolled up', (WidgetTester tester) async { final GlobalKey scaffoldKey = GlobalKey(); await tester.pumpWidget(MaterialApp( @@ -530,7 +530,7 @@ void main() { ); }); - testWidgets('Scaffold.bottomSheet', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Scaffold.bottomSheet', (WidgetTester tester) async { final Key bottomSheetKey = UniqueKey(); await tester.pumpWidget( diff --git a/packages/flutter/test/material/popup_menu_test.dart b/packages/flutter/test/material/popup_menu_test.dart index 79e3a7f6f6b1..e2fa281b6387 100644 --- a/packages/flutter/test/material/popup_menu_test.dart +++ b/packages/flutter/test/material/popup_menu_test.dart @@ -3741,7 +3741,7 @@ void main() { expect(_labelStyle(tester, 'Item 1')!.fontStyle, customTextStyle.fontStyle); }); - testWidgets('CheckedPopupMenuItem.onTap callback is called when defined', (WidgetTester tester) async { + testWidgetsWithLeakTracking('CheckedPopupMenuItem.onTap callback is called when defined', (WidgetTester tester) async { int count = 0; await tester.pumpWidget( TestApp( diff --git a/packages/flutter/test/material/progress_indicator_test.dart b/packages/flutter/test/material/progress_indicator_test.dart index 91fe68bc3a11..12ec99d24994 100644 --- a/packages/flutter/test/material/progress_indicator_test.dart +++ b/packages/flutter/test/material/progress_indicator_test.dart @@ -718,7 +718,7 @@ void main() { expect(tester.hasRunningAnimations, isTrue); }); - testWidgets('Material2 - RefreshProgressIndicator uses expected animation', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material2 - RefreshProgressIndicator uses expected animation', (WidgetTester tester) async { final AnimationSheetBuilder animationSheet = AnimationSheetBuilder(frameSize: const Size(50, 50)); addTearDown(animationSheet.dispose); @@ -735,7 +735,7 @@ void main() { ); }, skip: isBrowser); // https://github.com/flutter/flutter/issues/56001 - testWidgets('Material3 - RefreshProgressIndicator uses expected animation', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material3 - RefreshProgressIndicator uses expected animation', (WidgetTester tester) async { final AnimationSheetBuilder animationSheet = AnimationSheetBuilder(frameSize: const Size(50, 50)); addTearDown(animationSheet.dispose); @@ -1017,7 +1017,7 @@ void main() { handle.dispose(); }); - testWidgets('Material2 - Indeterminate CircularProgressIndicator uses expected animation', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material2 - Indeterminate CircularProgressIndicator uses expected animation', (WidgetTester tester) async { final AnimationSheetBuilder animationSheet = AnimationSheetBuilder(frameSize: const Size(40, 40)); addTearDown(animationSheet.dispose); @@ -1040,7 +1040,7 @@ void main() { ); }, skip: isBrowser); // https://github.com/flutter/flutter/issues/56001 - testWidgets('Material3 - Indeterminate CircularProgressIndicator uses expected animation', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material3 - Indeterminate CircularProgressIndicator uses expected animation', (WidgetTester tester) async { final AnimationSheetBuilder animationSheet = AnimationSheetBuilder(frameSize: const Size(40, 40)); addTearDown(animationSheet.dispose); diff --git a/packages/flutter/test/material/scaffold_test.dart b/packages/flutter/test/material/scaffold_test.dart index 28f87f4aa85c..b883025a5d20 100644 --- a/packages/flutter/test/material/scaffold_test.dart +++ b/packages/flutter/test/material/scaffold_test.dart @@ -271,7 +271,7 @@ void main() { expect(tester.binding.transientCallbackCount, greaterThan(0)); }); - testWidgets('Floating action button shrinks when bottom sheet becomes dominant', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Floating action button shrinks when bottom sheet becomes dominant', (WidgetTester tester) async { final DraggableScrollableController draggableController = DraggableScrollableController(); const double kBottomSheetDominatesPercentage = 0.3; @@ -310,7 +310,7 @@ void main() { } }); - testWidgets('Scaffold shows scrim when bottom sheet becomes dominant', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Scaffold shows scrim when bottom sheet becomes dominant', (WidgetTester tester) async { final DraggableScrollableController draggableController = DraggableScrollableController(); const double kBottomSheetDominatesPercentage = 0.3; const double kMinBottomSheetScrimOpacity = 0.1; @@ -621,7 +621,7 @@ void main() { expect(appBarBottomRight, equals(sheetTopRight)); }); - testWidgets('BottomSheet bottom padding is not consumed by viewInsets', (WidgetTester tester) async { + testWidgetsWithLeakTracking('BottomSheet bottom padding is not consumed by viewInsets', (WidgetTester tester) async { final Widget child = Directionality( textDirection: TextDirection.ltr, child: Scaffold( @@ -2155,7 +2155,7 @@ void main() { }); group('FlutterError control test', () { - testWidgets('showBottomSheet() while Scaffold has bottom sheet', + testWidgetsWithLeakTracking('showBottomSheet() while Scaffold has bottom sheet', (WidgetTester tester) async { final GlobalKey key = GlobalKey(); await tester.pumpWidget( @@ -2658,7 +2658,7 @@ void main() { expect(summary.toString(), 'The showSnackBar() method cannot be called during build.'); }); - testWidgets('Persistent BottomSheet is not dismissible via a11y means', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Persistent BottomSheet is not dismissible via a11y means', (WidgetTester tester) async { final Key bottomSheetKey = UniqueKey(); await tester.pumpWidget(MaterialApp( @@ -2681,7 +2681,7 @@ void main() { }); // Regression test for https://github.com/flutter/flutter/issues/117004 - testWidgets('can rebuild and remove bottomSheet at the same time', (WidgetTester tester) async { + testWidgetsWithLeakTracking('can rebuild and remove bottomSheet at the same time', (WidgetTester tester) async { bool themeIsLight = true; bool? defaultBottomSheet = true; final GlobalKey bottomSheetKey1 = GlobalKey(); diff --git a/packages/flutter/test/material/search_bar_theme_test.dart b/packages/flutter/test/material/search_bar_theme_test.dart index cfa506499784..358c7ddb79e3 100644 --- a/packages/flutter/test/material/search_bar_theme_test.dart +++ b/packages/flutter/test/material/search_bar_theme_test.dart @@ -242,19 +242,19 @@ void main() { expect(trailingRect.right, barRect.right - 16.0); } - testWidgets('SearchBar properties overrides defaults', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SearchBar properties overrides defaults', (WidgetTester tester) async { await tester.pumpWidget(buildFrame(useSearchBarProperties: true)); await tester.pumpAndSettle(); // allow the animations to finish checkSearchBar(tester); }); - testWidgets('SearchBar theme data overrides defaults', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SearchBar theme data overrides defaults', (WidgetTester tester) async { await tester.pumpWidget(buildFrame(searchBarThemeData: searchBarTheme)); await tester.pumpAndSettle(); checkSearchBar(tester); }); - testWidgets('Overall Theme SearchBar theme overrides defaults', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Overall Theme SearchBar theme overrides defaults', (WidgetTester tester) async { await tester.pumpWidget(buildFrame(overallTheme: searchBarTheme)); await tester.pumpAndSettle(); checkSearchBar(tester); @@ -262,7 +262,7 @@ void main() { // Same as the previous tests with empty SearchBarThemeData's instead of null. - testWidgets('SearchBar properties overrides defaults, empty theme and overall theme', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SearchBar properties overrides defaults, empty theme and overall theme', (WidgetTester tester) async { await tester.pumpWidget(buildFrame(useSearchBarProperties: true, searchBarThemeData: const SearchBarThemeData(), overallTheme: const SearchBarThemeData())); @@ -270,14 +270,14 @@ void main() { checkSearchBar(tester); }); - testWidgets('SearchBar theme overrides defaults and overall theme', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SearchBar theme overrides defaults and overall theme', (WidgetTester tester) async { await tester.pumpWidget(buildFrame(searchBarThemeData: searchBarTheme, overallTheme: const SearchBarThemeData())); await tester.pumpAndSettle(); // allow the animations to finish checkSearchBar(tester); }); - testWidgets('Overall Theme SearchBar theme overrides defaults and null theme', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Overall Theme SearchBar theme overrides defaults and null theme', (WidgetTester tester) async { await tester.pumpWidget(buildFrame(overallTheme: searchBarTheme)); await tester.pumpAndSettle(); // allow the animations to finish checkSearchBar(tester); diff --git a/packages/flutter/test/material/segmented_button_test.dart b/packages/flutter/test/material/segmented_button_test.dart index bc53f6766d20..3f8053b940fa 100644 --- a/packages/flutter/test/material/segmented_button_test.dart +++ b/packages/flutter/test/material/segmented_button_test.dart @@ -97,7 +97,7 @@ void main() { expect(material.type, MaterialType.transparency); }); - testWidgets('SegmentedButton supports exclusive choice by default', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SegmentedButton supports exclusive choice by default', (WidgetTester tester) async { int callbackCount = 0; int selectedSegment = 2; @@ -147,7 +147,7 @@ void main() { expect(selectedSegment, 3); }); - testWidgets('SegmentedButton supports multiple selected segments', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SegmentedButton supports multiple selected segments', (WidgetTester tester) async { int callbackCount = 0; Set selection = {1}; @@ -202,7 +202,7 @@ void main() { expect(selection, {2, 3}); }); -testWidgets('SegmentedButton allows for empty selection', (WidgetTester tester) async { +testWidgetsWithLeakTracking('SegmentedButton allows for empty selection', (WidgetTester tester) async { int callbackCount = 0; int? selectedSegment = 1; @@ -255,7 +255,7 @@ testWidgets('SegmentedButton allows for empty selection', (WidgetTester tester) expect(selectedSegment, 3); }); -testWidgets('SegmentedButton shows checkboxes for selected segments', (WidgetTester tester) async { +testWidgetsWithLeakTracking('SegmentedButton shows checkboxes for selected segments', (WidgetTester tester) async { Widget frameWithSelection(int selected) { return Material( child: boilerplate( @@ -292,7 +292,7 @@ testWidgets('SegmentedButton shows checkboxes for selected segments', (WidgetTes expect(find.byIcon(Icons.check), findsOneWidget); }); - testWidgets('SegmentedButton shows selected checkboxes in place of icon if it has a label as well', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SegmentedButton shows selected checkboxes in place of icon if it has a label as well', (WidgetTester tester) async { Widget frameWithSelection(int selected) { return Material( child: boilerplate( @@ -335,7 +335,7 @@ testWidgets('SegmentedButton shows checkboxes for selected segments', (WidgetTes expect(find.byIcon(Icons.add_alarm), findsNothing); }); - testWidgets('SegmentedButton shows selected checkboxes next to icon if there is no label', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SegmentedButton shows selected checkboxes next to icon if there is no label', (WidgetTester tester) async { Widget frameWithSelection(int selected) { return Material( child: boilerplate( @@ -376,7 +376,7 @@ testWidgets('SegmentedButton shows checkboxes for selected segments', (WidgetTes }); - testWidgets('SegmentedButtons have correct semantics', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SegmentedButtons have correct semantics', (WidgetTester tester) async { final SemanticsTester semantics = SemanticsTester(tester); await tester.pumpWidget( @@ -455,7 +455,7 @@ testWidgets('SegmentedButton shows checkboxes for selected segments', (WidgetTes }); - testWidgets('Multi-select SegmentedButtons have correct semantics', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Multi-select SegmentedButtons have correct semantics', (WidgetTester tester) async { final SemanticsTester semantics = SemanticsTester(tester); await tester.pumpWidget( @@ -532,7 +532,7 @@ testWidgets('SegmentedButton shows checkboxes for selected segments', (WidgetTes semantics.dispose(); }); - testWidgets('SegmentedButton default overlayColor and foregroundColor resolve pressed state', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SegmentedButton default overlayColor and foregroundColor resolve pressed state', (WidgetTester tester) async { final ThemeData theme = ThemeData(useMaterial3: true); await tester.pumpWidget( @@ -580,7 +580,7 @@ testWidgets('SegmentedButton shows checkboxes for selected segments', (WidgetTes expect(material.textStyle?.color, theme.colorScheme.onSurface); }); - testWidgets('SegmentedButton has no tooltips by default', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SegmentedButton has no tooltips by default', (WidgetTester tester) async { final ThemeData theme = ThemeData(useMaterial3: true); await tester.pumpWidget( MaterialApp( @@ -604,7 +604,7 @@ testWidgets('SegmentedButton shows checkboxes for selected segments', (WidgetTes expect(find.byType(Tooltip), findsNothing); }); - testWidgets('SegmentedButton has correct tooltips', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SegmentedButton has correct tooltips', (WidgetTester tester) async { final ThemeData theme = ThemeData(useMaterial3: true); await tester.pumpWidget( MaterialApp( diff --git a/packages/flutter/test/material/segmented_button_theme_test.dart b/packages/flutter/test/material/segmented_button_theme_test.dart index a273f3633e8a..5efee131502e 100644 --- a/packages/flutter/test/material/segmented_button_theme_test.dart +++ b/packages/flutter/test/material/segmented_button_theme_test.dart @@ -42,7 +42,7 @@ void main() { expect(description, []); }); - testWidgets('With no other configuration, defaults are used', (WidgetTester tester) async { + testWidgetsWithLeakTracking('With no other configuration, defaults are used', (WidgetTester tester) async { final ThemeData theme = ThemeData(useMaterial3: true); await tester.pumpWidget( MaterialApp( @@ -109,7 +109,7 @@ void main() { } }); - testWidgets('ThemeData.segmentedButtonTheme overrides defaults', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ThemeData.segmentedButtonTheme overrides defaults', (WidgetTester tester) async { final ThemeData theme = ThemeData( useMaterial3: true, segmentedButtonTheme: SegmentedButtonThemeData( @@ -202,7 +202,7 @@ void main() { } }); - testWidgets('SegmentedButtonTheme overrides ThemeData and defaults', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SegmentedButtonTheme overrides ThemeData and defaults', (WidgetTester tester) async { final SegmentedButtonThemeData global = SegmentedButtonThemeData( style: ButtonStyle( backgroundColor: MaterialStateProperty.resolveWith((Set states) { @@ -329,7 +329,7 @@ void main() { } }); - testWidgets('Widget parameters overrides SegmentedTheme, ThemeData and defaults', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Widget parameters overrides SegmentedTheme, ThemeData and defaults', (WidgetTester tester) async { final SegmentedButtonThemeData global = SegmentedButtonThemeData( style: ButtonStyle( backgroundColor: MaterialStateProperty.resolveWith((Set states) { diff --git a/packages/flutter/test/material/selection_area_test.dart b/packages/flutter/test/material/selection_area_test.dart index 8e19b78f6f7d..8e786831dc02 100644 --- a/packages/flutter/test/material/selection_area_test.dart +++ b/packages/flutter/test/material/selection_area_test.dart @@ -8,6 +8,7 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; Offset textOffsetToPosition(RenderParagraph paragraph, int offset) { @@ -17,7 +18,7 @@ Offset textOffsetToPosition(RenderParagraph paragraph, int offset) { } void main() { - testWidgets('SelectionArea uses correct selection controls', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SelectionArea uses correct selection controls', (WidgetTester tester) async { await tester.pumpWidget(const MaterialApp( home: SelectionArea( child: Text('abc'), @@ -39,7 +40,7 @@ void main() { } }, variant: TargetPlatformVariant.all()); - testWidgets('Does not crash when long pressing on padding after dragging', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Does not crash when long pressing on padding after dragging', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/123378 await tester.pumpWidget( const MaterialApp( @@ -70,11 +71,14 @@ void main() { }); - testWidgets('builds the default context menu by default', (WidgetTester tester) async { + testWidgetsWithLeakTracking('builds the default context menu by default', (WidgetTester tester) async { + final FocusNode focusNode = FocusNode(); + addTearDown(focusNode.dispose); + await tester.pumpWidget( MaterialApp( home: SelectionArea( - focusNode: FocusNode(), + focusNode: focusNode, child: const Text('How are you?'), ), ), @@ -97,12 +101,15 @@ void main() { skip: kIsWeb, // [intended] ); - testWidgets('builds a custom context menu if provided', (WidgetTester tester) async { + testWidgetsWithLeakTracking('builds a custom context menu if provided', (WidgetTester tester) async { final GlobalKey key = GlobalKey(); + final FocusNode focusNode = FocusNode(); + addTearDown(focusNode.dispose); + await tester.pumpWidget( MaterialApp( home: SelectionArea( - focusNode: FocusNode(), + focusNode: focusNode, contextMenuBuilder: ( BuildContext context, SelectableRegionState selectableRegionState, @@ -133,7 +140,7 @@ void main() { skip: kIsWeb, // [intended] ); - testWidgets('onSelectionChange is called when the selection changes', (WidgetTester tester) async { + testWidgetsWithLeakTracking('onSelectionChange is called when the selection changes', (WidgetTester tester) async { SelectedContent? content; await tester.pumpWidget(MaterialApp( @@ -165,7 +172,10 @@ void main() { expect(content!.plainText, 'How'); }); - testWidgets('stopping drag of end handle will show the toolbar', (WidgetTester tester) async { + testWidgetsWithLeakTracking('stopping drag of end handle will show the toolbar', (WidgetTester tester) async { + final FocusNode focusNode = FocusNode(); + addTearDown(focusNode.dispose); + // Regression test for https://github.com/flutter/flutter/issues/119314 await tester.pumpWidget( MaterialApp( @@ -177,7 +187,7 @@ void main() { children: [ const Text('How are you?'), SelectionArea( - focusNode: FocusNode(), + focusNode: focusNode, child: const Text('Good, and you?'), ), const Text('Fine, thank you.'), diff --git a/packages/flutter/test/material/snack_bar_test.dart b/packages/flutter/test/material/snack_bar_test.dart index bdef27eabbc0..bf7e4fe7b9fb 100644 --- a/packages/flutter/test/material/snack_bar_test.dart +++ b/packages/flutter/test/material/snack_bar_test.dart @@ -17,7 +17,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; void main() { - testWidgets('SnackBar control test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SnackBar control test', (WidgetTester tester) async { const String helloSnackBar = 'Hello SnackBar'; const Key tapTarget = Key('tap-target'); await tester.pumpWidget(MaterialApp( @@ -62,7 +62,7 @@ void main() { expect(find.text(helloSnackBar), findsNothing); }); - testWidgets('SnackBar twice test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SnackBar twice test', (WidgetTester tester) async { int snackBarCount = 0; const Key tapTarget = Key('tap-target'); await tester.pumpWidget(MaterialApp( @@ -137,7 +137,7 @@ void main() { expect(find.text('bar2'), findsNothing); }); - testWidgets('SnackBar cancel test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SnackBar cancel test', (WidgetTester tester) async { int snackBarCount = 0; const Key tapTarget = Key('tap-target'); late int time; @@ -223,7 +223,7 @@ void main() { expect(find.text('bar2'), findsNothing); }); - testWidgets('SnackBar dismiss test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SnackBar dismiss test', (WidgetTester tester) async { const Key tapTarget = Key('tap-target'); late DismissDirection dismissDirection; late double width; @@ -265,7 +265,7 @@ void main() { ); }); - testWidgets('SnackBar cannot be tapped twice', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SnackBar cannot be tapped twice', (WidgetTester tester) async { int tapCount = 0; await tester.pumpWidget(MaterialApp( home: Scaffold( @@ -304,7 +304,7 @@ void main() { expect(tapCount, equals(1)); }); - testWidgets('Material2 - Light theme SnackBar has dark background', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material2 - Light theme SnackBar has dark background', (WidgetTester tester) async { final ThemeData lightTheme = ThemeData.light(useMaterial3: false); await tester.pumpWidget( MaterialApp( @@ -346,7 +346,7 @@ void main() { expect(renderModel.color, equals(const Color(0xFF333333))); }); - testWidgets('Material3 - Light theme SnackBar has dark background', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material3 - Light theme SnackBar has dark background', (WidgetTester tester) async { final ThemeData lightTheme = ThemeData.light(useMaterial3: true); await tester.pumpWidget( MaterialApp( @@ -385,7 +385,7 @@ void main() { expect(renderModel.color, equals(lightTheme.colorScheme.inverseSurface)); }); - testWidgets('Dark theme SnackBar has light background', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Dark theme SnackBar has light background', (WidgetTester tester) async { final ThemeData darkTheme = ThemeData.dark(); await tester.pumpWidget( MaterialApp( @@ -424,7 +424,7 @@ void main() { expect(renderModel.color, equals(darkTheme.colorScheme.onSurface)); }); - testWidgets('Material2 - Dark theme SnackBar has primary text buttons', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material2 - Dark theme SnackBar has primary text buttons', (WidgetTester tester) async { final ThemeData darkTheme = ThemeData.dark(useMaterial3: false); await tester.pumpWidget( MaterialApp( @@ -463,7 +463,7 @@ void main() { expect(buttonTextStyle.color, equals(darkTheme.colorScheme.primary)); }); - testWidgets('Material3 - Dark theme SnackBar has primary text buttons', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material3 - Dark theme SnackBar has primary text buttons', (WidgetTester tester) async { final ThemeData darkTheme = ThemeData.dark(useMaterial3: true); await tester.pumpWidget( MaterialApp( @@ -502,7 +502,7 @@ void main() { expect(buttonTextStyle.color, equals(darkTheme.colorScheme.inversePrimary)); }); - testWidgets('SnackBar should inherit theme data from its ancestor.', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SnackBar should inherit theme data from its ancestor.', (WidgetTester tester) async { final SliderThemeData sliderTheme = SliderThemeData.fromPrimaryColors( primaryColor: Colors.black, primaryColorDark: Colors.black, @@ -636,7 +636,7 @@ void main() { expect(comparedTheme, themeAfterSnackBar); }); - testWidgets('Snackbar margin can be customized', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Snackbar margin can be customized', (WidgetTester tester) async { const double padding = 20.0; await tester.pumpWidget( MaterialApp( @@ -676,7 +676,7 @@ void main() { expect(snackBarBottomRight.dx, 800 - padding); // Device width is 800. }); - testWidgets('SnackbarBehavior.floating is positioned within safe area', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SnackbarBehavior.floating is positioned within safe area', (WidgetTester tester) async { const double viewPadding = 50.0; const double floatingSnackBarDefaultBottomMargin = 10.0; await tester.pumpWidget( @@ -723,7 +723,7 @@ void main() { ); }); - testWidgets('Snackbar padding can be customized', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Snackbar padding can be customized', (WidgetTester tester) async { const double padding = 20.0; await tester.pumpWidget( MaterialApp( @@ -766,7 +766,7 @@ void main() { expect(textTopRight.dy - snackBarTopRight.dy, padding); }); - testWidgets('Snackbar width can be customized', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Snackbar width can be customized', (WidgetTester tester) async { const double width = 200.0; await tester.pumpWidget( MaterialApp( @@ -805,7 +805,7 @@ void main() { expect(snackBarBottomRight.dx, (800 + width) / 2); // Device width is 800. }); - testWidgets('Snackbar width can be customized from ThemeData', + testWidgetsWithLeakTracking('Snackbar width can be customized from ThemeData', (WidgetTester tester) async { const double width = 200.0; await tester.pumpWidget( @@ -847,7 +847,7 @@ void main() { expect(snackBarBottomRight.dx, (800 + width) / 2); // Device width is 800. }); - testWidgets('Snackbar width customization takes preference of widget over theme', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Snackbar width customization takes preference of widget over theme', (WidgetTester tester) async { const double themeWidth = 200.0; const double widgetWidth = 400.0; await tester.pumpWidget( @@ -890,7 +890,7 @@ void main() { expect(snackBarBottomRight.dx, (800 + widgetWidth) / 2); // Device width is 800. }); - testWidgets('Material2 - Snackbar labels can be colored as MaterialColor', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material2 - Snackbar labels can be colored as MaterialColor', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( theme: ThemeData(useMaterial3: false), @@ -935,7 +935,7 @@ void main() { } }); - testWidgets('Material3 - Snackbar labels can be colored as MaterialColor', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material3 - Snackbar labels can be colored as MaterialColor', (WidgetTester tester) async { const MaterialColor usedColor = Colors.teal; await tester.pumpWidget( @@ -986,7 +986,7 @@ void main() { } }); - testWidgets('Snackbar labels can be colored as MaterialStateColor (Material 3)', + testWidgetsWithLeakTracking('Snackbar labels can be colored as MaterialStateColor (Material 3)', (WidgetTester tester) async { const _TestMaterialStateColor usedColor = _TestMaterialStateColor(); @@ -1038,7 +1038,7 @@ void main() { } }); - testWidgets('Material2 - SnackBar button text alignment', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material2 - SnackBar button text alignment', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: false), home: MediaQuery( @@ -1086,7 +1086,7 @@ void main() { expect(snackBarBottomRight.dy - actionTextBottomRight.dy, 17.0 + 40.0); // margin + bottom padding }); - testWidgets('Material3 - SnackBar button text alignment', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material3 - SnackBar button text alignment', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: true), home: MediaQuery( @@ -1248,7 +1248,7 @@ void main() { }, ); - testWidgets('SnackBar should push FloatingActionButton above', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SnackBar should push FloatingActionButton above', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( home: MediaQuery( data: const MediaQueryData( @@ -1303,7 +1303,7 @@ void main() { expect(fabRect.bottomRight.dy, snackBarTopRight.dy - defaultFabPadding); }); - testWidgets('Material2 - Floating SnackBar button text alignment', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material2 - Floating SnackBar button text alignment', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData( useMaterial3: false, @@ -1354,7 +1354,7 @@ void main() { expect(snackBarBottomRight.dy - actionTextBottomRight.dy, 27.0); // margin (with no bottom padding) }); - testWidgets('Material3 - Floating SnackBar button text alignment', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material3 - Floating SnackBar button text alignment', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData( useMaterial3: true, @@ -1525,7 +1525,7 @@ void main() { }, ); - testWidgets('SnackBarClosedReason', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SnackBarClosedReason', (WidgetTester tester) async { final GlobalKey scaffoldMessengerKey = GlobalKey(); bool actionPressed = false; SnackBarClosedReason? closedReason; @@ -1603,7 +1603,7 @@ void main() { expect(closedReason, equals(SnackBarClosedReason.timeout)); }); - testWidgets('accessible navigation behavior with action', (WidgetTester tester) async { + testWidgetsWithLeakTracking('accessible navigation behavior with action', (WidgetTester tester) async { final GlobalKey scaffoldKey = GlobalKey(); await tester.pumpWidget(MaterialApp( @@ -1646,7 +1646,7 @@ void main() { expect(find.text('ACTION'), findsNothing); }); - testWidgets('contributes dismiss semantics', (WidgetTester tester) async { + testWidgetsWithLeakTracking('contributes dismiss semantics', (WidgetTester tester) async { final SemanticsHandle handle = tester.ensureSemantics(); final GlobalKey scaffoldKey = GlobalKey(); @@ -1689,7 +1689,7 @@ void main() { handle.dispose(); }); - testWidgets('SnackBar default display duration test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SnackBar default display duration test', (WidgetTester tester) async { const String helloSnackBar = 'Hello SnackBar'; const Key tapTarget = Key('tap-target'); await tester.pumpWidget(MaterialApp( @@ -1737,7 +1737,7 @@ void main() { expect(find.text(helloSnackBar), findsNothing); }); - testWidgets('SnackBar handles updates to accessibleNavigation', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SnackBar handles updates to accessibleNavigation', (WidgetTester tester) async { Future boilerplate({ required bool accessibleNavigation }) { return tester.pumpWidget(MaterialApp( home: MediaQuery( @@ -1785,7 +1785,7 @@ void main() { expect(find.text('test'), findsNothing); }); - testWidgets('Snackbar calls onVisible once', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Snackbar calls onVisible once', (WidgetTester tester) async { const Key tapTarget = Key('tap-target'); int called = 0; await tester.pumpWidget(MaterialApp( @@ -1822,7 +1822,7 @@ void main() { expect(called, 1); }); - testWidgets('Snackbar does not call onVisible when it is queued', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Snackbar does not call onVisible when it is queued', (WidgetTester tester) async { const Key tapTarget = Key('tap-target'); int called = 0; await tester.pumpWidget(MaterialApp( @@ -2280,7 +2280,7 @@ void main() { 'Scaffold.bottomNavigationBar take up too much vertical space.\n' 'Consider constraining the size of these widgets to allow room for the SnackBar to be visible.'; - testWidgets('Snackbar with SnackBarBehavior.floating will assert when offset too high by a large Scaffold.floatingActionButton', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Snackbar with SnackBarBehavior.floating will assert when offset too high by a large Scaffold.floatingActionButton', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/84263 Future boilerplate({required double? fabHeight}) { return tester.pumpWidget( @@ -2317,7 +2317,7 @@ void main() { expect(tester.takeException(), isNull); }); - testWidgets('Material2 - Snackbar with SnackBarBehavior.floating will assert when offset too high by a large Scaffold.persistentFooterButtons', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material2 - Snackbar with SnackBarBehavior.floating will assert when offset too high by a large Scaffold.persistentFooterButtons', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/84263 await tester.pumpWidget( MaterialApp( @@ -2335,7 +2335,7 @@ void main() { expect(exception.message, offScreenMessage); }); - testWidgets('Material3 - Snackbar with SnackBarBehavior.floating will assert when offset too high by a large Scaffold.persistentFooterButtons', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material3 - Snackbar with SnackBarBehavior.floating will assert when offset too high by a large Scaffold.persistentFooterButtons', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/84263 await tester.pumpWidget( MaterialApp( @@ -2359,7 +2359,7 @@ void main() { expect(errorMessages.contains(offScreenMessage), isTrue); }); - testWidgets('Material2 - Snackbar with SnackBarBehavior.floating will assert when offset too high by a large Scaffold.bottomNavigationBar', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material2 - Snackbar with SnackBarBehavior.floating will assert when offset too high by a large Scaffold.bottomNavigationBar', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/84263 await tester.pumpWidget( MaterialApp( @@ -2376,7 +2376,7 @@ void main() { expect(exception.message, offScreenMessage); }); - testWidgets('Material3 - Snackbar with SnackBarBehavior.floating will assert when offset too high by a large Scaffold.bottomNavigationBar', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material3 - Snackbar with SnackBarBehavior.floating will assert when offset too high by a large Scaffold.bottomNavigationBar', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/84263 await tester.pumpWidget( MaterialApp( @@ -2474,7 +2474,7 @@ void main() { ); }); - testWidgets('SnackBars hero across transitions when using ScaffoldMessenger', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SnackBars hero across transitions when using ScaffoldMessenger', (WidgetTester tester) async { const String snackBarText = 'hello snackbar'; const String firstHeader = 'home'; const String secondHeader = 'second'; @@ -2621,7 +2621,7 @@ void main() { expect(find.text(snackBarText), findsOneWidget); }); - testWidgets('Material2 - SnackBars should be shown above the bottomSheet', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material2 - SnackBars should be shown above the bottomSheet', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: false), home: const Scaffold( @@ -2647,7 +2647,7 @@ void main() { await expectLater(find.byType(MaterialApp), matchesGoldenFile('m2_snack_bar.goldenTest.workWithBottomSheet.png')); }); - testWidgets('Material3 - SnackBars should be shown above the bottomSheet', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material3 - SnackBars should be shown above the bottomSheet', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: true), home: const Scaffold( @@ -2673,7 +2673,7 @@ void main() { await expectLater(find.byType(MaterialApp), matchesGoldenFile('m3_snack_bar.goldenTest.workWithBottomSheet.png')); }); - testWidgets('ScaffoldMessenger does not duplicate a SnackBar when presenting a MaterialBanner.', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ScaffoldMessenger does not duplicate a SnackBar when presenting a MaterialBanner.', (WidgetTester tester) async { const Key materialBannerTapTarget = Key('materialbanner-tap-target'); const Key snackBarTapTarget = Key('snackbar-tap-target'); const String snackBarText = 'SnackBar'; @@ -2730,7 +2730,7 @@ void main() { expect(find.text(materialBannerText), findsOneWidget); }); - testWidgets('Material2 - ScaffoldMessenger presents SnackBars to only the root Scaffold when Scaffolds are nested.', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material2 - ScaffoldMessenger presents SnackBars to only the root Scaffold when Scaffolds are nested.', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: false), home: Scaffold( @@ -2763,7 +2763,7 @@ void main() { expect(snackBarTopRight.dy, 465.0); }); - testWidgets('Material3 - ScaffoldMessenger presents SnackBars to only the root Scaffold when Scaffolds are nested.', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material3 - ScaffoldMessenger presents SnackBars to only the root Scaffold when Scaffolds are nested.', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: true), home: Scaffold( @@ -2797,7 +2797,7 @@ void main() { }); - testWidgets('ScaffoldMessengerState clearSnackBars works as expected', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ScaffoldMessengerState clearSnackBars works as expected', (WidgetTester tester) async { final List snackBars = ['Hello Snackbar', 'Hi Snackbar', 'Bye Snackbar']; int snackBarCounter = 0; const Key tapTarget = Key('tap-target'); @@ -2881,7 +2881,7 @@ void main() { ); } - testWidgets('Setting SnackBarBehavior.fixed will still assert for margin', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Setting SnackBarBehavior.fixed will still assert for margin', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/84935 await tester.pumpWidget(doBuildApp( behavior: SnackBarBehavior.fixed, @@ -2898,7 +2898,7 @@ void main() { ); }); - testWidgets('Default SnackBarBehavior will still assert for margin', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Default SnackBarBehavior will still assert for margin', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/84935 await tester.pumpWidget(doBuildApp( behavior: null, @@ -2915,7 +2915,7 @@ void main() { ); }); - testWidgets('Setting SnackBarBehavior.fixed will still assert for width', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Setting SnackBarBehavior.fixed will still assert for width', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/84935 await tester.pumpWidget(doBuildApp( behavior: SnackBarBehavior.fixed, @@ -2932,7 +2932,7 @@ void main() { ); }); - testWidgets('Default SnackBarBehavior will still assert for width', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Default SnackBarBehavior will still assert for width', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/84935 await tester.pumpWidget(doBuildApp( behavior: null, @@ -2950,7 +2950,7 @@ void main() { }); for (final double overflowThreshold in [-1.0, -.0001, 1.000001, 5]) { - testWidgets('SnackBar will assert for actionOverflowThreshold outside of 0-1 range', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SnackBar will assert for actionOverflowThreshold outside of 0-1 range', (WidgetTester tester) async { await tester.pumpWidget(doBuildApp( actionOverflowThreshold: overflowThreshold, behavior: SnackBarBehavior.fixed, @@ -2964,7 +2964,7 @@ void main() { }); } - testWidgets('Material2 - Snackbar by default clips BackdropFilter', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material2 - Snackbar by default clips BackdropFilter', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/98205 await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: false), @@ -2997,7 +2997,7 @@ void main() { await expectLater(find.byType(MaterialApp), matchesGoldenFile('m2_snack_bar.goldenTest.backdropFilter.png')); }); - testWidgets('Material3 - Snackbar by default clips BackdropFilter', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material3 - Snackbar by default clips BackdropFilter', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/98205 await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: true), @@ -3030,7 +3030,7 @@ void main() { await expectLater(find.byType(MaterialApp), matchesGoldenFile('m3_snack_bar.goldenTest.backdropFilter.png')); }); - testWidgets('Floating snackbar can display optional icon', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Floating snackbar can display optional icon', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: false), home: const Scaffold( @@ -3062,7 +3062,7 @@ void main() { 'snack_bar.goldenTest.floatingWithActionWithIcon.png')); }); - testWidgets('Material2 - Fixed width snackbar can display optional icon', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material2 - Fixed width snackbar can display optional icon', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: false), home: const Scaffold( @@ -3089,7 +3089,7 @@ void main() { await expectLater(find.byType(MaterialApp), matchesGoldenFile('m2_snack_bar.goldenTest.fixedWithActionWithIcon.png')); }); - testWidgets('Material3 - Fixed width snackbar can display optional icon', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material3 - Fixed width snackbar can display optional icon', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: true), home: const Scaffold( @@ -3116,7 +3116,7 @@ void main() { await expectLater(find.byType(MaterialApp), matchesGoldenFile('m3_snack_bar.goldenTest.fixedWithActionWithIcon.png')); }); - testWidgets('Material2 - Fixed snackbar can display optional icon without action', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material2 - Fixed snackbar can display optional icon without action', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: false), home: const Scaffold( @@ -3144,7 +3144,7 @@ void main() { await expectLater(find.byType(MaterialApp), matchesGoldenFile('m2_snack_bar.goldenTest.fixedWithIcon.png')); }); - testWidgets('Material3 - Fixed snackbar can display optional icon without action', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material3 - Fixed snackbar can display optional icon without action', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: true), home: const Scaffold( @@ -3172,7 +3172,7 @@ void main() { await expectLater(find.byType(MaterialApp), matchesGoldenFile('m3_snack_bar.goldenTest.fixedWithIcon.png')); }); - testWidgets('Material2 - Floating width snackbar can display optional icon without action', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material2 - Floating width snackbar can display optional icon without action', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: false), home: const Scaffold( @@ -3198,7 +3198,7 @@ void main() { await expectLater(find.byType(MaterialApp), matchesGoldenFile('m2_snack_bar.goldenTest.floatingWithIcon.png')); }); - testWidgets('Material3 - Floating width snackbar can display optional icon without action', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material3 - Floating width snackbar can display optional icon without action', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: true), home: const Scaffold( @@ -3224,7 +3224,7 @@ void main() { await expectLater(find.byType(MaterialApp), matchesGoldenFile('m3_snack_bar.goldenTest.floatingWithIcon.png')); }); - testWidgets('Material2 - Floating multi-line snackbar with icon is aligned correctly', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material2 - Floating multi-line snackbar with icon is aligned correctly', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: false), home: const Scaffold( @@ -3251,7 +3251,7 @@ void main() { await expectLater(find.byType(MaterialApp), matchesGoldenFile('m2_snack_bar.goldenTest.multiLineWithIcon.png')); }); - testWidgets('Material3 - Floating multi-line snackbar with icon is aligned correctly', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material3 - Floating multi-line snackbar with icon is aligned correctly', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: true), home: const Scaffold( @@ -3278,7 +3278,7 @@ void main() { await expectLater(find.byType(MaterialApp), matchesGoldenFile('m3_snack_bar.goldenTest.multiLineWithIcon.png')); }); - testWidgets('Material2 - Floating multi-line snackbar with icon and actionOverflowThreshold=1 is aligned correctly', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material2 - Floating multi-line snackbar with icon and actionOverflowThreshold=1 is aligned correctly', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: false), home: const Scaffold( @@ -3308,7 +3308,7 @@ void main() { ); }); - testWidgets('Material3 - Floating multi-line snackbar with icon and actionOverflowThreshold=1 is aligned correctly', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material3 - Floating multi-line snackbar with icon and actionOverflowThreshold=1 is aligned correctly', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( theme: ThemeData(useMaterial3: true), home: const Scaffold( @@ -3367,7 +3367,7 @@ void main() { ); }); -testWidgets('SnackBarAction backgroundColor works as a Color', (WidgetTester tester) async { +testWidgetsWithLeakTracking('SnackBarAction backgroundColor works as a Color', (WidgetTester tester) async { const Color backgroundColor = Colors.blue; await tester.pumpWidget( @@ -3416,7 +3416,7 @@ testWidgets('SnackBarAction backgroundColor works as a Color', (WidgetTester tes expect(materialAfterDismissed.color, Colors.transparent); }); - testWidgets('SnackBarAction backgroundColor works as a MaterialStateColor', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SnackBarAction backgroundColor works as a MaterialStateColor', (WidgetTester tester) async { final MaterialStateColor backgroundColor = MaterialStateColor.resolveWith((Set states) { if (states.contains(MaterialState.disabled)) { return Colors.blue; @@ -3470,7 +3470,7 @@ testWidgets('SnackBarAction backgroundColor works as a Color', (WidgetTester tes expect(materialAfterDismissed.color, Colors.blue); }); - testWidgets('SnackBarAction disabledBackgroundColor works as expected', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SnackBarAction disabledBackgroundColor works as expected', (WidgetTester tester) async { const Color backgroundColor = Colors.blue; const Color disabledBackgroundColor = Colors.red; @@ -3521,7 +3521,7 @@ testWidgets('SnackBarAction backgroundColor works as a Color', (WidgetTester tes expect(materialAfterDismissed.color, disabledBackgroundColor); }); - testWidgets('SnackBarAction asserts when backgroundColor is a MaterialStateColor and disabledBackgroundColor is also provided', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SnackBarAction asserts when backgroundColor is a MaterialStateColor and disabledBackgroundColor is also provided', (WidgetTester tester) async { final Color backgroundColor = MaterialStateColor.resolveWith((Set states) { if (states.contains(MaterialState.disabled)) { return Colors.blue; @@ -3568,7 +3568,7 @@ testWidgets('SnackBarAction backgroundColor works as a Color', (WidgetTester tes ); }); - testWidgets('SnackBar material applies SnackBar.clipBehavior', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SnackBar material applies SnackBar.clipBehavior', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -3612,7 +3612,7 @@ testWidgets('SnackBarAction backgroundColor works as a Color', (WidgetTester tes expect(material.clipBehavior, Clip.antiAlias); }); - testWidgets('Tap on button behind snack bar defined by width', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Tap on button behind snack bar defined by width', (WidgetTester tester) async { tester.view.physicalSize = const Size.square(200); tester.view.devicePixelRatio = 1; addTearDown(tester.view.resetPhysicalSize); @@ -3668,7 +3668,7 @@ testWidgets('SnackBarAction backgroundColor works as a Color', (WidgetTester tes }); - testWidgets('Tap on button behind snack bar defined by margin', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Tap on button behind snack bar defined by margin', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/78537. tester.view.physicalSize = const Size.square(200); tester.view.devicePixelRatio = 1; diff --git a/packages/flutter/test/material/switch_test.dart b/packages/flutter/test/material/switch_test.dart index 0959ad2d2fd4..df4d7bef3c55 100644 --- a/packages/flutter/test/material/switch_test.dart +++ b/packages/flutter/test/material/switch_test.dart @@ -2988,7 +2988,7 @@ void main() { expect(state.position.value, greaterThan(1)); }); - testWidgets('Switch thumb shows correct pressed color - M3', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Switch thumb shows correct pressed color - M3', (WidgetTester tester) async { final ThemeData themeData = ThemeData(useMaterial3: true); final ColorScheme colors = themeData.colorScheme; Widget buildApp({bool enabled = true, bool value = true}) { diff --git a/packages/flutter/test/material/text_button_test.dart b/packages/flutter/test/material/text_button_test.dart index 862eadb1bbd4..56ef76f9bd00 100644 --- a/packages/flutter/test/material/text_button_test.dart +++ b/packages/flutter/test/material/text_button_test.dart @@ -155,7 +155,7 @@ void main() { expect(material.type, MaterialType.button); }); - testWidgets('Default TextButton meets a11y contrast guidelines', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Default TextButton meets a11y contrast guidelines', (WidgetTester tester) async { final FocusNode focusNode = FocusNode(); await tester.pumpWidget( @@ -203,7 +203,7 @@ void main() { skip: isBrowser, // https://github.com/flutter/flutter/issues/44115 ); - testWidgets('TextButton with colored theme meets a11y contrast guidelines', (WidgetTester tester) async { + testWidgetsWithLeakTracking('TextButton with colored theme meets a11y contrast guidelines', (WidgetTester tester) async { final FocusNode focusNode = FocusNode(); Color getTextColor(Set states) { @@ -1636,7 +1636,7 @@ void main() { expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); }); - testWidgets('TextButton in SelectionArea changes mouse cursor when hovered', (WidgetTester tester) async { + testWidgetsWithLeakTracking('TextButton in SelectionArea changes mouse cursor when hovered', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/104595. await tester.pumpWidget(MaterialApp( home: SelectionArea( @@ -1689,6 +1689,7 @@ void main() { count += 1; } final MaterialStatesController controller = MaterialStatesController(); + addTearDown(controller.dispose); controller.addListener(valueChanged); await tester.pumpWidget( @@ -1789,20 +1790,21 @@ void main() { await gesture.removePointer(); } - testWidgets('TextButton statesController', (WidgetTester tester) async { + testWidgetsWithLeakTracking('TextButton statesController', (WidgetTester tester) async { testStatesController(null, tester); }); - testWidgets('TextButton.icon statesController', (WidgetTester tester) async { + testWidgetsWithLeakTracking('TextButton.icon statesController', (WidgetTester tester) async { testStatesController(const Icon(Icons.add), tester); }); - testWidgets('Disabled TextButton statesController', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Disabled TextButton statesController', (WidgetTester tester) async { int count = 0; void valueChanged() { count += 1; } final MaterialStatesController controller = MaterialStatesController(); + addTearDown(controller.dispose); controller.addListener(valueChanged); await tester.pumpWidget( diff --git a/packages/flutter/test/material/text_field_restoration_test.dart b/packages/flutter/test/material/text_field_restoration_test.dart index acc7bddd4af0..6e3a23d1d8dc 100644 --- a/packages/flutter/test/material/text_field_restoration_test.dart +++ b/packages/flutter/test/material/text_field_restoration_test.dart @@ -4,12 +4,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; const String text = 'Hello World! How are you? Life is good!'; const String alternativeText = 'Everything is awesome!!'; void main() { - testWidgets('TextField restoration', (WidgetTester tester) async { + testWidgetsWithLeakTracking('TextField restoration', (WidgetTester tester) async { await tester.pumpWidget( const MaterialApp( restorationScopeId: 'app', @@ -20,7 +21,7 @@ void main() { await restoreAndVerify(tester); }); - testWidgets('TextField restoration with external controller', (WidgetTester tester) async { + testWidgetsWithLeakTracking('TextField restoration with external controller', (WidgetTester tester) async { await tester.pumpWidget( const MaterialApp( restorationScopeId: 'root', diff --git a/packages/flutter/test/material/text_form_field_restoration_test.dart b/packages/flutter/test/material/text_form_field_restoration_test.dart index fd9d365e234e..570e8fa11c00 100644 --- a/packages/flutter/test/material/text_form_field_restoration_test.dart +++ b/packages/flutter/test/material/text_form_field_restoration_test.dart @@ -4,12 +4,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; const String text = 'Hello World! How are you? Life is good!'; const String alternativeText = 'Everything is awesome!!'; void main() { - testWidgets('TextField restoration', (WidgetTester tester) async { + testWidgetsWithLeakTracking('TextField restoration', (WidgetTester tester) async { await tester.pumpWidget( const MaterialApp( restorationScopeId: 'app', @@ -20,7 +21,7 @@ void main() { await restoreAndVerify(tester); }); - testWidgets('TextField restoration with external controller', (WidgetTester tester) async { + testWidgetsWithLeakTracking('TextField restoration with external controller', (WidgetTester tester) async { await tester.pumpWidget( const MaterialApp( restorationScopeId: 'root', @@ -33,7 +34,7 @@ void main() { await restoreAndVerify(tester); }); - testWidgets('State restoration (No Form ancestor) - onUserInteraction error text validation', (WidgetTester tester) async { + testWidgetsWithLeakTracking('State restoration (No Form ancestor) - onUserInteraction error text validation', (WidgetTester tester) async { String? errorText(String? value) => '$value/error'; late GlobalKey> formState; @@ -91,7 +92,7 @@ void main() { expect(find.text(errorText('bar')!), findsOneWidget); }); - testWidgets('State Restoration (No Form ancestor) - validator sets the error text only when validate is called', (WidgetTester tester) async { + testWidgetsWithLeakTracking('State Restoration (No Form ancestor) - validator sets the error text only when validate is called', (WidgetTester tester) async { String? errorText(String? value) => '$value/error'; late GlobalKey> formState; diff --git a/packages/flutter/test/material/text_form_field_test.dart b/packages/flutter/test/material/text_form_field_test.dart index 5b9ca7cafe83..9d52c9c0de45 100644 --- a/packages/flutter/test/material/text_form_field_test.dart +++ b/packages/flutter/test/material/text_form_field_test.dart @@ -1233,7 +1233,7 @@ void main() { expect(editableText.magnifierConfiguration, equals(myTextMagnifierConfiguration)); }); - testWidgets('Passes undoController to undoController TextField', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Passes undoController to undoController TextField', (WidgetTester tester) async { final UndoHistoryController undoController = UndoHistoryController(value: UndoHistoryValue.empty); addTearDown(undoController.dispose); diff --git a/packages/flutter/test/material/text_selection_toolbar_test.dart b/packages/flutter/test/material/text_selection_toolbar_test.dart index f3317c109c98..857ed6d0fcb3 100644 --- a/packages/flutter/test/material/text_selection_toolbar_test.dart +++ b/packages/flutter/test/material/text_selection_toolbar_test.dart @@ -123,7 +123,7 @@ void main() { expect(findOverflowButton(), findsOneWidget); }); - testWidgets('positions itself at anchorAbove if it fits', (WidgetTester tester) async { + testWidgetsWithLeakTracking('positions itself at anchorAbove if it fits', (WidgetTester tester) async { late StateSetter setState; const double height = 44.0; const double anchorBelowY = 500.0; @@ -172,7 +172,7 @@ void main() { expect(toolbarY, equals(anchorAboveY - height - _kToolbarContentDistance)); }); - testWidgets('can create and use a custom toolbar', (WidgetTester tester) async { + testWidgetsWithLeakTracking('can create and use a custom toolbar', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( diff --git a/packages/flutter/test/material/theme_test.dart b/packages/flutter/test/material/theme_test.dart index 22149aac2384..1100bbe0c3a9 100644 --- a/packages/flutter/test/material/theme_test.dart +++ b/packages/flutter/test/material/theme_test.dart @@ -196,7 +196,7 @@ void main() { expect(Theme.of(tester.element(find.text('menuItem'))).brightness, equals(Brightness.light)); }); - testWidgets('DropdownMenu inherits shadowed app theme', (WidgetTester tester) async { + testWidgetsWithLeakTracking('DropdownMenu inherits shadowed app theme', (WidgetTester tester) async { final Key dropdownMenuButtonKey = UniqueKey(); await tester.pumpWidget( MaterialApp( diff --git a/packages/flutter/test/material/time_test.dart b/packages/flutter/test/material/time_test.dart index 37050875ab72..97bb94617a14 100644 --- a/packages/flutter/test/material/time_test.dart +++ b/packages/flutter/test/material/time_test.dart @@ -80,7 +80,7 @@ void main() { expect(state.timeOfDay.value, const TimeOfDay(hour: 2, minute: 2)); }); - testWidgets('restart and restore', (WidgetTester tester) async { + testWidgetsWithLeakTracking('restart and restore', (WidgetTester tester) async { await tester.pumpWidget(const RootRestorationScope( restorationId: 'root-child', child: _RestorableWidget(), @@ -108,7 +108,7 @@ void main() { expect(state.timeOfDay.value, const TimeOfDay(hour: 2, minute: 2)); }); - testWidgets('restore to older state', (WidgetTester tester) async { + testWidgetsWithLeakTracking('restore to older state', (WidgetTester tester) async { await tester.pumpWidget(const RootRestorationScope( restorationId: 'root-child', child: _RestorableWidget(), @@ -139,7 +139,7 @@ void main() { expect(state.timeOfDay.value, const TimeOfDay(hour: 10, minute: 5)); }); - testWidgets('call notifiers when value changes', (WidgetTester tester) async { + testWidgetsWithLeakTracking('call notifiers when value changes', (WidgetTester tester) async { await tester.pumpWidget(const RootRestorationScope( restorationId: 'root-child', child: _RestorableWidget(),