From 7cd8b4074fa43a073bbf4a67c6b0c54a78b36f1a Mon Sep 17 00:00:00 2001 From: Kostia Sokolovskyi Date: Wed, 13 Sep 2023 18:54:19 +0200 Subject: [PATCH] Cover more test/widgets tests with leak tracking #4 (#134663) --- .../widgets/implicit_animations_test.dart | 52 ++++---- .../test/widgets/implicit_semantics_test.dart | 5 +- .../widgets/inherited_dependencies_test.dart | 3 +- .../test/widgets/inherited_model_test.dart | 9 +- .../flutter/test/widgets/inherited_test.dart | 27 ++-- .../test/widgets/inherited_theme_test.dart | 7 +- .../flutter/test/widgets/init_state_test.dart | 3 +- .../test/widgets/interactive_viewer_test.dart | 126 ++++++++---------- .../test/widgets/intrinsic_width_test.dart | 3 +- .../test/widgets/invert_colors_test.dart | 5 +- .../flutter/test/widgets/keep_alive_test.dart | 9 +- packages/flutter/test/widgets/key_test.dart | 3 +- .../test/widgets/keyboard_listener_test.dart | 16 ++- .../layout_builder_and_global_keys_test.dart | 5 +- .../layout_builder_and_parent_data_test.dart | 3 +- .../layout_builder_and_state_test.dart | 3 +- .../layout_builder_mutations_test.dart | 7 +- .../test/widgets/layout_builder_test.dart | 31 +++-- .../test/widgets/linked_scroll_view_test.dart | 5 +- .../flutter/test/widgets/list_body_test.dart | 13 +- .../test/widgets/list_view_builder_test.dart | 27 ++-- .../widgets/list_view_correction_test.dart | 13 +- .../test/widgets/list_view_fling_test.dart | 3 +- .../widgets/list_view_horizontal_test.dart | 9 +- .../test/widgets/list_view_misc_test.dart | 14 +- .../test/widgets/list_view_relayout_test.dart | 13 +- .../widgets/list_view_semantics_test.dart | 13 +- .../flutter/test/widgets/list_view_test.dart | 62 +++++---- .../test/widgets/list_view_vertical_test.dart | 5 +- .../widgets/list_view_viewporting_test.dart | 50 ++++--- .../list_view_with_inherited_test.dart | 3 +- 31 files changed, 301 insertions(+), 246 deletions(-) diff --git a/packages/flutter/test/widgets/implicit_animations_test.dart b/packages/flutter/test/widgets/implicit_animations_test.dart index 405968766558..d71b942d23db 100644 --- a/packages/flutter/test/widgets/implicit_animations_test.dart +++ b/packages/flutter/test/widgets/implicit_animations_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'; class MockOnEndFunction { int called = 0; @@ -24,7 +25,7 @@ void main() { mockOnEndFunction = MockOnEndFunction(); }); - testWidgets('BoxConstraintsTween control test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('BoxConstraintsTween control test', (WidgetTester tester) async { final BoxConstraintsTween tween = BoxConstraintsTween( begin: BoxConstraints.tight(const Size(20.0, 50.0)), end: BoxConstraints.tight(const Size(10.0, 30.0)), @@ -36,7 +37,7 @@ void main() { expect(result.maxHeight, 45.0); }); - testWidgets('DecorationTween control test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('DecorationTween control test', (WidgetTester tester) async { final DecorationTween tween = DecorationTween( begin: const BoxDecoration(color: Color(0xFF00FF00)), end: const BoxDecoration(color: Color(0xFFFFFF00)), @@ -45,7 +46,7 @@ void main() { expect(result.color, const Color(0xFF3FFF00)); }); - testWidgets('EdgeInsetsTween control test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('EdgeInsetsTween control test', (WidgetTester tester) async { final EdgeInsetsTween tween = EdgeInsetsTween( begin: const EdgeInsets.symmetric(vertical: 50.0), end: const EdgeInsets.only(top: 10.0, bottom: 30.0), @@ -57,7 +58,7 @@ void main() { expect(result.bottom, 45.0); }); - testWidgets('Matrix4Tween control test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Matrix4Tween control test', (WidgetTester tester) async { final Matrix4Tween tween = Matrix4Tween( begin: Matrix4.translationValues(10.0, 20.0, 30.0), end: Matrix4.translationValues(14.0, 24.0, 34.0), @@ -66,7 +67,7 @@ void main() { expect(result, equals(Matrix4.translationValues(11.0, 21.0, 31.0))); }); - testWidgets('AnimatedContainer onEnd callback test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('AnimatedContainer onEnd callback test', (WidgetTester tester) async { await tester.pumpWidget(wrap( child: TestAnimatedWidget( callback: mockOnEndFunction.handler, @@ -89,7 +90,7 @@ void main() { await tapTest2and3(tester, widgetFinder, mockOnEndFunction); }); - testWidgets('AnimatedPadding onEnd callback test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('AnimatedPadding onEnd callback test', (WidgetTester tester) async { await tester.pumpWidget(wrap( child: TestAnimatedWidget( callback: mockOnEndFunction.handler, @@ -112,7 +113,7 @@ void main() { await tapTest2and3(tester, widgetFinder, mockOnEndFunction); }); - testWidgets('AnimatedAlign onEnd callback test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('AnimatedAlign onEnd callback test', (WidgetTester tester) async { await tester.pumpWidget(wrap( child: TestAnimatedWidget( callback: mockOnEndFunction.handler, @@ -135,7 +136,7 @@ void main() { await tapTest2and3(tester, widgetFinder, mockOnEndFunction); }); - testWidgets('AnimatedPositioned onEnd callback test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('AnimatedPositioned onEnd callback test', (WidgetTester tester) async { await tester.pumpWidget(wrap( child: TestAnimatedWidget( callback: mockOnEndFunction.handler, @@ -158,7 +159,7 @@ void main() { await tapTest2and3(tester, widgetFinder, mockOnEndFunction); }); - testWidgets('AnimatedPositionedDirectional onEnd callback test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('AnimatedPositionedDirectional onEnd callback test', (WidgetTester tester) async { await tester.pumpWidget(wrap( child: TestAnimatedWidget( callback: mockOnEndFunction.handler, @@ -181,7 +182,7 @@ void main() { await tapTest2and3(tester, widgetFinder, mockOnEndFunction); }); - testWidgets('AnimatedSlide onEnd callback test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('AnimatedSlide onEnd callback test', (WidgetTester tester) async { await tester.pumpWidget(wrap( child: TestAnimatedWidget( callback: mockOnEndFunction.handler, @@ -203,7 +204,7 @@ void main() { await tapTest2and3(tester, widgetFinder, mockOnEndFunction); }); - testWidgets('AnimatedSlide transition test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('AnimatedSlide transition test', (WidgetTester tester) async { await tester.pumpWidget(wrap( child: TestAnimatedWidget( switchKey: switchKey, @@ -241,7 +242,7 @@ void main() { expect(state.builds, equals(2)); }); - testWidgets('AnimatedScale onEnd callback test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('AnimatedScale onEnd callback test', (WidgetTester tester) async { await tester.pumpWidget(wrap( child: TestAnimatedWidget( callback: mockOnEndFunction.handler, @@ -263,7 +264,7 @@ void main() { await tapTest2and3(tester, widgetFinder, mockOnEndFunction); }); - testWidgets('AnimatedScale transition test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('AnimatedScale transition test', (WidgetTester tester) async { await tester.pumpWidget(wrap( child: TestAnimatedWidget( switchKey: switchKey, @@ -301,7 +302,7 @@ void main() { expect(state.builds, equals(2)); }); - testWidgets('AnimatedRotation onEnd callback test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('AnimatedRotation onEnd callback test', (WidgetTester tester) async { await tester.pumpWidget(wrap( child: TestAnimatedWidget( callback: mockOnEndFunction.handler, @@ -323,7 +324,7 @@ void main() { await tapTest2and3(tester, widgetFinder, mockOnEndFunction); }); - testWidgets('AnimatedRotation transition test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('AnimatedRotation transition test', (WidgetTester tester) async { await tester.pumpWidget(wrap( child: TestAnimatedWidget( switchKey: switchKey, @@ -361,7 +362,7 @@ void main() { expect(state.builds, equals(2)); }); - testWidgets('AnimatedOpacity onEnd callback test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('AnimatedOpacity onEnd callback test', (WidgetTester tester) async { await tester.pumpWidget(wrap( child: TestAnimatedWidget( callback: mockOnEndFunction.handler, @@ -383,7 +384,7 @@ void main() { await tapTest2and3(tester, widgetFinder, mockOnEndFunction); }); - testWidgets('AnimatedOpacity transition test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('AnimatedOpacity transition test', (WidgetTester tester) async { await tester.pumpWidget(wrap( child: TestAnimatedWidget( switchKey: switchKey, @@ -421,7 +422,7 @@ void main() { expect(state.builds, equals(2)); }); - testWidgets('AnimatedFractionallySizedBox onEnd callback test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('AnimatedFractionallySizedBox onEnd callback test', (WidgetTester tester) async { await tester.pumpWidget(wrap( child: TestAnimatedWidget( callback: mockOnEndFunction.handler, @@ -443,7 +444,7 @@ void main() { await tapTest2and3(tester, widgetFinder, mockOnEndFunction); }); - testWidgets('SliverAnimatedOpacity onEnd callback test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SliverAnimatedOpacity onEnd callback test', (WidgetTester tester) async { await tester.pumpWidget(TestAnimatedWidget( callback: mockOnEndFunction.handler, switchKey: switchKey, @@ -464,7 +465,7 @@ void main() { await tapTest2and3(tester, widgetFinder, mockOnEndFunction); }); - testWidgets('SliverAnimatedOpacity transition test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SliverAnimatedOpacity transition test', (WidgetTester tester) async { await tester.pumpWidget(wrap( child: TestAnimatedWidget( switchKey: switchKey, @@ -502,7 +503,7 @@ void main() { expect(state.builds, equals(2)); }); - testWidgets('AnimatedDefaultTextStyle onEnd callback test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('AnimatedDefaultTextStyle onEnd callback test', (WidgetTester tester) async { await tester.pumpWidget(wrap( child: TestAnimatedWidget( callback: mockOnEndFunction.handler, @@ -525,7 +526,7 @@ void main() { await tapTest2and3(tester, widgetFinder, mockOnEndFunction); }); - testWidgets('AnimatedPhysicalModel onEnd callback test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('AnimatedPhysicalModel onEnd callback test', (WidgetTester tester) async { await tester.pumpWidget(wrap( child: TestAnimatedWidget( callback: mockOnEndFunction.handler, @@ -548,7 +549,7 @@ void main() { await tapTest2and3(tester, widgetFinder, mockOnEndFunction); }); - testWidgets('TweenAnimationBuilder onEnd callback test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('TweenAnimationBuilder onEnd callback test', (WidgetTester tester) async { await tester.pumpWidget(wrap( child: TestAnimatedWidget( callback: mockOnEndFunction.handler, @@ -571,7 +572,7 @@ void main() { await tapTest2and3(tester, widgetFinder, mockOnEndFunction); }); - testWidgets('AnimatedTheme onEnd callback test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('AnimatedTheme onEnd callback test', (WidgetTester tester) async { await tester.pumpWidget(wrap( child: TestAnimatedWidget( callback: mockOnEndFunction.handler, @@ -594,11 +595,12 @@ void main() { await tapTest2and3(tester, widgetFinder, mockOnEndFunction); }); - testWidgets('Ensure CurvedAnimations are disposed on widget change', + testWidgetsWithLeakTracking('Ensure CurvedAnimations are disposed on widget change', (WidgetTester tester) async { final GlobalKey> key = GlobalKey>(); final ValueNotifier curve = ValueNotifier(const Interval(0.0, 0.5)); + addTearDown(curve.dispose); await tester.pumpWidget(wrap( child: ValueListenableBuilder( valueListenable: curve, diff --git a/packages/flutter/test/widgets/implicit_semantics_test.dart b/packages/flutter/test/widgets/implicit_semantics_test.dart index 42ef79223539..41d6ac7e21fb 100644 --- a/packages/flutter/test/widgets/implicit_semantics_test.dart +++ b/packages/flutter/test/widgets/implicit_semantics_test.dart @@ -5,11 +5,12 @@ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; import 'semantics_tester.dart'; void main() { - testWidgets('Implicit Semantics merge behavior', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Implicit Semantics merge behavior', (WidgetTester tester) async { final SemanticsTester semantics = SemanticsTester(tester); await tester.pumpWidget( @@ -172,7 +173,7 @@ void main() { semantics.dispose(); }); - testWidgets('Do not merge with conflicts', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Do not merge with conflicts', (WidgetTester tester) async { final SemanticsTester semantics = SemanticsTester(tester); await tester.pumpWidget( diff --git a/packages/flutter/test/widgets/inherited_dependencies_test.dart b/packages/flutter/test/widgets/inherited_dependencies_test.dart index 2ed743e47cc0..22840f52892f 100644 --- a/packages/flutter/test/widgets/inherited_dependencies_test.dart +++ b/packages/flutter/test/widgets/inherited_dependencies_test.dart @@ -5,9 +5,10 @@ import 'package:flutter/src/widgets/basic.dart'; import 'package:flutter/src/widgets/framework.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; void main() { - testWidgets('InheritedWidget dependencies show up in diagnostic properties', (WidgetTester tester) async { + testWidgetsWithLeakTracking('InheritedWidget dependencies show up in diagnostic properties', (WidgetTester tester) async { final GlobalKey key = GlobalKey(); await tester.pumpWidget(Directionality( key: key, diff --git a/packages/flutter/test/widgets/inherited_model_test.dart b/packages/flutter/test/widgets/inherited_model_test.dart index 6753361cb42e..b1ae5ef2f69c 100644 --- a/packages/flutter/test/widgets/inherited_model_test.dart +++ b/packages/flutter/test/widgets/inherited_model_test.dart @@ -5,6 +5,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; // A simple "flat" InheritedModel: the data model is just 3 integer // valued fields: a, b, c. @@ -73,7 +74,7 @@ class _ShowABCFieldState extends State { } void main() { - testWidgets('InheritedModel basics', (WidgetTester tester) async { + testWidgetsWithLeakTracking('InheritedModel basics', (WidgetTester tester) async { int a = 0; int b = 1; int c = 2; @@ -189,7 +190,7 @@ void main() { expect(find.text('a: 2 b: 2 c: 3'), findsOneWidget); }); - testWidgets('Looking up an non existent InheritedModel ancestor returns null', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Looking up an non existent InheritedModel ancestor returns null', (WidgetTester tester) async { ABCModel? inheritedModel; await tester.pumpWidget( @@ -205,7 +206,7 @@ void main() { expect(inheritedModel, null); }); - testWidgets('Inner InheritedModel shadows the outer one', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Inner InheritedModel shadows the outer one', (WidgetTester tester) async { int a = 0; int b = 1; int c = 2; @@ -323,7 +324,7 @@ void main() { expect(find.text('a: 102 b: 102 c: null'), findsOneWidget); }); - testWidgets('InheritedModel inner models supported aspect change', (WidgetTester tester) async { + testWidgetsWithLeakTracking('InheritedModel inner models supported aspect change', (WidgetTester tester) async { int a = 0; int b = 1; int c = 2; diff --git a/packages/flutter/test/widgets/inherited_test.dart b/packages/flutter/test/widgets/inherited_test.dart index e1c9b8c83f01..478ed93d419d 100644 --- a/packages/flutter/test/widgets/inherited_test.dart +++ b/packages/flutter/test/widgets/inherited_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'; import 'test_widgets.dart'; @@ -55,7 +56,7 @@ class ChangeNotifierInherited extends InheritedNotifier { } void main() { - testWidgets('Inherited notifies dependents', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Inherited notifies dependents', (WidgetTester tester) async { final List log = []; final Builder builder = Builder( @@ -81,7 +82,7 @@ void main() { expect(log, equals([first, third])); }); - testWidgets('Update inherited when reparenting state', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Update inherited when reparenting state', (WidgetTester tester) async { final GlobalKey globalKey = GlobalKey(); final List log = []; @@ -111,7 +112,7 @@ void main() { expect(log, equals([first, second])); }); - testWidgets('Update inherited when removing node', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Update inherited when removing node', (WidgetTester tester) async { final List log = []; await tester.pumpWidget( @@ -166,7 +167,7 @@ void main() { log.clear(); }); - testWidgets('Update inherited when removing node and child has global key', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Update inherited when removing node and child has global key', (WidgetTester tester) async { final List log = []; @@ -230,7 +231,7 @@ void main() { log.clear(); }); - testWidgets('Update inherited when removing node and child has global key with constant child', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Update inherited when removing node and child has global key with constant child', (WidgetTester tester) async { final List log = []; final Key key = GlobalKey(); @@ -289,7 +290,7 @@ void main() { log.clear(); }); - testWidgets('Update inherited when removing node and child has global key with constant child, minimised', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Update inherited when removing node and child has global key with constant child, minimised', (WidgetTester tester) async { final List log = []; @@ -336,7 +337,7 @@ void main() { log.clear(); }); - testWidgets('Inherited widget notifies descendants when descendant previously failed to find a match', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Inherited widget notifies descendants when descendant previously failed to find a match', (WidgetTester tester) async { int? inheritedValue = -1; final Widget inner = Container( @@ -365,7 +366,7 @@ void main() { expect(inheritedValue, equals(3)); }); - testWidgets("Inherited widget doesn't notify descendants when descendant did not previously fail to find a match and had no dependencies", (WidgetTester tester) async { + testWidgetsWithLeakTracking("Inherited widget doesn't notify descendants when descendant did not previously fail to find a match and had no dependencies", (WidgetTester tester) async { int buildCount = 0; final Widget inner = Container( @@ -392,7 +393,7 @@ void main() { expect(buildCount, equals(1)); }); - testWidgets('Inherited widget does notify descendants when descendant did not previously fail to find a match but did have other dependencies', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Inherited widget does notify descendants when descendant did not previously fail to find a match but did have other dependencies', (WidgetTester tester) async { int buildCount = 0; final Widget inner = Container( @@ -423,10 +424,11 @@ void main() { expect(buildCount, equals(2)); }); - testWidgets("BuildContext.getInheritedWidgetOfExactType doesn't create a dependency", (WidgetTester tester) async { + testWidgetsWithLeakTracking("BuildContext.getInheritedWidgetOfExactType doesn't create a dependency", (WidgetTester tester) async { int buildCount = 0; final GlobalKey inheritedKey = GlobalKey(); final ChangeNotifier notifier = ChangeNotifier(); + addTearDown(notifier.dispose); final Widget builder = Builder( builder: (BuildContext context) { @@ -449,7 +451,7 @@ void main() { expect(buildCount, equals(1)); }); - testWidgets('initState() dependency on Inherited asserts', (WidgetTester tester) async { + testWidgetsWithLeakTracking('initState() dependency on Inherited asserts', (WidgetTester tester) async { // This is a regression test for https://github.com/flutter/flutter/issues/5491 bool exceptionCaught = false; @@ -461,9 +463,10 @@ void main() { expect(exceptionCaught, isTrue); }); - testWidgets('InheritedNotifier', (WidgetTester tester) async { + testWidgetsWithLeakTracking('InheritedNotifier', (WidgetTester tester) async { int buildCount = 0; final ChangeNotifier notifier = ChangeNotifier(); + addTearDown(notifier.dispose); final Widget builder = Builder( builder: (BuildContext context) { diff --git a/packages/flutter/test/widgets/inherited_theme_test.dart b/packages/flutter/test/widgets/inherited_theme_test.dart index 1b677ac81af2..6315cc4674a0 100644 --- a/packages/flutter/test/widgets/inherited_theme_test.dart +++ b/packages/flutter/test/widgets/inherited_theme_test.dart @@ -4,6 +4,7 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; class TestRoute extends PageRouteBuilder { TestRoute(Widget child) : super( @@ -26,7 +27,7 @@ class IconTextBox extends StatelessWidget { } void main() { - testWidgets('InheritedTheme.captureAll()', (WidgetTester tester) async { + testWidgetsWithLeakTracking('InheritedTheme.captureAll()', (WidgetTester tester) async { const double fontSize = 32; const double iconSize = 48; const Color textColor = Color(0xFF00FF00); @@ -146,7 +147,7 @@ void main() { expect(getIconStyle().fontSize, iconSize); }); - testWidgets('InheritedTheme.captureAll() multiple IconTheme ancestors', (WidgetTester tester) async { + testWidgetsWithLeakTracking('InheritedTheme.captureAll() multiple IconTheme ancestors', (WidgetTester tester) async { // This is a regression test for https://github.com/flutter/flutter/issues/39087 const Color outerColor = Color(0xFF0000FF); @@ -206,7 +207,7 @@ void main() { expect(getIconStyle(icon2).fontSize, iconSize); }); - testWidgets('InheritedTheme.captureAll() multiple DefaultTextStyle ancestors', (WidgetTester tester) async { + testWidgetsWithLeakTracking('InheritedTheme.captureAll() multiple DefaultTextStyle ancestors', (WidgetTester tester) async { // This is a regression test for https://github.com/flutter/flutter/issues/39087 const Color textColor = Color(0xFF00FF00); diff --git a/packages/flutter/test/widgets/init_state_test.dart b/packages/flutter/test/widgets/init_state_test.dart index d6b74a256d30..759f325d9171 100644 --- a/packages/flutter/test/widgets/init_state_test.dart +++ b/packages/flutter/test/widgets/init_state_test.dart @@ -4,6 +4,7 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; List ancestors = []; @@ -28,7 +29,7 @@ class TestWidgetState extends State { } void main() { - testWidgets('initState() is called when we are in the tree', (WidgetTester tester) async { + testWidgetsWithLeakTracking('initState() is called when we are in the tree', (WidgetTester tester) async { await tester.pumpWidget(const Parent(child: TestWidget())); expect(ancestors, containsAllInOrder(['Parent', 'View', 'RootWidget'])); }); diff --git a/packages/flutter/test/widgets/interactive_viewer_test.dart b/packages/flutter/test/widgets/interactive_viewer_test.dart index b2adda8d87b1..cf6be6a59986 100644 --- a/packages/flutter/test/widgets/interactive_viewer_test.dart +++ b/packages/flutter/test/widgets/interactive_viewer_test.dart @@ -8,14 +8,24 @@ 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'; import 'package:vector_math/vector_math_64.dart' show Matrix4, Quad, Vector3; import 'gesture_utils.dart'; void main() { group('InteractiveViewer', () { - testWidgets('child fits in viewport', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + late TransformationController transformationController; + + setUp(() { + transformationController = TransformationController(); + }); + + tearDown(() { + transformationController.dispose(); + }); + + testWidgetsWithLeakTracking('child fits in viewport', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -65,8 +75,7 @@ void main() { expect(transformationController.value, isNot(equals(Matrix4.identity()))); }); - testWidgets('boundary slightly bigger than child', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('boundary slightly bigger than child', (WidgetTester tester) async { const double boundaryMargin = 10.0; await tester.pumpWidget( MaterialApp( @@ -121,8 +130,7 @@ void main() { expect(transformationController.value.getMaxScaleOnAxis(), 200.0 / 220.0); }); - testWidgets('child bigger than viewport', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('child bigger than viewport', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -197,8 +205,7 @@ void main() { expect(transformationController.value, isNot(equals(Matrix4.identity()))); }); - testWidgets('child has no dimensions', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('child has no dimensions', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -232,8 +239,7 @@ void main() { expect(tester.takeException(), isAssertionError); }); - testWidgets('no boundary', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('no boundary', (WidgetTester tester) async { const double minScale = 0.8; await tester.pumpWidget( MaterialApp( @@ -288,8 +294,7 @@ void main() { expect(transformationController.value.getMaxScaleOnAxis(), minScale); }); - testWidgets('PanAxis.free allows panning in all directions for diagonal gesture', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('PanAxis.free allows panning in all directions for diagonal gesture', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -326,8 +331,7 @@ void main() { expect(translation.y, childOffset.dy - childInterior.dy); }); - testWidgets('PanAxis.aligned allows panning in one direction only for diagonal gesture', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('PanAxis.aligned allows panning in one direction only for diagonal gesture', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -365,8 +369,7 @@ void main() { expect(translation.y, childOffset.dy - childInterior.dy); }); - testWidgets('PanAxis.aligned allows panning in one direction only for horizontal leaning gesture', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('PanAxis.aligned allows panning in one direction only for horizontal leaning gesture', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -404,8 +407,7 @@ void main() { expect(translation.y, 0.0); }); - testWidgets('PanAxis.horizontal allows panning in the horizontal direction only for diagonal gesture', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('PanAxis.horizontal allows panning in the horizontal direction only for diagonal gesture', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -443,8 +445,7 @@ void main() { expect(translation.y, 0.0); }); - testWidgets('PanAxis.horizontal allows panning in the horizontal direction only for horizontal leaning gesture', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('PanAxis.horizontal allows panning in the horizontal direction only for horizontal leaning gesture', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -482,8 +483,7 @@ void main() { expect(translation.y, 0.0); }); - testWidgets('PanAxis.horizontal does not allow panning in vertical direction on vertical gesture', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('PanAxis.horizontal does not allow panning in vertical direction on vertical gesture', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -521,8 +521,7 @@ void main() { expect(translation.y, 0.0); }); - testWidgets('PanAxis.vertical allows panning in the vertical direction only for diagonal gesture', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('PanAxis.vertical allows panning in the vertical direction only for diagonal gesture', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -560,8 +559,7 @@ void main() { expect(translation.x, 0.0); }); - testWidgets('PanAxis.vertical allows panning in the vertical direction only for vertical leaning gesture', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('PanAxis.vertical allows panning in the vertical direction only for vertical leaning gesture', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -599,8 +597,7 @@ void main() { expect(translation.x, 0.0); }); - testWidgets('PanAxis.vertical does not allow panning in horizontal direction on vertical gesture', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('PanAxis.vertical does not allow panning in horizontal direction on vertical gesture', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -638,8 +635,7 @@ void main() { expect(translation.y, 0.0); }); - testWidgets('inertia fling and boundary sliding', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('inertia fling and boundary sliding', (WidgetTester tester) async { const double boundaryMargin = 50.0; await tester.pumpWidget( MaterialApp( @@ -697,8 +693,7 @@ void main() { expect(translation.y, moreOrLessEquals(boundaryMargin, epsilon: 1e-9)); }); - testWidgets('Scaling automatically causes a centering translation', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('Scaling automatically causes a centering translation', (WidgetTester tester) async { const double boundaryMargin = 50.0; const double minScale = 0.1; await tester.pumpWidget( @@ -782,8 +777,7 @@ void main() { expect(newSceneFocalPoint.dy, moreOrLessEquals(sceneFocalPoint.dy, epsilon: 1.0)); }); - testWidgets('Scaling automatically causes a centering translation even when alignPanAxis is set', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('Scaling automatically causes a centering translation even when alignPanAxis is set', (WidgetTester tester) async { const double boundaryMargin = 50.0; const double minScale = 0.1; await tester.pumpWidget( @@ -874,8 +868,7 @@ void main() { expect(newSceneFocalPoint.dy, moreOrLessEquals(sceneFocalPoint.dy, epsilon: 1.0)); }); - testWidgets('Can scale with mouse', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('Can scale with mouse', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -896,8 +889,7 @@ void main() { expect(transformationController.value.getMaxScaleOnAxis(), greaterThan(1.0)); }); - testWidgets('Cannot scale with mouse when scale is disabled', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('Cannot scale with mouse when scale is disabled', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -919,8 +911,7 @@ void main() { expect(transformationController.value.getMaxScaleOnAxis(), equals(1.0)); }); - testWidgets('Scale with mouse returns onInteraction properties', (WidgetTester tester) async{ - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('Scale with mouse returns onInteraction properties', (WidgetTester tester) async{ late Offset focalPoint; late Offset localFocalPoint; late double scaleChange; @@ -971,8 +962,7 @@ void main() { expect(scenePoint, const Offset(100, 100)); }); - testWidgets('Scaling amount is equal forth and back with a mouse scroll', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('Scaling amount is equal forth and back with a mouse scroll', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -1003,8 +993,7 @@ void main() { expect(transformationController.value.getMaxScaleOnAxis(), 1.0); }); - testWidgets('onInteraction can be used to get scene point', (WidgetTester tester) async{ - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('onInteraction can be used to get scene point', (WidgetTester tester) async{ late Offset focalPoint; late Offset localFocalPoint; late double scaleChange; @@ -1057,8 +1046,7 @@ void main() { expect(scenePoint.dy, greaterThan(0.0)); }); - testWidgets('onInteraction is called even when disabled (touch)', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('onInteraction is called even when disabled (touch)', (WidgetTester tester) async { bool calledStart = false; bool calledUpdate = false; bool calledEnd = false; @@ -1129,8 +1117,7 @@ void main() { expect(calledEnd, isTrue); }, variant: const TargetPlatformVariant({ TargetPlatform.android, TargetPlatform.iOS })); - testWidgets('onInteraction is called even when disabled (mouse)', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('onInteraction is called even when disabled (mouse)', (WidgetTester tester) async { bool calledStart = false; bool calledUpdate = false; bool calledEnd = false; @@ -1189,10 +1176,9 @@ void main() { expect(calledEnd, isTrue); }, variant: const TargetPlatformVariant({ TargetPlatform.macOS, TargetPlatform.linux, TargetPlatform.windows })); - testWidgets('viewport changes size', (WidgetTester tester) async { + testWidgetsWithLeakTracking('viewport changes size', (WidgetTester tester) async { addTearDown(tester.view.reset); - final TransformationController transformationController = TransformationController(); await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -1239,8 +1225,7 @@ void main() { expect(transformationController.value, equals(Matrix4.identity())); }); - testWidgets('gesture can start as pan and become scale', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('gesture can start as pan and become scale', (WidgetTester tester) async { const double boundaryMargin = 50.0; await tester.pumpWidget( MaterialApp( @@ -1297,8 +1282,7 @@ void main() { }); // Regression test for https://github.com/flutter/flutter/issues/65304 - testWidgets('can view beyond boundary when necessary for a small child', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('can view beyond boundary when necessary for a small child', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -1337,8 +1321,7 @@ void main() { expect(transformationController.value, equals(Matrix4.identity())); }); - testWidgets('scale does not jump when wrapped in GestureDetector', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('scale does not jump when wrapped in GestureDetector', (WidgetTester tester) async { double? initialScale; double? scale; await tester.pumpWidget( @@ -1413,7 +1396,7 @@ void main() { expect(transformationController.value.getMaxScaleOnAxis(), greaterThan(1.0)); }); - testWidgets('Check if ClipRect is present in the tree', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Check if ClipRect is present in the tree', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -1454,8 +1437,7 @@ void main() { ); }); - testWidgets('builder can change widgets that are off-screen', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('builder can change widgets that are off-screen', (WidgetTester tester) async { const double childHeight = 10.0; await tester.pumpWidget( MaterialApp( @@ -1539,7 +1521,7 @@ void main() { // Accessing the intrinsic size of a LayoutBuilder throws an error, so // InteractiveViewer only uses a LayoutBuilder when it's needed by // InteractiveViewer.builder. - testWidgets('LayoutBuilder is only used for InteractiveViewer.builder', (WidgetTester tester) async { + testWidgetsWithLeakTracking('LayoutBuilder is only used for InteractiveViewer.builder', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -1571,9 +1553,8 @@ void main() { expect(find.byType(LayoutBuilder), findsOneWidget); }); - testWidgets('scaleFactor', (WidgetTester tester) async { + testWidgetsWithLeakTracking('scaleFactor', (WidgetTester tester) async { const double scrollAmount = 30.0; - final TransformationController transformationController = TransformationController(); Future pumpScaleFactor(double scaleFactor) { return tester.pumpWidget( MaterialApp( @@ -1651,7 +1632,7 @@ void main() { expect(scaleHighZoomedIn - scaleHighZoomedOut, lessThan(scaleZoomedIn - scaleZoomedOut)); }); - testWidgets('alignment argument is used properly', (WidgetTester tester) async { + testWidgetsWithLeakTracking('alignment argument is used properly', (WidgetTester tester) async { const Alignment alignment = Alignment.center; await tester.pumpWidget(MaterialApp( @@ -1667,9 +1648,10 @@ void main() { expect(transform.alignment, alignment); }); - testWidgets('interactionEndFrictionCoefficient', (WidgetTester tester) async { + testWidgetsWithLeakTracking('interactionEndFrictionCoefficient', (WidgetTester tester) async { // Use the default interactionEndFrictionCoefficient. final TransformationController transformationController1 = TransformationController(); + addTearDown(transformationController1.dispose); await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -1695,6 +1677,7 @@ void main() { // Next try a custom interactionEndFrictionCoefficient. final TransformationController transformationController2 = TransformationController(); + addTearDown(transformationController2.dispose); await tester.pumpWidget( MaterialApp( home: Scaffold( @@ -1723,8 +1706,7 @@ void main() { expect(translation2.y, lessThan(translation1.y)); }); - testWidgets('discrete scroll pointer events', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('discrete scroll pointer events', (WidgetTester tester) async { const double boundaryMargin = 50.0; await tester.pumpWidget( MaterialApp( @@ -1767,8 +1749,7 @@ void main() { expect(translation.y, -125); }); - testWidgets('discrete scale pointer event', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('discrete scale pointer event', (WidgetTester tester) async { const double boundaryMargin = 50.0; await tester.pumpWidget( MaterialApp( @@ -1804,8 +1785,7 @@ void main() { expect(transformationController.value.getMaxScaleOnAxis(), 2.5); // capped at maxScale (2.5) }); - testWidgets('trackpadScrollCausesScale', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('trackpadScrollCausesScale', (WidgetTester tester) async { const double boundaryMargin = 50.0; await tester.pumpWidget( MaterialApp( @@ -1840,8 +1820,7 @@ void main() { expect(transformationController.value.getMaxScaleOnAxis(), moreOrLessEquals(1.499302500056767)); }); - testWidgets('trackpad pointer scroll events cause scale', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('trackpad pointer scroll events cause scale', (WidgetTester tester) async { const double boundaryMargin = 50.0; await tester.pumpWidget( MaterialApp( @@ -1891,8 +1870,7 @@ void main() { expect(translation.y, moreOrLessEquals(-99.37155332430822)); }); - testWidgets('Scaling inertia', (WidgetTester tester) async { - final TransformationController transformationController = TransformationController(); + testWidgetsWithLeakTracking('Scaling inertia', (WidgetTester tester) async { const double boundaryMargin = 50.0; await tester.pumpWidget( MaterialApp( diff --git a/packages/flutter/test/widgets/intrinsic_width_test.dart b/packages/flutter/test/widgets/intrinsic_width_test.dart index 20848ef9f8d3..b3c1c05e58a1 100644 --- a/packages/flutter/test/widgets/intrinsic_width_test.dart +++ b/packages/flutter/test/widgets/intrinsic_width_test.dart @@ -4,9 +4,10 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; void main() { - testWidgets('Intrinsic stepWidth, stepHeight', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Intrinsic stepWidth, stepHeight', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/25224 Widget buildFrame(double? stepWidth, double? stepHeight) { return Center( diff --git a/packages/flutter/test/widgets/invert_colors_test.dart b/packages/flutter/test/widgets/invert_colors_test.dart index 2c475a9715ef..11be7632ae11 100644 --- a/packages/flutter/test/widgets/invert_colors_test.dart +++ b/packages/flutter/test/widgets/invert_colors_test.dart @@ -10,9 +10,10 @@ library; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; void main() { - testWidgets('InvertColors', (WidgetTester tester) async { + testWidgetsWithLeakTracking('InvertColors', (WidgetTester tester) async { await tester.pumpWidget(const RepaintBoundary( child: SizedBox( width: 200.0, @@ -29,7 +30,7 @@ void main() { ); }); - testWidgets('InvertColors and ColorFilter', (WidgetTester tester) async { + testWidgetsWithLeakTracking('InvertColors and ColorFilter', (WidgetTester tester) async { await tester.pumpWidget(const RepaintBoundary( child: SizedBox( width: 200.0, diff --git a/packages/flutter/test/widgets/keep_alive_test.dart b/packages/flutter/test/widgets/keep_alive_test.dart index b25a14d45d67..6bd324f99046 100644 --- a/packages/flutter/test/widgets/keep_alive_test.dart +++ b/packages/flutter/test/widgets/keep_alive_test.dart @@ -7,6 +7,7 @@ import 'dart:io' show Platform; import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; class Leaf extends StatefulWidget { const Leaf({ @@ -46,7 +47,7 @@ List generateList(Widget child) { } void main() { - testWidgets('KeepAlive with ListView with itemExtent', (WidgetTester tester) async { + testWidgetsWithLeakTracking('KeepAlive with ListView with itemExtent', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -94,7 +95,7 @@ void main() { expect(find.byKey(const GlobalObjectKey<_LeafState>(90), skipOffstage: false), findsNothing); }); - testWidgets('KeepAlive with ListView without itemExtent', (WidgetTester tester) async { + testWidgetsWithLeakTracking('KeepAlive with ListView without itemExtent', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -141,7 +142,7 @@ void main() { expect(find.byKey(const GlobalObjectKey<_LeafState>(90), skipOffstage: false), findsNothing); }); - testWidgets('KeepAlive with GridView', (WidgetTester tester) async { + testWidgetsWithLeakTracking('KeepAlive with GridView', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -190,7 +191,7 @@ void main() { expect(find.byKey(const GlobalObjectKey<_LeafState>(90), skipOffstage: false), findsNothing); }); - testWidgets('KeepAlive render tree description', (WidgetTester tester) async { + testWidgetsWithLeakTracking('KeepAlive render tree description', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, diff --git a/packages/flutter/test/widgets/key_test.dart b/packages/flutter/test/widgets/key_test.dart index b6031887325b..8ba6247659e0 100644 --- a/packages/flutter/test/widgets/key_test.dart +++ b/packages/flutter/test/widgets/key_test.dart @@ -4,6 +4,7 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; class TestValueKey extends ValueKey { const TestValueKey(super.value); @@ -19,7 +20,7 @@ class NotEquals { } void main() { - testWidgets('Keys', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Keys', (WidgetTester tester) async { expect(ValueKey(nonconst(3)) == ValueKey(nonconst(3)), isTrue); expect(ValueKey(nonconst(3)) == ValueKey(nonconst(3)), isFalse); expect(ValueKey(nonconst(3)) == ValueKey(nonconst(2)), isFalse); diff --git a/packages/flutter/test/widgets/keyboard_listener_test.dart b/packages/flutter/test/widgets/keyboard_listener_test.dart index 985e5dd3f91b..1149bddd6844 100644 --- a/packages/flutter/test/widgets/keyboard_listener_test.dart +++ b/packages/flutter/test/widgets/keyboard_listener_test.dart @@ -5,19 +5,22 @@ import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; void main() { - testWidgets('Can dispose without keyboard', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can dispose without keyboard', (WidgetTester tester) async { final FocusNode focusNode = FocusNode(); + addTearDown(focusNode.dispose); await tester.pumpWidget(KeyboardListener(focusNode: focusNode, child: Container())); await tester.pumpWidget(KeyboardListener(focusNode: focusNode, child: Container())); await tester.pumpWidget(Container()); }); - testWidgets('Fuchsia key event', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Fuchsia key event', (WidgetTester tester) async { final List events = []; final FocusNode focusNode = FocusNode(); + addTearDown(focusNode.dispose); await tester.pumpWidget( KeyboardListener( @@ -39,13 +42,13 @@ void main() { expect(events[0].logicalKey, LogicalKeyboardKey.metaLeft); await tester.pumpWidget(Container()); - focusNode.dispose(); }, skip: isBrowser); // [intended] This is a Fuchsia-specific test. - testWidgets('Web key event', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Web key event', (WidgetTester tester) async { final List events = []; final FocusNode focusNode = FocusNode(); + addTearDown(focusNode.dispose); await tester.pumpWidget( KeyboardListener( @@ -67,13 +70,13 @@ void main() { expect(events[0].logicalKey, LogicalKeyboardKey.metaLeft); await tester.pumpWidget(Container()); - focusNode.dispose(); }); - testWidgets('Defunct listeners do not receive events', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Defunct listeners do not receive events', (WidgetTester tester) async { final List events = []; final FocusNode focusNode = FocusNode(); + addTearDown(focusNode.dispose); await tester.pumpWidget( KeyboardListener( @@ -101,6 +104,5 @@ void main() { expect(events.length, 0); await tester.pumpWidget(Container()); - focusNode.dispose(); }); } diff --git a/packages/flutter/test/widgets/layout_builder_and_global_keys_test.dart b/packages/flutter/test/widgets/layout_builder_and_global_keys_test.dart index 68e6f4ee27dd..d3c9178eaa3b 100644 --- a/packages/flutter/test/widgets/layout_builder_and_global_keys_test.dart +++ b/packages/flutter/test/widgets/layout_builder_and_global_keys_test.dart @@ -5,6 +5,7 @@ import 'package:flutter/src/rendering/sliver.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; class Wrapper extends StatelessWidget { const Wrapper({ @@ -41,7 +42,7 @@ class StatefulWrapperState extends State { } void main() { - testWidgets('Moving global key inside a LayoutBuilder', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Moving global key inside a LayoutBuilder', (WidgetTester tester) async { final GlobalKey key = GlobalKey(); await tester.pumpWidget( LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) { @@ -60,7 +61,7 @@ void main() { expect(tester.takeException(), null); }); - testWidgets('Moving global key inside a SliverLayoutBuilder', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Moving global key inside a SliverLayoutBuilder', (WidgetTester tester) async { final GlobalKey key = GlobalKey(); await tester.pumpWidget( diff --git a/packages/flutter/test/widgets/layout_builder_and_parent_data_test.dart b/packages/flutter/test/widgets/layout_builder_and_parent_data_test.dart index 6388fa320e50..b98714269530 100644 --- a/packages/flutter/test/widgets/layout_builder_and_parent_data_test.dart +++ b/packages/flutter/test/widgets/layout_builder_and_parent_data_test.dart @@ -4,6 +4,7 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; class SizeChanger extends StatefulWidget { const SizeChanger({ @@ -42,7 +43,7 @@ class SizeChangerState extends State { } void main() { - testWidgets('Applying parent data inside a LayoutBuilder', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Applying parent data inside a LayoutBuilder', (WidgetTester tester) async { int frame = 1; await tester.pumpWidget(SizeChanger( // when this is triggered, the child LayoutBuilder will build again child: LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) { diff --git a/packages/flutter/test/widgets/layout_builder_and_state_test.dart b/packages/flutter/test/widgets/layout_builder_and_state_test.dart index f5687492e714..3db4baef0b78 100644 --- a/packages/flutter/test/widgets/layout_builder_and_state_test.dart +++ b/packages/flutter/test/widgets/layout_builder_and_state_test.dart @@ -4,6 +4,7 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; import 'test_widgets.dart'; @@ -49,7 +50,7 @@ class Wrapper extends StatelessWidget { } void main() { - testWidgets('Calling setState on a widget that moves into a LayoutBuilder in the same frame', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Calling setState on a widget that moves into a LayoutBuilder in the same frame', (WidgetTester tester) async { StatefulWrapperState statefulWrapper; final Widget inner = Wrapper( child: StatefulWrapper( diff --git a/packages/flutter/test/widgets/layout_builder_mutations_test.dart b/packages/flutter/test/widgets/layout_builder_mutations_test.dart index 14f151bfe01a..d5e4748d0280 100644 --- a/packages/flutter/test/widgets/layout_builder_mutations_test.dart +++ b/packages/flutter/test/widgets/layout_builder_mutations_test.dart @@ -11,6 +11,7 @@ import 'package:flutter/src/widgets/media_query.dart'; import 'package:flutter/src/widgets/scroll_view.dart'; import 'package:flutter/src/widgets/sliver_layout_builder.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; class Wrapper extends StatelessWidget { const Wrapper({ @@ -25,7 +26,7 @@ class Wrapper extends StatelessWidget { } void main() { - testWidgets('Moving a global key from another LayoutBuilder at layout time', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Moving a global key from another LayoutBuilder at layout time', (WidgetTester tester) async { final GlobalKey victimKey = GlobalKey(); await tester.pumpWidget(Row( @@ -71,7 +72,7 @@ void main() { expect(tester.takeException(), null); }); - testWidgets('Moving a global key from another SliverLayoutBuilder at layout time', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Moving a global key from another SliverLayoutBuilder at layout time', (WidgetTester tester) async { final GlobalKey victimKey1 = GlobalKey(); final GlobalKey victimKey2 = GlobalKey(); @@ -128,7 +129,7 @@ void main() { expect(tester.takeException(), null); }); - testWidgets('LayoutBuilder does not layout twice', (WidgetTester tester) async { + testWidgetsWithLeakTracking('LayoutBuilder does not layout twice', (WidgetTester tester) async { // This widget marks itself dirty when the closest MediaQuery changes. final _LayoutCount widget = _LayoutCount(); late StateSetter setState; diff --git a/packages/flutter/test/widgets/layout_builder_test.dart b/packages/flutter/test/widgets/layout_builder_test.dart index 6a298b4a88b7..18542fcd1a5d 100644 --- a/packages/flutter/test/widgets/layout_builder_test.dart +++ b/packages/flutter/test/widgets/layout_builder_test.dart @@ -5,9 +5,10 @@ import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; void main() { - testWidgets('LayoutBuilder parent size', (WidgetTester tester) async { + testWidgetsWithLeakTracking('LayoutBuilder parent size', (WidgetTester tester) async { late Size layoutBuilderSize; final Key childKey = UniqueKey(); final Key parentKey = UniqueKey(); @@ -38,7 +39,7 @@ void main() { expect(childBox.size, equals(const Size(50.0, 100.0))); }); - testWidgets('SliverLayoutBuilder parent geometry', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SliverLayoutBuilder parent geometry', (WidgetTester tester) async { late SliverConstraints parentConstraints1; late SliverConstraints parentConstraints2; final Key childKey1 = UniqueKey(); @@ -88,7 +89,7 @@ void main() { expect(childSliver2.geometry, parentSliver2.geometry); }); - testWidgets('LayoutBuilder stateful child', (WidgetTester tester) async { + testWidgetsWithLeakTracking('LayoutBuilder stateful child', (WidgetTester tester) async { late Size layoutBuilderSize; late StateSetter setState; final Key childKey = UniqueKey(); @@ -134,7 +135,7 @@ void main() { expect(childBox.size, equals(const Size(100.0, 200.0))); }); - testWidgets('SliverLayoutBuilder stateful descendants', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SliverLayoutBuilder stateful descendants', (WidgetTester tester) async { late StateSetter setState; double childWidth = 10.0; double childHeight = 20.0; @@ -203,7 +204,7 @@ void main() { expect(parentSliver.geometry!.paintExtent, 600); }); - testWidgets('LayoutBuilder stateful parent', (WidgetTester tester) async { + testWidgetsWithLeakTracking('LayoutBuilder stateful parent', (WidgetTester tester) async { late Size layoutBuilderSize; late StateSetter setState; final Key childKey = UniqueKey(); @@ -247,7 +248,7 @@ void main() { expect(box.size, equals(const Size(100.0, 200.0))); }); - testWidgets('LayoutBuilder and Inherited -- do not rebuild when not using inherited', (WidgetTester tester) async { + testWidgetsWithLeakTracking('LayoutBuilder and Inherited -- do not rebuild when not using inherited', (WidgetTester tester) async { int built = 0; final Widget target = LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { @@ -270,7 +271,7 @@ void main() { expect(built, 1); }); - testWidgets('LayoutBuilder and Inherited -- do rebuild when using inherited', (WidgetTester tester) async { + testWidgetsWithLeakTracking('LayoutBuilder and Inherited -- do rebuild when using inherited', (WidgetTester tester) async { int built = 0; final Widget target = LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { @@ -294,7 +295,7 @@ void main() { expect(built, 2); }); - testWidgets('SliverLayoutBuilder and Inherited -- do not rebuild when not using inherited', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SliverLayoutBuilder and Inherited -- do not rebuild when not using inherited', (WidgetTester tester) async { int built = 0; final Widget target = Directionality( textDirection: TextDirection.ltr, @@ -325,7 +326,7 @@ void main() { expect(built, 1); }); - testWidgets( + testWidgetsWithLeakTracking( 'SliverLayoutBuilder and Inherited -- do rebuild when not using inherited', (WidgetTester tester) async { int built = 0; @@ -360,7 +361,7 @@ void main() { }, ); - testWidgets('nested SliverLayoutBuilder', (WidgetTester tester) async { + testWidgetsWithLeakTracking('nested SliverLayoutBuilder', (WidgetTester tester) async { late SliverConstraints parentConstraints1; late SliverConstraints parentConstraints2; final Key childKey = UniqueKey(); @@ -405,10 +406,11 @@ void main() { expect(parentSliver1.geometry, parentSliver2.geometry); }); - testWidgets('localToGlobal works with SliverLayoutBuilder', (WidgetTester tester) async { + testWidgetsWithLeakTracking('localToGlobal works with SliverLayoutBuilder', (WidgetTester tester) async { final Key childKey1 = UniqueKey(); final Key childKey2 = UniqueKey(); final ScrollController scrollController = ScrollController(); + addTearDown(scrollController.dispose); await tester.pumpWidget( Directionality( @@ -461,8 +463,9 @@ void main() { ); }); - testWidgets('hitTest works within SliverLayoutBuilder', (WidgetTester tester) async { + testWidgetsWithLeakTracking('hitTest works within SliverLayoutBuilder', (WidgetTester tester) async { final ScrollController scrollController = ScrollController(); + addTearDown(scrollController.dispose); List hitCounts = [0, 0, 0]; await tester.pumpWidget( @@ -589,7 +592,7 @@ void main() { expect(hitCounts, const [0, 0, 0]); }); - testWidgets('LayoutBuilder does not call builder when layout happens but layout constraints do not change', (WidgetTester tester) async { + testWidgetsWithLeakTracking('LayoutBuilder does not call builder when layout happens but layout constraints do not change', (WidgetTester tester) async { int builderInvocationCount = 0; Future pumpTestWidget(Size size) async { @@ -665,7 +668,7 @@ void main() { expect(spy.performResizeCount, 2); }); - testWidgets('LayoutBuilder descendant widget can access [RenderBox.size] when rebuilding during layout', (WidgetTester tester) async { + testWidgetsWithLeakTracking('LayoutBuilder descendant widget can access [RenderBox.size] when rebuilding during layout', (WidgetTester tester) async { Size? childSize; int buildCount = 0; diff --git a/packages/flutter/test/widgets/linked_scroll_view_test.dart b/packages/flutter/test/widgets/linked_scroll_view_test.dart index ee2a5c5921c1..ee1373ec545a 100644 --- a/packages/flutter/test/widgets/linked_scroll_view_test.dart +++ b/packages/flutter/test/widgets/linked_scroll_view_test.dart @@ -14,6 +14,7 @@ import 'dart:math' as math; 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'; class LinkedScrollController extends ScrollController { LinkedScrollController({ this.before, this.after }); @@ -381,7 +382,7 @@ class _TestState extends State { } void main() { - testWidgets('LinkedScrollController - 1', (WidgetTester tester) async { + testWidgetsWithLeakTracking('LinkedScrollController - 1', (WidgetTester tester) async { await tester.pumpWidget(const Test()); expect(find.text('Hello A'), findsOneWidget); expect(find.text('Hello 1'), findsOneWidget); @@ -459,7 +460,7 @@ void main() { expect(find.text('Hello D'), findsNothing); expect(find.text('Hello 4'), findsOneWidget); }); - testWidgets('LinkedScrollController - 2', (WidgetTester tester) async { + testWidgetsWithLeakTracking('LinkedScrollController - 2', (WidgetTester tester) async { await tester.pumpWidget(const Test()); expect(find.text('Hello A'), findsOneWidget); expect(find.text('Hello B'), findsOneWidget); diff --git a/packages/flutter/test/widgets/list_body_test.dart b/packages/flutter/test/widgets/list_body_test.dart index 6ac39df8d32d..0bf2b609b824 100644 --- a/packages/flutter/test/widgets/list_body_test.dart +++ b/packages/flutter/test/widgets/list_body_test.dart @@ -5,6 +5,7 @@ import 'package:flutter/src/foundation/assertions.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; const List children = [ SizedBox(width: 200.0, height: 150.0), @@ -29,7 +30,7 @@ void expectRects(WidgetTester tester, List expected) { void main() { - testWidgets('ListBody down', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListBody down', (WidgetTester tester) async { await tester.pumpWidget(const Flex( direction: Axis.vertical, children: [ ListBody(children: children) ], @@ -46,7 +47,7 @@ void main() { ); }); - testWidgets('ListBody up', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListBody up', (WidgetTester tester) async { await tester.pumpWidget(const Flex( direction: Axis.vertical, children: [ ListBody(reverse: true, children: children) ], @@ -63,7 +64,7 @@ void main() { ); }); - testWidgets('ListBody right', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListBody right', (WidgetTester tester) async { await tester.pumpWidget(const Flex( textDirection: TextDirection.ltr, direction: Axis.horizontal, @@ -86,7 +87,7 @@ void main() { ); }); - testWidgets('ListBody left', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListBody left', (WidgetTester tester) async { await tester.pumpWidget(const Flex( textDirection: TextDirection.ltr, direction: Axis.horizontal, @@ -109,7 +110,7 @@ void main() { ); }); - testWidgets('Limited space along main axis error', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Limited space along main axis error', (WidgetTester tester) async { final FlutterExceptionHandler oldHandler = FlutterError.onError!; final List errors = []; FlutterError.onError = (FlutterErrorDetails error) => errors.add(error); @@ -142,7 +143,7 @@ void main() { )); }); - testWidgets('Nested ListBody unbounded cross axis error', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Nested ListBody unbounded cross axis error', (WidgetTester tester) async { final FlutterExceptionHandler oldHandler = FlutterError.onError!; final List errors = []; FlutterError.onError = (FlutterErrorDetails error) => errors.add(error); diff --git a/packages/flutter/test/widgets/list_view_builder_test.dart b/packages/flutter/test/widgets/list_view_builder_test.dart index 52b095735e0f..ccc83e248383 100644 --- a/packages/flutter/test/widgets/list_view_builder_test.dart +++ b/packages/flutter/test/widgets/list_view_builder_test.dart @@ -4,11 +4,12 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; import 'test_widgets.dart'; void main() { - testWidgets('ListView.builder mount/dismount smoke test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView.builder mount/dismount smoke test', (WidgetTester tester) async { final List callbackTracker = []; // the root view is 800x600 in the test environment @@ -61,7 +62,7 @@ void main() { check(visible: [0, 1, 2, 3, 4, 5], hidden: [ 6, 7, 8]); }); - testWidgets('ListView.builder vertical', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView.builder vertical', (WidgetTester tester) async { final List callbackTracker = []; // the root view is 800x600 in the test environment @@ -79,11 +80,14 @@ void main() { } Widget buildWidget() { + final ScrollController controller = ScrollController(initialScrollOffset: 300.0); + addTearDown(controller.dispose); + return Directionality( textDirection: TextDirection.ltr, child: FlipWidget( left: ListView.builder( - controller: ScrollController(initialScrollOffset: 300.0), + controller: controller, itemExtent: 200.0, itemBuilder: itemBuilder, ), @@ -134,7 +138,7 @@ void main() { callbackTracker.clear(); }); - testWidgets('ListView.builder horizontal', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView.builder horizontal', (WidgetTester tester) async { final List callbackTracker = []; // the root view is 800x600 in the test environment @@ -152,11 +156,14 @@ void main() { } Widget buildWidget() { + final ScrollController controller = ScrollController(initialScrollOffset: 300.0); + addTearDown(controller.dispose); + return Directionality( textDirection: TextDirection.ltr, child: FlipWidget( left: ListView.builder( - controller: ScrollController(initialScrollOffset: 300.0), + controller: controller, itemBuilder: itemBuilder, itemExtent: 200.0, scrollDirection: Axis.horizontal, @@ -208,7 +215,7 @@ void main() { callbackTracker.clear(); }); - testWidgets('ListView.builder 10 items, 2-3 items visible', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView.builder 10 items, 2-3 items visible', (WidgetTester tester) async { final List callbackTracker = []; // The root view is 800x600 in the test environment and our list @@ -261,7 +268,7 @@ void main() { callbackTracker.clear(); }); - testWidgets('ListView.builder 30 items with big jump, using prototypeItem', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView.builder 30 items with big jump, using prototypeItem', (WidgetTester tester) async { final List callbackTracker = []; // The root view is 800x600 in the test environment and our list @@ -309,7 +316,7 @@ void main() { callbackTracker.clear(); }); - testWidgets('ListView.separated', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView.separated', (WidgetTester tester) async { Widget buildFrame({ required int itemCount }) { return Directionality( textDirection: TextDirection.ltr, @@ -355,7 +362,7 @@ void main() { }); - testWidgets('ListView.separated uses correct semanticChildCount', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView.separated uses correct semanticChildCount', (WidgetTester tester) async { Widget buildFrame({ required int itemCount}) { return Directionality( textDirection: TextDirection.ltr, @@ -403,7 +410,7 @@ void main() { }); // Regression test for https://github.com/flutter/flutter/issues/72292 - testWidgets('ListView.builder and SingleChildScrollView can work well together', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView.builder and SingleChildScrollView can work well together', (WidgetTester tester) async { Widget builder(int itemCount) { return Directionality( textDirection: TextDirection.ltr, diff --git a/packages/flutter/test/widgets/list_view_correction_test.dart b/packages/flutter/test/widgets/list_view_correction_test.dart index 804e74e11394..c6d44618e9ea 100644 --- a/packages/flutter/test/widgets/list_view_correction_test.dart +++ b/packages/flutter/test/widgets/list_view_correction_test.dart @@ -4,10 +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'; void main() { - testWidgets('ListView can handle shrinking top elements', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView can handle shrinking top elements', (WidgetTester tester) async { final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -65,8 +68,10 @@ void main() { expect(tester.getTopLeft(find.text('2')).dy, equals(200.0)); }); - testWidgets('ListView can handle shrinking top elements with cache extent', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView can handle shrinking top elements with cache extent', (WidgetTester tester) async { final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -122,8 +127,10 @@ void main() { expect(tester.getTopLeft(find.text('2')).dy, equals(150.0)); }); - testWidgets('ListView can handle inserts at 0', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView can handle inserts at 0', (WidgetTester tester) async { final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, diff --git a/packages/flutter/test/widgets/list_view_fling_test.dart b/packages/flutter/test/widgets/list_view_fling_test.dart index ebf7019b4b48..aa76b397aeeb 100644 --- a/packages/flutter/test/widgets/list_view_fling_test.dart +++ b/packages/flutter/test/widgets/list_view_fling_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 double kHeight = 10.0; const double kFlingOffset = kHeight * 20.0; void main() { - testWidgets("Flings don't stutter", (WidgetTester tester) async { + testWidgetsWithLeakTracking("Flings don't stutter", (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, diff --git a/packages/flutter/test/widgets/list_view_horizontal_test.dart b/packages/flutter/test/widgets/list_view_horizontal_test.dart index 26b0533da0ac..7e3999b4507b 100644 --- a/packages/flutter/test/widgets/list_view_horizontal_test.dart +++ b/packages/flutter/test/widgets/list_view_horizontal_test.dart @@ -4,6 +4,7 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; const List items = [0, 1, 2, 3, 4, 5]; @@ -28,7 +29,7 @@ Widget buildFrame({ bool reverse = false, required TextDirection textDirection } } void main() { - testWidgets('Drag horizontally with scroll anchor at start (LTR)', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Drag horizontally with scroll anchor at start (LTR)', (WidgetTester tester) async { await tester.pumpWidget(buildFrame(textDirection: TextDirection.ltr)); await tester.pump(const Duration(seconds: 1)); @@ -147,7 +148,7 @@ void main() { expect(find.text('5'), findsNothing); }); - testWidgets('Drag horizontally with scroll anchor at end (LTR)', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Drag horizontally with scroll anchor at end (LTR)', (WidgetTester tester) async { await tester.pumpWidget(buildFrame(reverse: true, textDirection: TextDirection.ltr)); await tester.pump(const Duration(seconds: 1)); @@ -247,7 +248,7 @@ void main() { expect(find.text('5'), findsOneWidget); }); - testWidgets('Drag horizontally with scroll anchor at start (RTL)', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Drag horizontally with scroll anchor at start (RTL)', (WidgetTester tester) async { await tester.pumpWidget(buildFrame(textDirection: TextDirection.rtl)); await tester.pump(const Duration(seconds: 1)); @@ -347,7 +348,7 @@ void main() { expect(find.text('5'), findsOneWidget); }); - testWidgets('Drag horizontally with scroll anchor at end (LTR)', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Drag horizontally with scroll anchor at end (LTR)', (WidgetTester tester) async { await tester.pumpWidget(buildFrame(reverse: true, textDirection: TextDirection.rtl)); await tester.pump(const Duration(seconds: 1)); diff --git a/packages/flutter/test/widgets/list_view_misc_test.dart b/packages/flutter/test/widgets/list_view_misc_test.dart index 42c216c8966f..c58b7a231694 100644 --- a/packages/flutter/test/widgets/list_view_misc_test.dart +++ b/packages/flutter/test/widgets/list_view_misc_test.dart @@ -4,11 +4,12 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; const Key blockKey = Key('test'); void main() { - testWidgets('Cannot scroll a non-overflowing block', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Cannot scroll a non-overflowing block', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -36,7 +37,7 @@ void main() { await gesture.up(); }); - testWidgets('Can scroll an overflowing block', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Can scroll an overflowing block', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -67,7 +68,7 @@ void main() { await gesture.up(); }); - testWidgets('ListView reverse', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView reverse', (WidgetTester tester) async { int first = 0; int second = 0; @@ -111,8 +112,9 @@ void main() { expect(second, equals(1)); }); - testWidgets('ListView controller', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView controller', (WidgetTester tester) async { final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); Widget buildBlock() { return Directionality( @@ -127,7 +129,7 @@ void main() { expect(controller.offset, equals(0.0)); }); - testWidgets('SliverBlockChildListDelegate.estimateMaxScrollOffset hits end', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SliverBlockChildListDelegate.estimateMaxScrollOffset hits end', (WidgetTester tester) async { final SliverChildListDelegate delegate = SliverChildListDelegate([ Container(), Container(), @@ -161,7 +163,7 @@ void main() { expect(maxScrollOffset, equals(26.0)); }); - testWidgets('Resizing a ListView child restores scroll offset', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Resizing a ListView child restores scroll offset', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/9221 final AnimationController controller = AnimationController( vsync: const TestVSync(), diff --git a/packages/flutter/test/widgets/list_view_relayout_test.dart b/packages/flutter/test/widgets/list_view_relayout_test.dart index 7d0ff9bb14c9..f0d0e53ed03c 100644 --- a/packages/flutter/test/widgets/list_view_relayout_test.dart +++ b/packages/flutter/test/widgets/list_view_relayout_test.dart @@ -5,9 +5,10 @@ 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'; void main() { - testWidgets('Nested ListView with shrinkWrap', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Nested ListView with shrinkWrap', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -36,7 +37,7 @@ void main() { ); }); - testWidgets('Underflowing ListView should relayout for additional children', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Underflowing ListView should relayout for additional children', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/5950 await tester.pumpWidget( @@ -65,7 +66,7 @@ void main() { expect(find.text('200'), findsOneWidget); }); - testWidgets('Underflowing ListView contentExtent should track additional children', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Underflowing ListView contentExtent should track additional children', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -102,7 +103,7 @@ void main() { expect(list.geometry!.scrollExtent, equals(0.0)); }); - testWidgets('Overflowing ListView should relayout for missing children', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Overflowing ListView should relayout for missing children', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -143,7 +144,7 @@ void main() { expect(find.text('400'), findsNothing); }); - testWidgets('Overflowing ListView should not relayout for additional children', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Overflowing ListView should not relayout for additional children', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -177,7 +178,7 @@ void main() { expect(find.text('100'), findsNothing); }); - testWidgets('Overflowing ListView should become scrollable', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Overflowing ListView should become scrollable', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/5920 // When a ListView's viewport hasn't overflowed, scrolling is disabled. // When children are added that cause it to overflow, scrolling should diff --git a/packages/flutter/test/widgets/list_view_semantics_test.dart b/packages/flutter/test/widgets/list_view_semantics_test.dart index c801973a1c07..3fdf022de955 100644 --- a/packages/flutter/test/widgets/list_view_semantics_test.dart +++ b/packages/flutter/test/widgets/list_view_semantics_test.dart @@ -4,6 +4,7 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; import 'semantics_tester.dart'; @@ -14,9 +15,10 @@ void main() { const int itemCount = 10; const double itemHeight = 150.0; - testWidgets('forward vertical', (WidgetTester tester) async { + testWidgetsWithLeakTracking('forward vertical', (WidgetTester tester) async { final SemanticsTester semantics = SemanticsTester(tester); final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); await tester.pumpWidget( Directionality( @@ -44,9 +46,10 @@ void main() { semantics.dispose(); }); - testWidgets('reverse vertical', (WidgetTester tester) async { + testWidgetsWithLeakTracking('reverse vertical', (WidgetTester tester) async { final SemanticsTester semantics = SemanticsTester(tester); final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); await tester.pumpWidget( Directionality( @@ -75,9 +78,10 @@ void main() { semantics.dispose(); }); - testWidgets('forward horizontal', (WidgetTester tester) async { + testWidgetsWithLeakTracking('forward horizontal', (WidgetTester tester) async { final SemanticsTester semantics = SemanticsTester(tester); final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); await tester.pumpWidget( Directionality( @@ -106,9 +110,10 @@ void main() { semantics.dispose(); }); - testWidgets('reverse horizontal', (WidgetTester tester) async { + testWidgetsWithLeakTracking('reverse horizontal', (WidgetTester tester) async { final SemanticsTester semantics = SemanticsTester(tester); final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); await tester.pumpWidget( Directionality( diff --git a/packages/flutter/test/widgets/list_view_test.dart b/packages/flutter/test/widgets/list_view_test.dart index bfb39cfcce42..a9ef0063f05a 100644 --- a/packages/flutter/test/widgets/list_view_test.dart +++ b/packages/flutter/test/widgets/list_view_test.dart @@ -6,6 +6,7 @@ import 'package:collection/collection.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'; import '../rendering/rendering_tester.dart' show TestClipPaintingContext; @@ -77,7 +78,7 @@ class _StatefulListViewState extends State<_StatefulListView> { void main() { // Regression test for https://github.com/flutter/flutter/issues/100451 - testWidgets('ListView.builder respects findChildIndexCallback', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView.builder respects findChildIndexCallback', (WidgetTester tester) async { bool finderCalled = false; int itemCount = 7; late StateSetter stateSetter; @@ -113,7 +114,7 @@ void main() { }); // Regression test for https://github.com/flutter/flutter/issues/100451 - testWidgets('ListView.separator respects findChildIndexCallback', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView.separator respects findChildIndexCallback', (WidgetTester tester) async { bool finderCalled = false; int itemCount = 7; late StateSetter stateSetter; @@ -149,7 +150,7 @@ void main() { expect(finderCalled, true); }); - testWidgets('ListView default control', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView default control', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -160,7 +161,7 @@ void main() { ); }); - testWidgets('ListView itemExtent control test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView itemExtent control test', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -207,7 +208,7 @@ void main() { expect(find.text('5'), findsNothing); }); - testWidgets('ListView large scroll jump', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView large scroll jump', (WidgetTester tester) async { final List log = []; await tester.pumpWidget( @@ -249,7 +250,7 @@ void main() { log.clear(); }); - testWidgets('ListView large scroll jump and keepAlive first child not keepAlive', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView large scroll jump and keepAlive first child not keepAlive', (WidgetTester tester) async { Future checkAndScroll([ String zero = '0:false' ]) async { expect(find.text(zero), findsOneWidget); expect(find.text('1:false'), findsOneWidget); @@ -286,7 +287,7 @@ void main() { await checkAndScroll('0:true'); }); - testWidgets('ListView can build out of underflow', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView can build out of underflow', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -342,7 +343,7 @@ void main() { expect(find.text('5'), findsNothing); }); - testWidgets('ListView can build out of overflow padding', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView can build out of overflow padding', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -361,7 +362,7 @@ void main() { expect(find.text('padded', skipOffstage: false), findsOneWidget); }); - testWidgets('ListView with itemExtent in unbounded context', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView with itemExtent in unbounded context', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -381,7 +382,7 @@ void main() { expect(find.text('19'), findsOneWidget); }); - testWidgets('ListView with shrink wrap in bounded context correctly uses cache extent', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView with shrink wrap in bounded context correctly uses cache extent', (WidgetTester tester) async { final SemanticsHandle handle = tester.ensureSemantics(); await tester.pumpWidget( Directionality( @@ -405,7 +406,7 @@ void main() { handle.dispose(); }); - testWidgets('ListView hidden items should stay hidden if their semantics are updated', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView hidden items should stay hidden if their semantics are updated', (WidgetTester tester) async { final SemanticsHandle handle = tester.ensureSemantics(); await tester.pumpWidget( Directionality( @@ -440,7 +441,7 @@ void main() { handle.dispose(); }); - testWidgets('didFinishLayout has correct indices', (WidgetTester tester) async { + testWidgetsWithLeakTracking('didFinishLayout has correct indices', (WidgetTester tester) async { final TestSliverChildListDelegate delegate = TestSliverChildListDelegate( List.generate( 20, @@ -486,7 +487,7 @@ void main() { delegate.log.clear(); }); - testWidgets('ListView automatically pad MediaQuery on axis', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView automatically pad MediaQuery on axis', (WidgetTester tester) async { EdgeInsets? innerMediaQueryPadding; await tester.pumpWidget( @@ -514,7 +515,7 @@ void main() { expect(innerMediaQueryPadding, const EdgeInsets.symmetric(horizontal: 30.0)); }); - testWidgets('ListView clips if overflow is smaller than cacheExtent', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView clips if overflow is smaller than cacheExtent', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/17426. await tester.pumpWidget( @@ -545,7 +546,7 @@ void main() { expect(find.byType(Viewport), paints..clipRect()); }); - testWidgets('ListView does not clips if no overflow', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView does not clips if no overflow', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -568,7 +569,7 @@ void main() { expect(find.byType(Viewport), isNot(paints..clipRect())); }); - testWidgets('ListView (fixed extent) clips if overflow is smaller than cacheExtent', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView (fixed extent) clips if overflow is smaller than cacheExtent', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/17426. await tester.pumpWidget( @@ -600,7 +601,7 @@ void main() { expect(find.byType(Viewport), paints..clipRect()); }); - testWidgets('ListView (fixed extent) does not clips if no overflow', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView (fixed extent) does not clips if no overflow', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -624,7 +625,7 @@ void main() { expect(find.byType(Viewport), isNot(paints..clipRect())); }); - testWidgets('ListView.horizontal has implicit scrolling by default', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView.horizontal has implicit scrolling by default', (WidgetTester tester) async { final SemanticsHandle handle = tester.ensureSemantics(); await tester.pumpWidget( Directionality( @@ -657,9 +658,10 @@ void main() { handle.dispose(); }); - testWidgets('Updates viewport dimensions when scroll direction changes', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Updates viewport dimensions when scroll direction changes', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/43380. final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); Widget buildListView({ required Axis scrollDirection }) { return Directionality( @@ -694,7 +696,7 @@ void main() { expect(controller.position.viewportDimension, 100.0); }); - testWidgets('ListView respects clipBehavior', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView respects clipBehavior', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -728,9 +730,14 @@ void main() { // 4th, check that a non-default clip behavior can be sent to the painting context. renderObject.paint(context, Offset.zero); expect(context.clipBehavior, equals(Clip.antiAlias)); - }); - - testWidgets('ListView.builder respects clipBehavior', (WidgetTester tester) async { + }, + leakTrackingTestConfig: const LeakTrackingTestConfig( + // TODO(ksokolovskyi): remove after fixing + // https://github.com/flutter/flutter/issues/134572 + notDisposedAllowList: {'ContainerLayer': 1}, + )); + + testWidgetsWithLeakTracking('ListView.builder respects clipBehavior', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -745,7 +752,7 @@ void main() { expect(renderObject.clipBehavior, equals(Clip.antiAlias)); }); - testWidgets('ListView.custom respects clipBehavior', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView.custom respects clipBehavior', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -762,7 +769,7 @@ void main() { expect(renderObject.clipBehavior, equals(Clip.antiAlias)); }); - testWidgets('ListView.separated respects clipBehavior', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView.separated respects clipBehavior', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -779,8 +786,9 @@ void main() { }); // Regression test for https://github.com/flutter/flutter/pull/131393 - testWidgets('itemExtentBuilder test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('itemExtentBuilder test', (WidgetTester tester) async { final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); final List buildLog = []; late SliverLayoutDimensions sliverLayoutDimensions; await tester.pumpWidget( @@ -909,7 +917,7 @@ void main() { expect(buildLog.max, 61); }); - testWidgets('itemExtent, prototypeItem and itemExtentBuilder conflicts test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('itemExtent, prototypeItem and itemExtentBuilder conflicts test', (WidgetTester tester) async { Object? error; try { await tester.pumpWidget( diff --git a/packages/flutter/test/widgets/list_view_vertical_test.dart b/packages/flutter/test/widgets/list_view_vertical_test.dart index 73b0910b0a75..16a103732d0a 100644 --- a/packages/flutter/test/widgets/list_view_vertical_test.dart +++ b/packages/flutter/test/widgets/list_view_vertical_test.dart @@ -4,6 +4,7 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; const List items = [0, 1, 2, 3, 4, 5]; @@ -20,7 +21,7 @@ Widget buildFrame() { } void main() { - testWidgets('Drag vertically', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Drag vertically', (WidgetTester tester) async { await tester.pumpWidget(buildFrame()); await tester.pump(); @@ -63,7 +64,7 @@ void main() { expect(find.text('5'), findsNothing); }); - testWidgets('Drag vertically', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Drag vertically', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, diff --git a/packages/flutter/test/widgets/list_view_viewporting_test.dart b/packages/flutter/test/widgets/list_view_viewporting_test.dart index 0648cf99d57d..51764016a3ba 100644 --- a/packages/flutter/test/widgets/list_view_viewporting_test.dart +++ b/packages/flutter/test/widgets/list_view_viewporting_test.dart @@ -5,11 +5,12 @@ 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'; import 'test_widgets.dart'; void main() { - testWidgets('ListView mount/dismount smoke test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView mount/dismount smoke test', (WidgetTester tester) async { final List callbackTracker = []; // the root view is 800x600 in the test environment @@ -59,7 +60,7 @@ void main() { ])); }); - testWidgets('ListView vertical', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView vertical', (WidgetTester tester) async { final List callbackTracker = []; // the root view is 800x600 in the test environment @@ -77,11 +78,14 @@ void main() { } Widget builder() { + final ScrollController controller = ScrollController(initialScrollOffset: 300.0); + addTearDown(controller.dispose); + return Directionality( textDirection: TextDirection.ltr, child: FlipWidget( left: ListView.builder( - controller: ScrollController(initialScrollOffset: 300.0), + controller: controller, itemBuilder: itemBuilder, ), right: const Text('Not Today'), @@ -122,7 +126,7 @@ void main() { callbackTracker.clear(); }); - testWidgets('ListView horizontal', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView horizontal', (WidgetTester tester) async { final List callbackTracker = []; // the root view is 800x600 in the test environment @@ -140,12 +144,15 @@ void main() { } Widget builder() { + final ScrollController controller = ScrollController(initialScrollOffset: 500.0); + addTearDown(controller.dispose); + return Directionality( textDirection: TextDirection.ltr, child: FlipWidget( left: ListView.builder( scrollDirection: Axis.horizontal, - controller: ScrollController(initialScrollOffset: 500.0), + controller: controller, itemBuilder: itemBuilder, ), right: const Text('Not Today'), @@ -176,7 +183,7 @@ void main() { callbackTracker.clear(); }); - testWidgets('ListView reinvoke builders', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView reinvoke builders', (WidgetTester tester) async { final List callbackTracker = []; final List text = []; @@ -228,7 +235,7 @@ void main() { text.clear(); }); - testWidgets('ListView reinvoke builders', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView reinvoke builders', (WidgetTester tester) async { late StateSetter setState; ThemeData themeData = ThemeData.light(useMaterial3: false); @@ -271,7 +278,7 @@ void main() { expect(widget.color, equals(Colors.green)); }); - testWidgets('ListView padding', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView padding', (WidgetTester tester) async { Widget itemBuilder(BuildContext context, int index) { return Container( key: ValueKey(index), @@ -298,7 +305,7 @@ void main() { expect(firstBox.size.width, equals(800.0 - 12.0)); }); - testWidgets('ListView underflow extents', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView underflow extents', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -433,8 +440,11 @@ void main() { expect(position.minScrollExtent, equals(0.0)); }); - testWidgets('ListView should not paint hidden children', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView should not paint hidden children', (WidgetTester tester) async { const Text text = Text('test'); + final ScrollController controller = ScrollController(initialScrollOffset: 300.0); + addTearDown(controller.dispose); + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -443,7 +453,7 @@ void main() { height: 200.0, child: ListView( cacheExtent: 500.0, - controller: ScrollController(initialScrollOffset: 300.0), + controller: controller, children: const [ SizedBox(height: 140.0, child: text), SizedBox(height: 160.0, child: text), @@ -462,14 +472,17 @@ void main() { expect(list, paintsExactlyCountTimes(#drawParagraph, 2)); }); - testWidgets('ListView should paint with offset', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView should paint with offset', (WidgetTester tester) async { + final ScrollController controller = ScrollController(initialScrollOffset: 120.0); + addTearDown(controller.dispose); + await tester.pumpWidget( MaterialApp( home: Scaffold( body: SizedBox( height: 500.0, child: CustomScrollView( - controller: ScrollController(initialScrollOffset: 120.0), + controller: controller, slivers: [ const SliverAppBar( expandedHeight: 250.0, @@ -493,9 +506,14 @@ void main() { final RenderObject renderObject = tester.renderObject(find.byType(Scrollable)); expect(renderObject, paintsExactlyCountTimes(#drawParagraph, 10)); - }); - - testWidgets('ListView should paint with rtl', (WidgetTester tester) async { + }, + leakTrackingTestConfig: const LeakTrackingTestConfig( + // TODO(ksokolovskyi): remove after fixing + // https://github.com/flutter/flutter/issues/134661 + notDisposedAllowList: {'AnnotatedRegionLayer': 1}, + )); + + testWidgetsWithLeakTracking('ListView should paint with rtl', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.rtl, diff --git a/packages/flutter/test/widgets/list_view_with_inherited_test.dart b/packages/flutter/test/widgets/list_view_with_inherited_test.dart index 1cfdbdaecea8..d47e6f96f9bf 100644 --- a/packages/flutter/test/widgets/list_view_with_inherited_test.dart +++ b/packages/flutter/test/widgets/list_view_with_inherited_test.dart @@ -4,6 +4,7 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; List items = [ 'one', @@ -40,7 +41,7 @@ Widget buildFrame() { } void main() { - testWidgets('ListView is a build function (smoketest)', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ListView is a build function (smoketest)', (WidgetTester tester) async { await tester.pumpWidget(buildFrame()); expect(find.text('one'), findsOneWidget); expect(find.text('two'), findsOneWidget);