From 658710b6f944e9a6f8bba9c4896fb953f1062976 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 18 Sep 2023 13:45:38 -0700 Subject: [PATCH] Cover more tests with leak tracking. (#134805) --- .../cupertino/activity_indicator_test.dart | 15 ++-- .../adaptive_text_selection_toolbar_test.dart | 19 +++-- packages/flutter/test/cupertino/app_test.dart | 79 ++++++++++++------ .../test/cupertino/bottom_tab_bar_test.dart | 31 +++---- .../flutter/test/cupertino/button_test.dart | 31 +++---- .../flutter/test/cupertino/checkbox_test.dart | 15 ++-- packages/flutter/test/material/app_test.dart | 46 ++++++++--- .../material/calendar_date_picker_test.dart | 82 +++++++++---------- packages/flutter/test/material/chip_test.dart | 17 +++- .../test/widgets/undo_history_test.dart | 26 +++--- 10 files changed, 215 insertions(+), 146 deletions(-) diff --git a/packages/flutter/test/cupertino/activity_indicator_test.dart b/packages/flutter/test/cupertino/activity_indicator_test.dart index dcb8ac43156d5..1db90ea77ce7b 100644 --- a/packages/flutter/test/cupertino/activity_indicator_test.dart +++ b/packages/flutter/test/cupertino/activity_indicator_test.dart @@ -10,9 +10,10 @@ library; import 'package:flutter/cupertino.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; void main() { - testWidgets('Activity indicator animate property works', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Activity indicator animate property works', (WidgetTester tester) async { await tester.pumpWidget(buildCupertinoActivityIndicator()); expect(SchedulerBinding.instance.transientCallbackCount, equals(1)); @@ -28,7 +29,7 @@ void main() { expect(SchedulerBinding.instance.transientCallbackCount, equals(1)); }); - testWidgets('Activity indicator dark mode', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Activity indicator dark mode', (WidgetTester tester) async { final Key key = UniqueKey(); await tester.pumpWidget( Center( @@ -77,7 +78,7 @@ void main() { ); }); - testWidgets('Activity indicator 0% in progress', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Activity indicator 0% in progress', (WidgetTester tester) async { final Key key = UniqueKey(); await tester.pumpWidget( Center( @@ -99,7 +100,7 @@ void main() { ); }); - testWidgets('Activity indicator 30% in progress', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Activity indicator 30% in progress', (WidgetTester tester) async { final Key key = UniqueKey(); await tester.pumpWidget( Center( @@ -121,7 +122,7 @@ void main() { ); }); - testWidgets('Activity indicator 100% in progress', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Activity indicator 100% in progress', (WidgetTester tester) async { final Key key = UniqueKey(); await tester.pumpWidget( Center( @@ -142,7 +143,7 @@ void main() { }); // Regression test for https://github.com/flutter/flutter/issues/41345. - testWidgets('has the correct corner radius', (WidgetTester tester) async { + testWidgetsWithLeakTracking('has the correct corner radius', (WidgetTester tester) async { await tester.pumpWidget( const CupertinoActivityIndicator(animating: false, radius: 100), ); @@ -158,7 +159,7 @@ void main() { ); }); - testWidgets('Can specify color', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can specify color', (WidgetTester tester) async { final Key key = UniqueKey(); await tester.pumpWidget( Center( diff --git a/packages/flutter/test/cupertino/adaptive_text_selection_toolbar_test.dart b/packages/flutter/test/cupertino/adaptive_text_selection_toolbar_test.dart index 70f4be6d4518b..fd5b2c93935d8 100644 --- a/packages/flutter/test/cupertino/adaptive_text_selection_toolbar_test.dart +++ b/packages/flutter/test/cupertino/adaptive_text_selection_toolbar_test.dart @@ -6,6 +6,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; import '../widgets/clipboard_utils.dart'; import '../widgets/live_text_utils.dart'; @@ -37,7 +38,7 @@ void main() { ); } - testWidgets('Builds the right toolbar on each platform, including web, and shows buttonItems', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Builds the right toolbar on each platform, including web, and shows buttonItems', (WidgetTester tester) async { const String buttonText = 'Click me'; await tester.pumpWidget( @@ -78,7 +79,7 @@ void main() { skip: isBrowser, // [intended] see https://github.com/flutter/flutter/issues/108382 ); - testWidgets('Can build children directly as well', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can build children directly as well', (WidgetTester tester) async { final GlobalKey key = GlobalKey(); await tester.pumpWidget( @@ -101,17 +102,21 @@ void main() { skip: isBrowser, // [intended] see https://github.com/flutter/flutter/issues/108382 ); - testWidgets('Can build from EditableTextState', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can build from EditableTextState', (WidgetTester tester) async { final GlobalKey key = GlobalKey(); + final FocusNode focusNode = FocusNode(); + addTearDown(focusNode.dispose); + final TextEditingController controller = TextEditingController(); + addTearDown(controller.dispose); await tester.pumpWidget(CupertinoApp( home: Align( alignment: Alignment.topLeft, child: SizedBox( width: 400, child: EditableText( - controller: TextEditingController(), + controller: controller, backgroundCursorColor: const Color(0xff00ffff), - focusNode: FocusNode(), + focusNode: focusNode, style: const TextStyle(), cursorColor: const Color(0xff00ffff), selectionControls: cupertinoTextSelectionHandleControls, @@ -160,7 +165,7 @@ void main() { variant: TargetPlatformVariant.all(), ); - testWidgets('Can build for editable text from raw parameters', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can build for editable text from raw parameters', (WidgetTester tester) async { final GlobalKey key = GlobalKey(); await tester.pumpWidget(CupertinoApp( home: Center( @@ -210,7 +215,7 @@ void main() { variant: TargetPlatformVariant.all(), ); - testWidgets('Builds the correct button per-platform', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Builds the correct button per-platform', (WidgetTester tester) async { const String buttonText = 'Click me'; await tester.pumpWidget( diff --git a/packages/flutter/test/cupertino/app_test.dart b/packages/flutter/test/cupertino/app_test.dart index 50265a8f66951..ea384af7feba9 100644 --- a/packages/flutter/test/cupertino/app_test.dart +++ b/packages/flutter/test/cupertino/app_test.dart @@ -40,7 +40,7 @@ void main() { expect(find.widgetWithText(Navigator, 'foo'), findsOneWidget); }); - testWidgets('Has default cupertino localizations', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Has default cupertino localizations', (WidgetTester tester) async { await tester.pumpWidget( CupertinoApp( home: Builder( @@ -62,7 +62,7 @@ void main() { expect(find.text('Thu Oct 4 '), findsOneWidget); }); - testWidgets('Can use dynamic color', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can use dynamic color', (WidgetTester tester) async { const CupertinoDynamicColor dynamicColor = CupertinoDynamicColor.withBrightness( color: Color(0xFF000000), darkColor: Color(0xFF000001), @@ -84,7 +84,7 @@ void main() { expect(tester.widget(find.byType(Title)).color.value, 0xFF000001); }); - testWidgets('Can customize initial routes', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can customize initial routes', (WidgetTester tester) async { final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>(); await tester.pumpWidget( CupertinoApp( @@ -131,7 +131,7 @@ void main() { expect(find.text('regular page two'), findsNothing); }); - testWidgets('CupertinoApp.navigatorKey can be updated', (WidgetTester tester) async { + testWidgetsWithLeakTracking('CupertinoApp.navigatorKey can be updated', (WidgetTester tester) async { final GlobalKey<NavigatorState> key1 = GlobalKey<NavigatorState>(); await tester.pumpWidget(CupertinoApp( navigatorKey: key1, @@ -147,12 +147,13 @@ void main() { expect(key1.currentState, isNull); }); - testWidgets('CupertinoApp.router works', (WidgetTester tester) async { + testWidgetsWithLeakTracking('CupertinoApp.router works', (WidgetTester tester) async { final PlatformRouteInformationProvider provider = PlatformRouteInformationProvider( initialRouteInformation: RouteInformation( uri: Uri.parse('initial'), ), ); + addTearDown(provider.dispose); final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate( builder: (BuildContext context, RouteInformation information) { return Text(information.uri.toString()); @@ -164,6 +165,7 @@ void main() { return route.didPop(result); }, ); + addTearDown(delegate.dispose); await tester.pumpWidget(CupertinoApp.router( routeInformationProvider: provider, routeInformationParser: SimpleRouteInformationParser(), @@ -176,9 +178,14 @@ void main() { await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); await tester.pumpAndSettle(); expect(find.text('popped'), findsOneWidget); - }); - - testWidgets('CupertinoApp.router route information parser is optional', (WidgetTester tester) async { + }, + // TODO(polina-c): remove after fixing + // https://github.com/flutter/flutter/issues/134205 + leakTrackingTestConfig: const LeakTrackingTestConfig( + allowAllNotDisposed: true, + )); + + testWidgetsWithLeakTracking('CupertinoApp.router route information parser is optional', (WidgetTester tester) async { final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate( builder: (BuildContext context, RouteInformation information) { return Text(information.uri.toString()); @@ -190,6 +197,7 @@ void main() { return route.didPop(result); }, ); + addTearDown(delegate.dispose); delegate.routeInformation = RouteInformation(uri: Uri.parse('initial')); await tester.pumpWidget(CupertinoApp.router( routerDelegate: delegate, @@ -201,9 +209,14 @@ void main() { await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); await tester.pumpAndSettle(); expect(find.text('popped'), findsOneWidget); - }); - - testWidgets('CupertinoApp.router throw if route information provider is provided but no route information parser', (WidgetTester tester) async { + }, + // TODO(polina-c): remove after fixing + // https://github.com/flutter/flutter/issues/134205 + leakTrackingTestConfig: const LeakTrackingTestConfig( + allowAllNotDisposed: true, + )); + + testWidgetsWithLeakTracking('CupertinoApp.router throw if route information provider is provided but no route information parser', (WidgetTester tester) async { final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate( builder: (BuildContext context, RouteInformation information) { return Text(information.uri.toString()); @@ -215,12 +228,14 @@ void main() { return route.didPop(result); }, ); + addTearDown(delegate.dispose); delegate.routeInformation = RouteInformation(uri: Uri.parse('initial')); final PlatformRouteInformationProvider provider = PlatformRouteInformationProvider( initialRouteInformation: RouteInformation( uri: Uri.parse('initial'), ), ); + addTearDown(provider.dispose); await tester.pumpWidget(CupertinoApp.router( routeInformationProvider: provider, routerDelegate: delegate, @@ -228,7 +243,7 @@ void main() { expect(tester.takeException(), isAssertionError); }); - testWidgets('CupertinoApp.router throw if route configuration is provided along with other delegate', (WidgetTester tester) async { + testWidgetsWithLeakTracking('CupertinoApp.router throw if route configuration is provided along with other delegate', (WidgetTester tester) async { final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate( builder: (BuildContext context, RouteInformation information) { return Text(information.uri.toString()); @@ -240,6 +255,7 @@ void main() { return route.didPop(result); }, ); + addTearDown(delegate.dispose); delegate.routeInformation = RouteInformation(uri: Uri.parse('initial')); final RouterConfig<RouteInformation> routerConfig = RouterConfig<RouteInformation>(routerDelegate: delegate); await tester.pumpWidget(CupertinoApp.router( @@ -249,15 +265,19 @@ void main() { expect(tester.takeException(), isAssertionError); }); - testWidgets('CupertinoApp.router router config works', (WidgetTester tester) async { + testWidgetsWithLeakTracking('CupertinoApp.router router config works', (WidgetTester tester) async { + late SimpleNavigatorRouterDelegate delegate; + addTearDown(() => delegate.dispose()); + final PlatformRouteInformationProvider provider = PlatformRouteInformationProvider( + initialRouteInformation: RouteInformation( + uri: Uri.parse('initial'), + ), + ); + addTearDown(provider.dispose); final RouterConfig<RouteInformation> routerConfig = RouterConfig<RouteInformation>( - routeInformationProvider: PlatformRouteInformationProvider( - initialRouteInformation: RouteInformation( - uri: Uri.parse('initial'), - ), - ), + routeInformationProvider: provider, routeInformationParser: SimpleRouteInformationParser(), - routerDelegate: SimpleNavigatorRouterDelegate( + routerDelegate: delegate = SimpleNavigatorRouterDelegate( builder: (BuildContext context, RouteInformation information) { return Text(information.uri.toString()); }, @@ -280,9 +300,14 @@ void main() { await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); await tester.pumpAndSettle(); expect(find.text('popped'), findsOneWidget); - }); - - testWidgets('CupertinoApp has correct default ScrollBehavior', (WidgetTester tester) async { + }, + // TODO(polina-c): remove after fixing + // https://github.com/flutter/flutter/issues/134205 + leakTrackingTestConfig: const LeakTrackingTestConfig( + allowAllNotDisposed: true, + )); + + testWidgetsWithLeakTracking('CupertinoApp has correct default ScrollBehavior', (WidgetTester tester) async { late BuildContext capturedContext; await tester.pumpWidget( CupertinoApp( @@ -297,7 +322,7 @@ void main() { expect(ScrollConfiguration.of(capturedContext).runtimeType, CupertinoScrollBehavior); }); - testWidgets('A ScrollBehavior can be set for CupertinoApp', (WidgetTester tester) async { + testWidgetsWithLeakTracking('A ScrollBehavior can be set for CupertinoApp', (WidgetTester tester) async { late BuildContext capturedContext; await tester.pumpWidget( CupertinoApp( @@ -315,7 +340,7 @@ void main() { expect(scrollBehavior.getScrollPhysics(capturedContext).runtimeType, NeverScrollableScrollPhysics); }); - testWidgets('When `useInheritedMediaQuery` is true an existing MediaQuery is used if one is available', (WidgetTester tester) async { + testWidgetsWithLeakTracking('When `useInheritedMediaQuery` is true an existing MediaQuery is used if one is available', (WidgetTester tester) async { late BuildContext capturedContext; final UniqueKey uniqueKey = UniqueKey(); await tester.pumpWidget( @@ -335,7 +360,7 @@ void main() { expect(capturedContext.dependOnInheritedWidgetOfExactType<MediaQuery>()?.key, uniqueKey); }); - testWidgets('Text color is correctly resolved when CupertinoThemeData.brightness is null', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Text color is correctly resolved when CupertinoThemeData.brightness is null', (WidgetTester tester) async { debugBrightnessOverride = Brightness.dark; await tester.pumpWidget( @@ -374,7 +399,7 @@ void main() { debugBrightnessOverride = null; }); - testWidgets('Cursor color is resolved when CupertinoThemeData.brightness is null', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Cursor color is resolved when CupertinoThemeData.brightness is null', (WidgetTester tester) async { debugBrightnessOverride = Brightness.dark; RenderEditable findRenderEditable(WidgetTester tester) { @@ -431,7 +456,7 @@ void main() { debugBrightnessOverride = null; }); - testWidgets('Assert in buildScrollbar that controller != null when using it', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Assert in buildScrollbar that controller != null when using it', (WidgetTester tester) async { const ScrollBehavior defaultBehavior = CupertinoScrollBehavior(); late BuildContext capturedContext; diff --git a/packages/flutter/test/cupertino/bottom_tab_bar_test.dart b/packages/flutter/test/cupertino/bottom_tab_bar_test.dart index 04576a904d604..20c8b054aa976 100644 --- a/packages/flutter/test/cupertino/bottom_tab_bar_test.dart +++ b/packages/flutter/test/cupertino/bottom_tab_bar_test.dart @@ -7,6 +7,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; import '../image_data.dart'; import '../widgets/semantics_tester.dart'; @@ -29,7 +30,7 @@ Future<void> pumpWidgetWithBoilerplate(WidgetTester tester, Widget widget) async Future<void> main() async { - testWidgets('Need at least 2 tabs', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Need at least 2 tabs', (WidgetTester tester) async { await expectLater( () => pumpWidgetWithBoilerplate(tester, CupertinoTabBar( items: <BottomNavigationBarItem>[ @@ -47,7 +48,7 @@ Future<void> main() async { ); }); - testWidgets('Active and inactive colors', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Active and inactive colors', (WidgetTester tester) async { await pumpWidgetWithBoilerplate(tester, MediaQuery( data: const MediaQueryData(), child: CupertinoTabBar( @@ -81,7 +82,7 @@ Future<void> main() async { }); - testWidgets('BottomNavigationBar.label will create a text widget', (WidgetTester tester) async { + testWidgetsWithLeakTracking('BottomNavigationBar.label will create a text widget', (WidgetTester tester) async { await pumpWidgetWithBoilerplate(tester, MediaQuery( data: const MediaQueryData(), child: CupertinoTabBar( @@ -103,7 +104,7 @@ Future<void> main() async { expect(find.text('Tab 2'), findsOneWidget); }); - testWidgets('Active and inactive colors dark mode', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Active and inactive colors dark mode', (WidgetTester tester) async { const CupertinoDynamicColor dynamicActiveColor = CupertinoDynamicColor.withBrightness( color: Color(0xFF000000), darkColor: Color(0xFF000001), @@ -191,7 +192,7 @@ Future<void> main() async { expect(decoration2.border!.top.color.value, 0x29000000); }); - testWidgets('Tabs respects themes', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Tabs respects themes', (WidgetTester tester) async { await tester.pumpWidget( CupertinoApp( home: CupertinoTabBar( @@ -255,7 +256,7 @@ Future<void> main() async { expect(actualActive.text.style!.color, isSameColorAs(CupertinoColors.activeBlue.darkColor)); }); - testWidgets('Use active icon', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Use active icon', (WidgetTester tester) async { final MemoryImage activeIcon = MemoryImage(Uint8List.fromList(kBlueSquarePng)); final MemoryImage inactiveIcon = MemoryImage(Uint8List.fromList(kTransparentImage)); @@ -288,7 +289,7 @@ Future<void> main() async { expect(image.image, activeIcon); }); - testWidgets('Adjusts height to account for bottom padding', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Adjusts height to account for bottom padding', (WidgetTester tester) async { final CupertinoTabBar tabBar = CupertinoTabBar( items: <BottomNavigationBarItem>[ BottomNavigationBarItem( @@ -327,7 +328,7 @@ Future<void> main() async { expect(tester.getSize(find.byType(CupertinoTabBar)).height, 90.0); }); - testWidgets('Set custom height', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Set custom height', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/51704 const double tabBarHeight = 56.0; final CupertinoTabBar tabBar = CupertinoTabBar( @@ -370,7 +371,7 @@ Future<void> main() async { expect(tester.getSize(find.byType(CupertinoTabBar)).height, tabBarHeight + bottomPadding); }); - testWidgets('Ensure bar height will not change when toggle keyboard', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Ensure bar height will not change when toggle keyboard', (WidgetTester tester) async { const double tabBarHeight = 56.0; final CupertinoTabBar tabBar = CupertinoTabBar( height: tabBarHeight, @@ -424,7 +425,7 @@ Future<void> main() async { expect(tester.getSize(find.byType(CupertinoTabBar)).height, tabBarHeight + bottomPadding); }); - testWidgets('Opaque background does not add blur effects', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Opaque background does not add blur effects', (WidgetTester tester) async { await pumpWidgetWithBoilerplate(tester, MediaQuery( data: const MediaQueryData(), child: CupertinoTabBar( @@ -463,7 +464,7 @@ Future<void> main() async { expect(find.byType(BackdropFilter), findsNothing); }); - testWidgets('Tap callback', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Tap callback', (WidgetTester tester) async { late int callbackTab; await pumpWidgetWithBoilerplate(tester, MediaQuery( @@ -491,7 +492,7 @@ Future<void> main() async { expect(callbackTab, 1); }); - testWidgets('tabs announce semantics', (WidgetTester tester) async { + testWidgetsWithLeakTracking('tabs announce semantics', (WidgetTester tester) async { final SemanticsTester semantics = SemanticsTester(tester); await pumpWidgetWithBoilerplate(tester, MediaQuery( @@ -526,7 +527,7 @@ Future<void> main() async { semantics.dispose(); }); - testWidgets('Label of items should be nullable', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Label of items should be nullable', (WidgetTester tester) async { final MemoryImage iconProvider = MemoryImage(Uint8List.fromList(kTransparentImage)); final List<int> itemsTapped = <int>[]; @@ -563,7 +564,7 @@ Future<void> main() async { expect(itemsTapped, <int>[1]); }); - testWidgets('Hide border hides the top border of the tabBar', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Hide border hides the top border of the tabBar', (WidgetTester tester) async { await pumpWidgetWithBoilerplate( tester, MediaQuery( @@ -623,7 +624,7 @@ Future<void> main() async { expect(boxDecorationHiddenBorder.border, isNull); }); - testWidgets('Hovering over tab bar item updates cursor to clickable on Web', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Hovering over tab bar item updates cursor to clickable on Web', (WidgetTester tester) async { await pumpWidgetWithBoilerplate( tester, MediaQuery( diff --git a/packages/flutter/test/cupertino/button_test.dart b/packages/flutter/test/cupertino/button_test.dart index e5e0cae05a4bb..b3587ae7fdd76 100644 --- a/packages/flutter/test/cupertino/button_test.dart +++ b/packages/flutter/test/cupertino/button_test.dart @@ -8,6 +8,7 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; import '../widgets/semantics_tester.dart'; @@ -17,7 +18,7 @@ const TextStyle testStyle = TextStyle( ); void main() { - testWidgets('Default layout minimum size', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Default layout minimum size', (WidgetTester tester) async { await tester.pumpWidget( boilerplate(child: const CupertinoButton( onPressed: null, @@ -32,7 +33,7 @@ void main() { ); }); - testWidgets('Minimum size parameter', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Minimum size parameter', (WidgetTester tester) async { const double minSize = 60.0; await tester.pumpWidget( boilerplate(child: const CupertinoButton( @@ -49,7 +50,7 @@ void main() { ); }); - testWidgets('Size grows with text', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Size grows with text', (WidgetTester tester) async { await tester.pumpWidget( boilerplate(child: const CupertinoButton( onPressed: null, @@ -102,7 +103,7 @@ void main() { }); */ - testWidgets('Button child alignment', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Button child alignment', (WidgetTester tester) async { await tester.pumpWidget( CupertinoApp( home: CupertinoButton( @@ -129,7 +130,7 @@ void main() { expect(align.alignment, Alignment.centerLeft); }); - testWidgets('Button with background is wider', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Button with background is wider', (WidgetTester tester) async { await tester.pumpWidget(boilerplate(child: const CupertinoButton( onPressed: null, color: Color(0xFFFFFFFF), @@ -143,7 +144,7 @@ void main() { ); }); - testWidgets('Custom padding', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Custom padding', (WidgetTester tester) async { await tester.pumpWidget(boilerplate(child: const CupertinoButton( onPressed: null, padding: EdgeInsets.all(100.0), @@ -156,7 +157,7 @@ void main() { ); }); - testWidgets('Button takes taps', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Button takes taps', (WidgetTester tester) async { bool value = false; await tester.pumpWidget( StatefulBuilder( @@ -195,7 +196,7 @@ void main() { expect(SchedulerBinding.instance.transientCallbackCount, equals(0)); }); - testWidgets('Enabled button animates', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Enabled button animates', (WidgetTester tester) async { await tester.pumpWidget(boilerplate(child: CupertinoButton( child: const Text('Tap me'), onPressed: () { }, @@ -231,7 +232,7 @@ void main() { expect(transition.opacity.value, moreOrLessEquals(1.0, epsilon: 0.001)); }); - testWidgets('pressedOpacity defaults to 0.1', (WidgetTester tester) async { + testWidgetsWithLeakTracking('pressedOpacity defaults to 0.1', (WidgetTester tester) async { await tester.pumpWidget(boilerplate(child: CupertinoButton( child: const Text('Tap me'), onPressed: () { }, @@ -250,7 +251,7 @@ void main() { expect(opacity.opacity.value, 0.4); }); - testWidgets('pressedOpacity parameter', (WidgetTester tester) async { + testWidgetsWithLeakTracking('pressedOpacity parameter', (WidgetTester tester) async { const double pressedOpacity = 0.5; await tester.pumpWidget(boilerplate(child: CupertinoButton( pressedOpacity: pressedOpacity, @@ -271,7 +272,7 @@ void main() { expect(opacity.opacity.value, pressedOpacity); }); - testWidgets('Cupertino button is semantically a button', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Cupertino button is semantically a button', (WidgetTester tester) async { final SemanticsTester semantics = SemanticsTester(tester); await tester.pumpWidget( boilerplate( @@ -302,7 +303,7 @@ void main() { semantics.dispose(); }); - testWidgets('Can specify colors', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can specify colors', (WidgetTester tester) async { await tester.pumpWidget(boilerplate(child: CupertinoButton( color: const Color(0x000000FF), disabledColor: const Color(0x0000FF00), @@ -330,7 +331,7 @@ void main() { expect(boxDecoration.color, const Color(0x0000FF00)); }); - testWidgets('Can specify dynamic colors', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can specify dynamic colors', (WidgetTester tester) async { const Color bgColor = CupertinoDynamicColor.withBrightness( color: Color(0xFF123456), darkColor: Color(0xFF654321), @@ -379,7 +380,7 @@ void main() { expect(boxDecoration.color!.value, 0xFF111111); }); - testWidgets('Button respects themes', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Button respects themes', (WidgetTester tester) async { late TextStyle textStyle; await tester.pumpWidget( @@ -453,7 +454,7 @@ void main() { expect(decoration.color, isSameColorAs(CupertinoColors.systemBlue.darkColor)); }); - testWidgets('Hovering over Cupertino button updates cursor to clickable on Web', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Hovering over Cupertino button updates cursor to clickable on Web', (WidgetTester tester) async { await tester.pumpWidget( CupertinoApp( home: Center( diff --git a/packages/flutter/test/cupertino/checkbox_test.dart b/packages/flutter/test/cupertino/checkbox_test.dart index 601aef991d884..7f047e62cf7d3 100644 --- a/packages/flutter/test/cupertino/checkbox_test.dart +++ b/packages/flutter/test/cupertino/checkbox_test.dart @@ -7,6 +7,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; import '../widgets/semantics_tester.dart'; @@ -15,7 +16,7 @@ void main() { debugResetSemanticsIdCounter(); }); - testWidgets('CupertinoCheckbox semantics', (WidgetTester tester) async { + testWidgetsWithLeakTracking('CupertinoCheckbox semantics', (WidgetTester tester) async { final SemanticsHandle handle = tester.ensureSemantics(); await tester.pumpWidget( @@ -155,7 +156,7 @@ void main() { handle.dispose(); }); - testWidgets('Can wrap CupertinoCheckbox with Semantics', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can wrap CupertinoCheckbox with Semantics', (WidgetTester tester) async { final SemanticsHandle handle = tester.ensureSemantics(); await tester.pumpWidget( @@ -183,7 +184,7 @@ void main() { handle.dispose(); }); - testWidgets('CupertinoCheckbox tristate: true', (WidgetTester tester) async { + testWidgetsWithLeakTracking('CupertinoCheckbox tristate: true', (WidgetTester tester) async { bool? checkBoxValue; await tester.pumpWidget( @@ -227,7 +228,7 @@ void main() { expect(checkBoxValue, null); }); - testWidgets('has semantics for tristate', (WidgetTester tester) async { + testWidgetsWithLeakTracking('has semantics for tristate', (WidgetTester tester) async { final SemanticsTester semantics = SemanticsTester(tester); await tester.pumpWidget( CupertinoApp( @@ -294,7 +295,7 @@ void main() { semantics.dispose(); }); - testWidgets('has semantic events', (WidgetTester tester) async { + testWidgetsWithLeakTracking('has semantic events', (WidgetTester tester) async { dynamic semanticEvent; bool? checkboxValue = false; tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, (dynamic message) async { @@ -334,7 +335,7 @@ void main() { semanticsTester.dispose(); }); - testWidgets('Checkbox can be toggled by keyboard shortcuts', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Checkbox can be toggled by keyboard shortcuts', (WidgetTester tester) async { tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional; bool? value = true; Widget buildApp({bool enabled = true}) { @@ -371,7 +372,7 @@ void main() { expect(value, isTrue); }); - testWidgets('Checkbox respects shape and side', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Checkbox respects shape and side', (WidgetTester tester) async { const RoundedRectangleBorder roundedRectangleBorder = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(5))); diff --git a/packages/flutter/test/material/app_test.dart b/packages/flutter/test/material/app_test.dart index 31d86997a8815..06b2cbb00ed06 100644 --- a/packages/flutter/test/material/app_test.dart +++ b/packages/flutter/test/material/app_test.dart @@ -1083,12 +1083,13 @@ void main() { expect(key1.currentState, isNull); }); - testWidgets('MaterialApp.router works', (WidgetTester tester) async { + testWidgetsWithLeakTracking('MaterialApp.router works', (WidgetTester tester) async { final PlatformRouteInformationProvider provider = PlatformRouteInformationProvider( initialRouteInformation: RouteInformation( uri: Uri.parse('initial'), ), ); + addTearDown(provider.dispose); final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate( builder: (BuildContext context, RouteInformation information) { return Text(information.uri.toString()); @@ -1100,6 +1101,7 @@ void main() { return route.didPop(result); }, ); + addTearDown(delegate.dispose); await tester.pumpWidget(MaterialApp.router( routeInformationProvider: provider, routeInformationParser: SimpleRouteInformationParser(), @@ -1112,9 +1114,14 @@ void main() { await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); await tester.pumpAndSettle(); expect(find.text('popped'), findsOneWidget); - }); - - testWidgets('MaterialApp.router route information parser is optional', (WidgetTester tester) async { + }, + // TODO(polina-c): remove after fixing + // https://github.com/flutter/flutter/issues/134205 + leakTrackingTestConfig: const LeakTrackingTestConfig( + allowAllNotDisposed: true, + )); + + testWidgetsWithLeakTracking('MaterialApp.router route information parser is optional', (WidgetTester tester) async { final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate( builder: (BuildContext context, RouteInformation information) { return Text(information.uri.toString()); @@ -1126,6 +1133,7 @@ void main() { return route.didPop(result); }, ); + addTearDown(delegate.dispose); delegate.routeInformation = RouteInformation(uri: Uri.parse('initial')); await tester.pumpWidget(MaterialApp.router( routerDelegate: delegate, @@ -1137,7 +1145,12 @@ void main() { await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); await tester.pumpAndSettle(); expect(find.text('popped'), findsOneWidget); - }); + }, + // TODO(polina-c): remove after fixing + // https://github.com/flutter/flutter/issues/134205 + leakTrackingTestConfig: const LeakTrackingTestConfig( + allowAllNotDisposed: true, + )); testWidgetsWithLeakTracking('MaterialApp.router throw if route information provider is provided but no route information parser', (WidgetTester tester) async { final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate( @@ -1151,6 +1164,7 @@ void main() { return route.didPop(result); }, ); + addTearDown(delegate.dispose); delegate.routeInformation = RouteInformation(uri: Uri.parse('initial')); final PlatformRouteInformationProvider provider = PlatformRouteInformationProvider( initialRouteInformation: RouteInformation( @@ -1177,6 +1191,7 @@ void main() { return route.didPop(result); }, ); + addTearDown(delegate.dispose); delegate.routeInformation = RouteInformation(uri: Uri.parse('initial')); final RouterConfig<RouteInformation> routerConfig = RouterConfig<RouteInformation>(routerDelegate: delegate); await tester.pumpWidget(MaterialApp.router( @@ -1186,15 +1201,19 @@ void main() { expect(tester.takeException(), isAssertionError); }); - testWidgets('MaterialApp.router router config works', (WidgetTester tester) async { + testWidgetsWithLeakTracking('MaterialApp.router router config works', (WidgetTester tester) async { + late SimpleNavigatorRouterDelegate routerDelegate; + addTearDown(() => routerDelegate.dispose()); + late PlatformRouteInformationProvider provider; + addTearDown(() => provider.dispose()); final RouterConfig<RouteInformation> routerConfig = RouterConfig<RouteInformation>( - routeInformationProvider: PlatformRouteInformationProvider( + routeInformationProvider: provider = PlatformRouteInformationProvider( initialRouteInformation: RouteInformation( uri: Uri.parse('initial'), ), ), routeInformationParser: SimpleRouteInformationParser(), - routerDelegate: SimpleNavigatorRouterDelegate( + routerDelegate: routerDelegate = SimpleNavigatorRouterDelegate( builder: (BuildContext context, RouteInformation information) { return Text(information.uri.toString()); }, @@ -1217,7 +1236,12 @@ void main() { await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); await tester.pumpAndSettle(); expect(find.text('popped'), findsOneWidget); - }); + }, + // TODO(polina-c): remove after fixing + // https://github.com/flutter/flutter/issues/134205 + leakTrackingTestConfig: const LeakTrackingTestConfig( + allowAllNotDisposed: true, + )); testWidgetsWithLeakTracking('MaterialApp.builder can build app without a Navigator', (WidgetTester tester) async { Widget? builderChild; @@ -1545,7 +1569,9 @@ class SimpleNavigatorRouterDelegate extends RouterDelegate<RouteInformation> wit SimpleNavigatorRouterDelegate({ required this.builder, required this.onPopPage, - }); + }) { + maybeDispatchObjectCreation(); + } @override GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>(); diff --git a/packages/flutter/test/material/calendar_date_picker_test.dart b/packages/flutter/test/material/calendar_date_picker_test.dart index 7dcf81209da9e..7caae93b9a770 100644 --- a/packages/flutter/test/material/calendar_date_picker_test.dart +++ b/packages/flutter/test/material/calendar_date_picker_test.dart @@ -77,7 +77,7 @@ void main() { } group('CalendarDatePicker', () { - testWidgets('Can select a day', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can select a day', (WidgetTester tester) async { DateTime? selectedDate; await tester.pumpWidget(calendarDatePicker( initialDate: DateTime(2016, DateTime.january, 15), @@ -87,7 +87,7 @@ void main() { expect(selectedDate, equals(DateTime(2016, DateTime.january, 12))); }); - testWidgets('Can select a day with nothing first selected', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can select a day with nothing first selected', (WidgetTester tester) async { DateTime? selectedDate; await tester.pumpWidget(calendarDatePicker( onDateChanged: (DateTime date) => selectedDate = date, @@ -96,7 +96,7 @@ void main() { expect(selectedDate, equals(DateTime(2016, DateTime.january, 12))); }); - testWidgets('Can select a month', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can select a month', (WidgetTester tester) async { DateTime? displayedMonth; await tester.pumpWidget(calendarDatePicker( initialDate: DateTime(2016, DateTime.january, 15), @@ -121,7 +121,7 @@ void main() { expect(displayedMonth, equals(DateTime(2015, DateTime.december))); }); - testWidgets('Can select a month with nothing first selected', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can select a month with nothing first selected', (WidgetTester tester) async { DateTime? displayedMonth; await tester.pumpWidget(calendarDatePicker( onDisplayedMonthChanged: (DateTime date) => displayedMonth = date, @@ -145,7 +145,7 @@ void main() { expect(displayedMonth, equals(DateTime(2015, DateTime.december))); }); - testWidgets('Can select a year', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can select a year', (WidgetTester tester) async { DateTime? displayedMonth; await tester.pumpWidget(calendarDatePicker( initialDate: DateTime(2016, DateTime.january, 15), @@ -160,7 +160,7 @@ void main() { expect(displayedMonth, equals(DateTime(2018))); }); - testWidgets('Can select a year with nothing first selected', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can select a year with nothing first selected', (WidgetTester tester) async { DateTime? displayedMonth; await tester.pumpWidget(calendarDatePicker( onDisplayedMonthChanged: (DateTime date) => displayedMonth = date, @@ -174,7 +174,7 @@ void main() { expect(displayedMonth, equals(DateTime(2018))); }); - testWidgets('Selecting date does not change displayed month', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Selecting date does not change displayed month', (WidgetTester tester) async { DateTime? selectedDate; DateTime? displayedMonth; await tester.pumpWidget(calendarDatePicker( @@ -197,7 +197,7 @@ void main() { expect(find.text('31'), findsNothing); }); - testWidgets('Changing year does change selected date', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Changing year does change selected date', (WidgetTester tester) async { DateTime? selectedDate; await tester.pumpWidget(calendarDatePicker( initialDate: DateTime(2016, DateTime.january, 15), @@ -249,7 +249,7 @@ void main() { expect(displayedMonth, equals(DateTime(2018, DateTime.march))); }); - testWidgets('Can select a year and then a day', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can select a year and then a day', (WidgetTester tester) async { DateTime? selectedDate; await tester.pumpWidget(calendarDatePicker( initialDate: DateTime(2016, DateTime.january, 15), @@ -263,7 +263,7 @@ void main() { expect(selectedDate, equals(DateTime(2017, DateTime.january, 19))); }); - testWidgets('Cannot select a day outside bounds', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Cannot select a day outside bounds', (WidgetTester tester) async { final DateTime validDate = DateTime(2017, DateTime.january, 15); DateTime? selectedDate; await tester.pumpWidget(calendarDatePicker( @@ -286,7 +286,7 @@ void main() { expect(selectedDate, validDate); }); - testWidgets('Cannot navigate to a month outside bounds', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Cannot navigate to a month outside bounds', (WidgetTester tester) async { DateTime? displayedMonth; await tester.pumpWidget(calendarDatePicker( firstDate: DateTime(2016, DateTime.december, 15), @@ -310,7 +310,7 @@ void main() { expect(previousMonthIcon, findsNothing); }); - testWidgets('Cannot select disabled year', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Cannot select disabled year', (WidgetTester tester) async { DateTime? displayedMonth; await tester.pumpWidget(calendarDatePicker( firstDate: DateTime(2018, DateTime.june, 9), @@ -331,7 +331,7 @@ void main() { expect(displayedMonth, isNull); }); - testWidgets('Selecting firstDate year respects firstDate', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Selecting firstDate year respects firstDate', (WidgetTester tester) async { DateTime? selectedDate; DateTime? displayedMonth; await tester.pumpWidget(calendarDatePicker( @@ -351,7 +351,7 @@ void main() { expect(selectedDate, DateTime(2016, DateTime.june, 9)); }); - testWidgets('Selecting lastDate year respects lastDate', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Selecting lastDate year respects lastDate', (WidgetTester tester) async { DateTime? selectedDate; DateTime? displayedMonth; await tester.pumpWidget(calendarDatePicker( @@ -373,7 +373,7 @@ void main() { expect(selectedDate, DateTime(2019, DateTime.january, 4)); }); - testWidgets('Selecting lastDate year respects lastDate', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Selecting lastDate year respects lastDate', (WidgetTester tester) async { DateTime? selectedDate; DateTime? displayedMonth; await tester.pumpWidget(calendarDatePicker( @@ -396,7 +396,7 @@ void main() { expect(selectedDate, DateTime(2019, DateTime.january, 4)); }); - testWidgets('Only predicate days are selectable', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Only predicate days are selectable', (WidgetTester tester) async { DateTime? selectedDate; await tester.pumpWidget(calendarDatePicker( firstDate: DateTime(2017, DateTime.january, 10), @@ -413,7 +413,7 @@ void main() { expect(selectedDate, DateTime(2017, DateTime.january, 10)); }); - testWidgets('Can select initial calendar picker mode', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can select initial calendar picker mode', (WidgetTester tester) async { await tester.pumpWidget(calendarDatePicker( initialDate: DateTime(2014, DateTime.january, 15), initialCalendarMode: DatePickerMode.year, @@ -425,7 +425,7 @@ void main() { expect(find.text('January 2018'), findsOneWidget); }); - testWidgets('Material2 - currentDate is highlighted', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material2 - currentDate is highlighted', (WidgetTester tester) async { await tester.pumpWidget(calendarDatePicker( useMaterial3: false, initialDate: DateTime(2016, DateTime.january, 15), @@ -443,7 +443,7 @@ void main() { ); }); - testWidgets('Material3 - currentDate is highlighted', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material3 - currentDate is highlighted', (WidgetTester tester) async { await tester.pumpWidget(calendarDatePicker( useMaterial3: true, initialDate: DateTime(2016, DateTime.january, 15), @@ -461,7 +461,7 @@ void main() { ); }); - testWidgets('Material2 - currentDate is highlighted even if it is disabled', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material2 - currentDate is highlighted even if it is disabled', (WidgetTester tester) async { await tester.pumpWidget(calendarDatePicker( useMaterial3: false, firstDate: DateTime(2016, 1, 3), @@ -482,7 +482,7 @@ void main() { ); }); - testWidgets('Material3 - currentDate is highlighted even if it is disabled', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material3 - currentDate is highlighted even if it is disabled', (WidgetTester tester) async { await tester.pumpWidget(calendarDatePicker( useMaterial3: true, firstDate: DateTime(2016, 1, 3), @@ -503,7 +503,7 @@ void main() { ); }); - testWidgets('Selecting date does not switch picker to year selection', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Selecting date does not switch picker to year selection', (WidgetTester tester) async { await tester.pumpWidget(calendarDatePicker( initialDate: DateTime(2020, DateTime.may, 10), initialCalendarMode: DatePickerMode.year, @@ -517,7 +517,7 @@ void main() { expect(find.text('2017'), findsNothing); }); - testWidgets('Selecting disabled date does not change current selection', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Selecting disabled date does not change current selection', (WidgetTester tester) async { DateTime day(int day) => DateTime(2020, DateTime.may, day); DateTime selection = day(2); @@ -542,7 +542,7 @@ void main() { }); for (final bool useMaterial3 in <bool>[false, true]) { - testWidgets('Updates to initialDate parameter are not reflected in the state (useMaterial3=$useMaterial3)', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Updates to initialDate parameter are not reflected in the state (useMaterial3=$useMaterial3)', (WidgetTester tester) async { final Key pickerKey = UniqueKey(); final DateTime initialDate = DateTime(2020, 1, 21); final DateTime updatedDate = DateTime(1976, 2, 23); @@ -592,7 +592,7 @@ void main() { }); } - testWidgets('Updates to initialCalendarMode parameter is not reflected in the state', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Updates to initialCalendarMode parameter is not reflected in the state', (WidgetTester tester) async { final Key pickerKey = UniqueKey(); await tester.pumpWidget(calendarDatePicker( @@ -619,7 +619,7 @@ void main() { expect(find.text('2016'), findsOneWidget); // 2016 in year grid }); - testWidgets('Dragging more than half the width should not cause a jump', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Dragging more than half the width should not cause a jump', (WidgetTester tester) async { await tester.pumpWidget(calendarDatePicker( initialDate: DateTime(2016, DateTime.january, 15), )); @@ -641,7 +641,7 @@ void main() { }); group('Keyboard navigation', () { - testWidgets('Can toggle to year mode', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can toggle to year mode', (WidgetTester tester) async { await tester.pumpWidget(calendarDatePicker( initialDate: DateTime(2016, DateTime.january, 15), )); @@ -656,7 +656,7 @@ void main() { expect(find.text('January 2016'), findsOneWidget); }); - testWidgets('Can navigate next/previous months', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can navigate next/previous months', (WidgetTester tester) async { await tester.pumpWidget(calendarDatePicker( initialDate: DateTime(2016, DateTime.january, 15), )); @@ -685,7 +685,7 @@ void main() { expect(find.text('March 2016'), findsOneWidget); }); - testWidgets('Can navigate date grid with arrow keys', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can navigate date grid with arrow keys', (WidgetTester tester) async { DateTime? selectedDate; await tester.pumpWidget(calendarDatePicker( initialDate: DateTime(2016, DateTime.january, 15), @@ -715,7 +715,7 @@ void main() { expect(selectedDate, DateTime(2016, DateTime.january, 18)); }); - testWidgets('Navigating with arrow keys scrolls months', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Navigating with arrow keys scrolls months', (WidgetTester tester) async { DateTime? selectedDate; await tester.pumpWidget(calendarDatePicker( initialDate: DateTime(2016, DateTime.january, 15), @@ -756,7 +756,7 @@ void main() { expect(selectedDate, DateTime(2015, DateTime.november, 26)); }); - testWidgets('RTL text direction reverses the horizontal arrow key navigation', (WidgetTester tester) async { + testWidgetsWithLeakTracking('RTL text direction reverses the horizontal arrow key navigation', (WidgetTester tester) async { DateTime? selectedDate; await tester.pumpWidget(calendarDatePicker( initialDate: DateTime(2016, DateTime.january, 15), @@ -800,7 +800,7 @@ void main() { feedback.dispose(); }); - testWidgets('Selecting date vibrates', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Selecting date vibrates', (WidgetTester tester) async { await tester.pumpWidget(calendarDatePicker( initialDate: DateTime(2016, DateTime.january, 15), )); @@ -815,7 +815,7 @@ void main() { expect(feedback.hapticCount, 3); }); - testWidgets('Tapping unselectable date does not vibrate', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Tapping unselectable date does not vibrate', (WidgetTester tester) async { await tester.pumpWidget(calendarDatePicker( initialDate: DateTime(2016, DateTime.january, 10), selectableDayPredicate: (DateTime date) => date.day.isEven, @@ -831,7 +831,7 @@ void main() { expect(feedback.hapticCount, 0); }); - testWidgets('Changing modes and year vibrates', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Changing modes and year vibrates', (WidgetTester tester) async { await tester.pumpWidget(calendarDatePicker( initialDate: DateTime(2016, DateTime.january, 15), )); @@ -845,7 +845,7 @@ void main() { }); group('Semantics', () { - testWidgets('day mode', (WidgetTester tester) async { + testWidgetsWithLeakTracking('day mode', (WidgetTester tester) async { final SemanticsHandle semantics = tester.ensureSemantics(); await tester.pumpWidget(calendarDatePicker( @@ -1061,7 +1061,7 @@ void main() { semantics.dispose(); }); - testWidgets('calendar year mode', (WidgetTester tester) async { + testWidgetsWithLeakTracking('calendar year mode', (WidgetTester tester) async { final SemanticsHandle semantics = tester.ensureSemantics(); await tester.pumpWidget(calendarDatePicker( @@ -1091,12 +1091,12 @@ void main() { }); group('YearPicker', () { - testWidgets('Current year is visible in year picker', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Current year is visible in year picker', (WidgetTester tester) async { await tester.pumpWidget(yearPicker()); expect(find.text('2016'), findsOneWidget); }); - testWidgets('Can select a year', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can select a year', (WidgetTester tester) async { DateTime? selectedDate; await tester.pumpWidget(yearPicker( onChanged: (DateTime date) => selectedDate = date, @@ -1107,7 +1107,7 @@ void main() { expect(selectedDate, equals(DateTime(2018))); }); - testWidgets('Cannot select disabled year', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Cannot select disabled year', (WidgetTester tester) async { DateTime? selectedYear; await tester.pumpWidget(yearPicker( firstDate: DateTime(2018, DateTime.june, 9), @@ -1126,7 +1126,7 @@ void main() { expect(selectedYear, equals(DateTime(2018, DateTime.july))); }); - testWidgets('Selecting year with no selected month uses earliest month', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Selecting year with no selected month uses earliest month', (WidgetTester tester) async { DateTime? selectedYear; await tester.pumpWidget(yearPicker( firstDate: DateTime(2018, DateTime.june, 9), @@ -1145,7 +1145,7 @@ void main() { expect(selectedYear, equals(DateTime(2019, DateTime.june))); }); - testWidgets('Selecting year with no selected month uses January', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Selecting year with no selected month uses January', (WidgetTester tester) async { DateTime? selectedYear; await tester.pumpWidget(yearPicker( firstDate: DateTime(2018, DateTime.june, 9), diff --git a/packages/flutter/test/material/chip_test.dart b/packages/flutter/test/material/chip_test.dart index 992bd5947b05c..d95f4fbad7a24 100644 --- a/packages/flutter/test/material/chip_test.dart +++ b/packages/flutter/test/material/chip_test.dart @@ -703,11 +703,13 @@ void main() { expect(calledDelete, isFalse); }); - testWidgets('Chip elements are ordered horizontally for locale', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Chip elements are ordered horizontally for locale', (WidgetTester tester) async { final UniqueKey iconKey = UniqueKey(); + late final OverlayEntry entry; + addTearDown(() => entry..remove()..dispose()); final Widget test = Overlay( initialEntries: <OverlayEntry>[ - OverlayEntry( + entry = OverlayEntry( builder: (BuildContext context) { return Material( child: Chip( @@ -882,11 +884,14 @@ void main() { testWidgets('Chip padding - LTR', (WidgetTester tester) async { final GlobalKey keyA = GlobalKey(); final GlobalKey keyB = GlobalKey(); + + late final OverlayEntry entry; + addTearDown(() => entry..remove()..dispose()); await tester.pumpWidget( wrapForChip( child: Overlay( initialEntries: <OverlayEntry>[ - OverlayEntry( + entry = OverlayEntry( builder: (BuildContext context) { return Material( child: Center( @@ -918,12 +923,16 @@ void main() { testWidgets('Chip padding - RTL', (WidgetTester tester) async { final GlobalKey keyA = GlobalKey(); final GlobalKey keyB = GlobalKey(); + + late final OverlayEntry entry; + addTearDown(() => entry..remove()..dispose()); + await tester.pumpWidget( wrapForChip( textDirection: TextDirection.rtl, child: Overlay( initialEntries: <OverlayEntry>[ - OverlayEntry( + entry = OverlayEntry( builder: (BuildContext context) { return Material( child: Center( diff --git a/packages/flutter/test/widgets/undo_history_test.dart b/packages/flutter/test/widgets/undo_history_test.dart index ce09b652e4d62..dffb059bfc6ef 100644 --- a/packages/flutter/test/widgets/undo_history_test.dart +++ b/packages/flutter/test/widgets/undo_history_test.dart @@ -9,7 +9,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'editable_text_utils.dart'; -final FocusNode focusNode = FocusNode(debugLabel: 'UndoHistory Node'); +final FocusNode _focusNode = FocusNode(debugLabel: 'UndoHistory Node'); void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -41,7 +41,7 @@ void main() { onTriggered: (int newValue) { value.value = newValue; }, - focusNode: focusNode, + focusNode: _focusNode, child: Container(), ), ), @@ -57,7 +57,7 @@ void main() { controller.redo(); expect(value.value, 0); - focusNode.requestFocus(); + _focusNode.requestFocus(); await tester.pump(); expect(controller.value.canUndo, false); expect(controller.value.canRedo, false); @@ -130,9 +130,9 @@ void main() { onTriggered: (int newValue) { value.value = newValue; }, - focusNode: focusNode, + focusNode: _focusNode, child: Focus( - focusNode: focusNode, + focusNode: _focusNode, child: Container(), ), ), @@ -149,7 +149,7 @@ void main() { await sendRedo(tester); expect(value.value, 0); - focusNode.requestFocus(); + _focusNode.requestFocus(); await tester.pump(); expect(controller.value.canUndo, false); expect(controller.value.canRedo, false); @@ -222,13 +222,13 @@ void main() { onTriggered: (int newValue) { value.value = newValue; }, - focusNode: focusNode, + focusNode: _focusNode, child: Container(), ), ), ); - focusNode.requestFocus(); + _focusNode.requestFocus(); // Wait for the throttling. await tester.pump(const Duration(milliseconds: 500)); @@ -275,7 +275,7 @@ void main() { onTriggered: (int newValue) { value.value = valueToUse(newValue); }, - focusNode: focusNode, + focusNode: _focusNode, child: Container(), ), ), @@ -291,7 +291,7 @@ void main() { controller.redo(); expect(value.value, 0); - focusNode.requestFocus(); + _focusNode.requestFocus(); await tester.pump(); expect(controller.value.canUndo, false); expect(controller.value.canRedo, false); @@ -389,9 +389,9 @@ void main() { onTriggered: (int newValue) { value.value = newValue; }, - focusNode: focusNode, + focusNode: _focusNode, child: Focus( - focusNode: focusNode, + focusNode: _focusNode, child: Container(), ), ), @@ -399,7 +399,7 @@ void main() { ); await tester.pump(const Duration(milliseconds: 500)); - focusNode.requestFocus(); + _focusNode.requestFocus(); await tester.pump(); // Undo/redo have no effect if the value has never changed.