diff --git a/packages/flutter/test/widgets/notification_test.dart b/packages/flutter/test/widgets/notification_test.dart index e58d86f2f06e0..ddfa0d23111e8 100644 --- a/packages/flutter/test/widgets/notification_test.dart +++ b/packages/flutter/test/widgets/notification_test.dart @@ -4,15 +4,16 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; class MyNotification extends Notification { } void main() { - testWidgets('Notification basics - toString', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Notification basics - toString', (WidgetTester tester) async { expect(MyNotification(), hasOneLineDescription); }); - testWidgets('Notification basics - dispatch', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Notification basics - dispatch', (WidgetTester tester) async { final List log = []; final GlobalKey key = GlobalKey(); await tester.pumpWidget(NotificationListener( @@ -36,7 +37,7 @@ void main() { expect(log, ['b', notification, 'a', notification]); }); - testWidgets('Notification basics - cancel', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Notification basics - cancel', (WidgetTester tester) async { final List log = []; final GlobalKey key = GlobalKey(); await tester.pumpWidget(NotificationListener( @@ -60,7 +61,7 @@ void main() { expect(log, ['b', notification]); }); - testWidgets('Notification basics - listener null return value', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Notification basics - listener null return value', (WidgetTester tester) async { final List log = []; final GlobalKey key = GlobalKey(); await tester.pumpWidget(NotificationListener( @@ -77,7 +78,7 @@ void main() { expect(log, [MyNotification]); }); - testWidgets('Notification basics - listener null return value', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Notification basics - listener null return value', (WidgetTester tester) async { await tester.pumpWidget(const Placeholder()); final ScrollMetricsNotification n1 = ScrollMetricsNotification( metrics: FixedScrollMetrics( diff --git a/packages/flutter/test/widgets/obscured_animated_image_test.dart b/packages/flutter/test/widgets/obscured_animated_image_test.dart index 788d8f2d4905f..179df2c1a8e0b 100644 --- a/packages/flutter/test/widgets/obscured_animated_image_test.dart +++ b/packages/flutter/test/widgets/obscured_animated_image_test.dart @@ -8,6 +8,7 @@ import 'dart:ui' as ui show Image; 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 '../image_data.dart'; import '../painting/fake_codec.dart'; @@ -17,7 +18,7 @@ Future main() async { final FakeCodec fakeCodec = await FakeCodec.fromData(Uint8List.fromList(kAnimatedGif)); final FakeImageProvider fakeImageProvider = FakeImageProvider(fakeCodec); - testWidgets('Obscured image does not animate', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Obscured image does not animate', (WidgetTester tester) async { final GlobalKey imageKey = GlobalKey(); await tester.pumpWidget( MaterialApp( diff --git a/packages/flutter/test/widgets/opacity_repaint_test.dart b/packages/flutter/test/widgets/opacity_repaint_test.dart index b0aff87cd6753..c858380ef5a11 100644 --- a/packages/flutter/test/widgets/opacity_repaint_test.dart +++ b/packages/flutter/test/widgets/opacity_repaint_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('RenderOpacity avoids repainting and does not drop layer at fully opaque', (WidgetTester tester) async { + testWidgetsWithLeakTracking('RenderOpacity avoids repainting and does not drop layer at fully opaque', (WidgetTester tester) async { RenderTestObject.paintCount = 0; await tester.pumpWidget( const ColoredBox( @@ -46,7 +47,7 @@ void main() { expect(RenderTestObject.paintCount, 1); }); - testWidgets('RenderOpacity allows opacity layer to be dropped at 0 opacity', (WidgetTester tester) async { + testWidgetsWithLeakTracking('RenderOpacity allows opacity layer to be dropped at 0 opacity', (WidgetTester tester) async { RenderTestObject.paintCount = 0; await tester.pumpWidget( diff --git a/packages/flutter/test/widgets/opacity_test.dart b/packages/flutter/test/widgets/opacity_test.dart index 197720dcc22a1..a638dcfe2029a 100644 --- a/packages/flutter/test/widgets/opacity_test.dart +++ b/packages/flutter/test/widgets/opacity_test.dart @@ -7,14 +7,17 @@ @Tags(['reduced-test-set']) library; +import 'dart:ui' as ui; + 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 'semantics_tester.dart'; void main() { - testWidgets('Opacity', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Opacity', (WidgetTester tester) async { final SemanticsTester semantics = SemanticsTester(tester); // Opacity 1.0: Semantics and painting @@ -151,7 +154,7 @@ void main() { semantics.dispose(); }); - testWidgets('offset is correctly handled in Opacity', (WidgetTester tester) async { + testWidgetsWithLeakTracking('offset is correctly handled in Opacity', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( theme: ThemeData(useMaterial3: false), @@ -184,7 +187,7 @@ void main() { ); }); - testWidgets('empty opacity does not crash', (WidgetTester tester) async { + testWidgetsWithLeakTracking('empty opacity does not crash', (WidgetTester tester) async { await tester.pumpWidget( RepaintBoundary(child: Opacity(opacity: 0.5, child: Container())), ); @@ -192,10 +195,11 @@ void main() { // The following line will send the layer to engine and cause crash if an // empty opacity layer is sent. final OffsetLayer offsetLayer = element.renderObject!.debugLayer! as OffsetLayer; - await offsetLayer.toImage(const Rect.fromLTRB(0.0, 0.0, 1.0, 1.0)); + final ui.Image image = await offsetLayer.toImage(const Rect.fromLTRB(0.0, 0.0, 1.0, 1.0)); + image.dispose(); }, skip: isBrowser); // https://github.com/flutter/flutter/issues/49857 - testWidgets('Child shows up in the right spot when opacity is disabled', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Child shows up in the right spot when opacity is disabled', (WidgetTester tester) async { debugDisableOpacityLayers = true; final GlobalKey key = GlobalKey(); await tester.pumpWidget( diff --git a/packages/flutter/test/widgets/overflow_bar_test.dart b/packages/flutter/test/widgets/overflow_bar_test.dart index d8e9520b20cd2..3145df151320a 100644 --- a/packages/flutter/test/widgets/overflow_bar_test.dart +++ b/packages/flutter/test/widgets/overflow_bar_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('OverflowBar documented defaults', (WidgetTester tester) async { + testWidgetsWithLeakTracking('OverflowBar documented defaults', (WidgetTester tester) async { const OverflowBar bar = OverflowBar(); expect(bar.spacing, 0); expect(bar.alignment, null); @@ -17,7 +18,7 @@ void main() { expect(bar.children, const []); }); - testWidgets('Empty OverflowBar', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Empty OverflowBar', (WidgetTester tester) async { const Size size = Size(16, 24); await tester.pumpWidget( @@ -46,7 +47,7 @@ void main() { expect(tester.getSize(find.byType(OverflowBar)), Size.zero); }); - testWidgets('OverflowBar horizontal layout', (WidgetTester tester) async { + testWidgetsWithLeakTracking('OverflowBar horizontal layout', (WidgetTester tester) async { final Key child1Key = UniqueKey(); final Key child2Key = UniqueKey(); final Key child3Key = UniqueKey(); @@ -93,7 +94,7 @@ void main() { expect(tester.getRect(find.byKey(child1Key)), const Rect.fromLTRB(10.0 + 96 + 10.0, 8, 10.0 + 10.0 + 144, 56)); }); - testWidgets('OverflowBar vertical layout', (WidgetTester tester) async { + testWidgetsWithLeakTracking('OverflowBar vertical layout', (WidgetTester tester) async { final Key child1Key = UniqueKey(); final Key child2Key = UniqueKey(); final Key child3Key = UniqueKey(); @@ -174,7 +175,7 @@ void main() { expect(tester.getRect(find.byKey(child3Key)), const Rect.fromLTRB(100.0/2.0 - 32/2, 112, 100.0/2.0 + 32/2, 144)); }); - testWidgets('OverflowBar intrinsic width', (WidgetTester tester) async { + testWidgetsWithLeakTracking('OverflowBar intrinsic width', (WidgetTester tester) async { Widget buildFrame({ required double width }) { return Directionality( textDirection: TextDirection.ltr, @@ -205,7 +206,7 @@ void main() { expect(tester.getSize(find.byType(OverflowBar)).width, 150); }); - testWidgets('OverflowBar intrinsic height', (WidgetTester tester) async { + testWidgetsWithLeakTracking('OverflowBar intrinsic height', (WidgetTester tester) async { Widget buildFrame({ required double maxWidth }) { return Directionality( textDirection: TextDirection.ltr, @@ -237,7 +238,7 @@ void main() { }); - testWidgets('OverflowBar is wider that its intrinsic width', (WidgetTester tester) async { + testWidgetsWithLeakTracking('OverflowBar is wider that its intrinsic width', (WidgetTester tester) async { final Key key0 = UniqueKey(); final Key key1 = UniqueKey(); final Key key2 = UniqueKey(); @@ -273,7 +274,7 @@ void main() { expect(tester.getTopLeft(find.byKey(key2)).dx, 600); }); - testWidgets('OverflowBar with alignment should match Row with mainAxisAlignment', (WidgetTester tester) async { + testWidgetsWithLeakTracking('OverflowBar with alignment should match Row with mainAxisAlignment', (WidgetTester tester) async { final Key key0 = UniqueKey(); final Key key1 = UniqueKey(); final Key key2 = UniqueKey(); diff --git a/packages/flutter/test/widgets/overflow_box_test.dart b/packages/flutter/test/widgets/overflow_box_test.dart index 2cb07611145f4..bc97f50e7f094 100644 --- a/packages/flutter/test/widgets/overflow_box_test.dart +++ b/packages/flutter/test/widgets/overflow_box_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('OverflowBox control test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('OverflowBox control test', (WidgetTester tester) async { final GlobalKey inner = GlobalKey(); await tester.pumpWidget(Align( alignment: Alignment.bottomRight, @@ -30,7 +31,7 @@ void main() { expect(box.size, equals(const Size(100.0, 50.0))); }); - testWidgets('OverflowBox implements debugFillProperties', (WidgetTester tester) async { + testWidgetsWithLeakTracking('OverflowBox implements debugFillProperties', (WidgetTester tester) async { final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder(); const OverflowBox( minWidth: 1.0, @@ -50,7 +51,7 @@ void main() { ]); }); - testWidgets('SizedOverflowBox alignment', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SizedOverflowBox alignment', (WidgetTester tester) async { final GlobalKey inner = GlobalKey(); await tester.pumpWidget(Directionality( textDirection: TextDirection.rtl, @@ -73,7 +74,7 @@ void main() { ); }); - testWidgets('SizedOverflowBox alignment (direction-sensitive)', (WidgetTester tester) async { + testWidgetsWithLeakTracking('SizedOverflowBox alignment (direction-sensitive)', (WidgetTester tester) async { final GlobalKey inner = GlobalKey(); await tester.pumpWidget(Directionality( textDirection: TextDirection.rtl, diff --git a/packages/flutter/test/widgets/overlay_portal_test.dart b/packages/flutter/test/widgets/overlay_portal_test.dart index d361f0c5d6b61..22d624b9c0b76 100644 --- a/packages/flutter/test/widgets/overlay_portal_test.dart +++ b/packages/flutter/test/widgets/overlay_portal_test.dart @@ -5,6 +5,7 @@ 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'; class _ManyRelayoutBoundaries extends StatelessWidget { const _ManyRelayoutBoundaries({ @@ -94,18 +95,20 @@ void main() { _PaintOrder.paintOrder.clear(); }); - testWidgets('The overlay child sees the right inherited widgets', (WidgetTester tester) async { + testWidgetsWithLeakTracking('The overlay child sees the right inherited widgets', (WidgetTester tester) async { int buildCount = 0; TextDirection? directionSeenByOverlayChild; TextDirection textDirection = TextDirection.rtl; late StateSetter setState; + late final OverlayEntry overlayEntry; + addTearDown(() => overlayEntry..remove()..dispose()); await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayEntry( + overlayEntry = OverlayEntry( builder: (BuildContext context) { return StatefulBuilder( builder: (BuildContext context, StateSetter setter) { @@ -141,13 +144,16 @@ void main() { expect(directionSeenByOverlayChild, textDirection); }); - testWidgets('Safe to deactivate and re-activate OverlayPortal', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Safe to deactivate and re-activate OverlayPortal', (WidgetTester tester) async { + late final OverlayEntry overlayEntry; + addTearDown(() => overlayEntry..remove()..dispose()); + final Widget widget = Directionality( key: GlobalKey(debugLabel: 'key'), textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayEntry( + overlayEntry = OverlayEntry( builder: (BuildContext context) { return OverlayPortal( controller: controller1, @@ -164,14 +170,17 @@ void main() { await tester.pumpWidget(SizedBox(child: widget)); }); - testWidgets('Safe to hide overlay child and remove OverlayPortal in the same frame', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Safe to hide overlay child and remove OverlayPortal in the same frame', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/129025. + late final OverlayEntry overlayEntry; + addTearDown(() => overlayEntry..remove()..dispose()); + final Widget widget = Directionality( key: GlobalKey(debugLabel: 'key'), textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayEntry( + overlayEntry = OverlayEntry( builder: (BuildContext context) { return OverlayPortal( controller: controller1, @@ -192,7 +201,7 @@ void main() { expect(tester.takeException(), isNull); }); - testWidgets('Safe to hide overlay child and reparent OverlayPortal in the same frame', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Safe to hide overlay child and reparent OverlayPortal in the same frame', (WidgetTester tester) async { final OverlayPortal overlayPortal = OverlayPortal( key: GlobalKey(debugLabel: 'key'), controller: controller1, @@ -202,12 +211,14 @@ void main() { List children = [ const SizedBox(), overlayPortal ]; + late final OverlayEntry overlayEntry; + addTearDown(() => overlayEntry..remove()..dispose()); late StateSetter setState; final Widget widget = Directionality( textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayStatefulEntry( + overlayEntry = OverlayStatefulEntry( builder: (BuildContext context, StateSetter setter) { setState = setter; return Column(children: children); @@ -228,13 +239,16 @@ void main() { expect(tester.takeException(), isNull); }); - testWidgets('Safe to hide overlay child and reparent OverlayPortal in the same frame 2', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Safe to hide overlay child and reparent OverlayPortal in the same frame 2', (WidgetTester tester) async { + late final OverlayEntry overlayEntry; + addTearDown(() => overlayEntry..remove()..dispose()); + final Widget widget = Directionality( key: GlobalKey(debugLabel: 'key'), textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayEntry( + overlayEntry = OverlayEntry( builder: (BuildContext context) { return OverlayPortal( controller: controller1, @@ -255,14 +269,17 @@ void main() { expect(tester.takeException(), isNull); }); - testWidgets('No relayout boundary between OverlayPortal and Overlay', (WidgetTester tester) async { + testWidgetsWithLeakTracking('No relayout boundary between OverlayPortal and Overlay', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/133545. + late final OverlayEntry overlayEntry; + addTearDown(() => overlayEntry..remove()..dispose()); final GlobalKey key = GlobalKey(debugLabel: 'key'); + final Widget widget = Directionality( textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayEntry( + overlayEntry = OverlayEntry( builder: (BuildContext context) { // The Positioned widget prevents a relayout boundary from being // introduced between the Overlay and OverlayPortal. @@ -326,14 +343,17 @@ void main() { ); }); - testWidgets('show/hide works', (WidgetTester tester) async { + testWidgetsWithLeakTracking('show/hide works', (WidgetTester tester) async { + late final OverlayEntry overlayEntry; + addTearDown(() => overlayEntry..remove()..dispose()); final OverlayPortalController controller = OverlayPortalController(debugLabel: 'local controller'); + const Widget target = SizedBox(); final Widget widget = Directionality( textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayEntry( + overlayEntry = OverlayEntry( builder: (BuildContext context) { return OverlayPortal( controller: controller, @@ -364,13 +384,16 @@ void main() { expect(find.byWidget(target), findsOneWidget); }); - testWidgets('overlayChildBuilder is not evaluated until show is called', (WidgetTester tester) async { + testWidgetsWithLeakTracking('overlayChildBuilder is not evaluated until show is called', (WidgetTester tester) async { + late final OverlayEntry overlayEntry; + addTearDown(() => overlayEntry..remove()..dispose()); final OverlayPortalController controller = OverlayPortalController(debugLabel: 'local controller'); + final Widget widget = Directionality( textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayEntry( + overlayEntry = OverlayEntry( builder: (BuildContext context) { return OverlayPortal( controller: controller, @@ -387,16 +410,18 @@ void main() { expect(tester.takeException(), isNull); }); - testWidgets('overlay child can use Positioned', (WidgetTester tester) async { + testWidgetsWithLeakTracking('overlay child can use Positioned', (WidgetTester tester) async { double dimensions = 30; late StateSetter setState; + late final OverlayEntry overlayEntry; + addTearDown(() => overlayEntry..remove()..dispose()); await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayEntry( + overlayEntry = OverlayEntry( builder: (BuildContext context) { return StatefulBuilder( builder: (BuildContext context, StateSetter setter) { @@ -433,9 +458,11 @@ void main() { expect(tester.getSize(find.byType(Placeholder)), const Size(50, 50)) ; }); - testWidgets('overlay child can be hit tested', (WidgetTester tester) async { + testWidgetsWithLeakTracking('overlay child can be hit tested', (WidgetTester tester) async { double offset = 0; late StateSetter setState; + late final OverlayEntry overlayEntry; + addTearDown(() => overlayEntry..remove()..dispose()); bool isHit = false; await tester.pumpWidget( @@ -443,7 +470,7 @@ void main() { textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayEntry( + overlayEntry = OverlayEntry( builder: (BuildContext context) { return StatefulBuilder( builder: (BuildContext context, StateSetter setter) { @@ -488,13 +515,16 @@ void main() { expect(isHit, true); }); - testWidgets('works in a LayoutBuilder', (WidgetTester tester) async { + testWidgetsWithLeakTracking('works in a LayoutBuilder', (WidgetTester tester) async { + late final OverlayEntry overlayEntry; + addTearDown(() => overlayEntry..remove()..dispose()); + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayEntry( + overlayEntry = OverlayEntry( builder: (BuildContext context) { return LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { @@ -515,7 +545,9 @@ void main() { expect(tester.takeException(), isNull); }); - testWidgets('works in a LayoutBuilder 2', (WidgetTester tester) async { + testWidgetsWithLeakTracking('works in a LayoutBuilder 2', (WidgetTester tester) async { + late final OverlayEntry overlayEntry; + addTearDown(() => overlayEntry..remove()..dispose()); late StateSetter setState; bool shouldShowChild = false; @@ -532,7 +564,7 @@ void main() { textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayStatefulEntry(builder: (BuildContext context, StateSetter setter) { + overlayEntry = OverlayStatefulEntry(builder: (BuildContext context, StateSetter setter) { setState = setter; return OverlayPortal( controller: controller1, @@ -552,7 +584,9 @@ void main() { expect(tester.takeException(), isNull); }); - testWidgets('works in a LayoutBuilder 3', (WidgetTester tester) async { + testWidgetsWithLeakTracking('works in a LayoutBuilder 3', (WidgetTester tester) async { + late final OverlayEntry overlayEntry; + addTearDown(() => overlayEntry..remove()..dispose()); late StateSetter setState; bool shouldShowChild = false; @@ -571,7 +605,7 @@ void main() { textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayStatefulEntry(builder: (BuildContext context, StateSetter setter) { + overlayEntry = OverlayStatefulEntry(builder: (BuildContext context, StateSetter setter) { setState = setter; // The Positioned widget ensures there's no relayout boundary // between the Overlay and the OverlayPortal. @@ -598,7 +632,7 @@ void main() { expect(tester.takeException(), isNull); }); - testWidgets('throws when no Overlay', (WidgetTester tester) async { + testWidgetsWithLeakTracking('throws when no Overlay', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -626,10 +660,12 @@ void main() { ); }); - testWidgets('widget is laid out before overlay child', (WidgetTester tester) async { + testWidgetsWithLeakTracking('widget is laid out before overlay child', (WidgetTester tester) async { final GlobalKey widgetKey = GlobalKey(debugLabel: 'widget'); final RenderBox childBox = RenderConstrainedBox(additionalConstraints: const BoxConstraints()); final RenderBox overlayChildBox = RenderConstrainedBox(additionalConstraints: const BoxConstraints()); + late final OverlayEntry overlayEntry; + addTearDown(() => overlayEntry..remove()..dispose()); int layoutCount = 0; await tester.pumpWidget( @@ -637,7 +673,7 @@ void main() { textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayEntry( + overlayEntry = OverlayEntry( builder: (BuildContext context) { return _ManyRelayoutBoundaries(levels: 50, child: Builder(builder: (BuildContext context) { return OverlayPortal( @@ -679,12 +715,16 @@ void main() { verifyTreeIsClean(); }); - testWidgets('adding/removing overlay child does not redirty overlay more than once', (WidgetTester tester) async { + testWidgetsWithLeakTracking('adding/removing overlay child does not redirty overlay more than once', (WidgetTester tester) async { final GlobalKey widgetKey = GlobalKey(debugLabel: 'widget'); final GlobalKey overlayKey = GlobalKey(debugLabel: 'overlay'); final RenderBox childBox = RenderConstrainedBox(additionalConstraints: const BoxConstraints()); final RenderBox overlayChildBox = RenderConstrainedBox(additionalConstraints: const BoxConstraints()); final _RenderLayoutCounter overlayLayoutCounter = _RenderLayoutCounter(); + late final OverlayEntry overlayEntry1; + addTearDown(() => overlayEntry1..remove()..dispose()); + late final OverlayEntry overlayEntry2; + addTearDown(() => overlayEntry2..remove()..dispose()); int layoutCount = 0; controller1.hide(); @@ -695,8 +735,8 @@ void main() { key: overlayKey, initialEntries: [ // Overlay.performLayout will call layoutCounter.layout. - OverlayEntry(builder: (BuildContext context) => WidgetToRenderBoxAdapter(renderBox: overlayLayoutCounter)), - OverlayEntry( + overlayEntry1 = OverlayEntry(builder: (BuildContext context) => WidgetToRenderBoxAdapter(renderBox: overlayLayoutCounter)), + overlayEntry2 = OverlayEntry( builder: (BuildContext context) { return _ManyRelayoutBoundaries(levels: 50, child: Builder(builder: (BuildContext context) { return OverlayPortal( @@ -737,11 +777,13 @@ void main() { verifyTreeIsClean(); }); - testWidgets('Adding/Removing OverlayPortal in LayoutBuilder during layout', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Adding/Removing OverlayPortal in LayoutBuilder during layout', (WidgetTester tester) async { final GlobalKey widgetKey = GlobalKey(debugLabel: 'widget'); final GlobalKey overlayKey = GlobalKey(debugLabel: 'overlay'); controller1.hide(); late StateSetter setState; + late final OverlayEntry overlayEntry; + addTearDown(() => overlayEntry..remove()..dispose()); Size size = Size.zero; final Widget overlayPortal = OverlayPortal( @@ -757,7 +799,7 @@ void main() { child: Overlay( key: overlayKey, initialEntries: [ - OverlayEntry( + overlayEntry = OverlayEntry( builder: (BuildContext context) { return StatefulBuilder( builder: (BuildContext context, StateSetter stateSetter) { @@ -957,7 +999,7 @@ void main() { }); group('GlobalKey Reparenting', () { - testWidgets('child is laid out before overlay child after OverlayEntry shuffle', (WidgetTester tester) async { + testWidgetsWithLeakTracking('child is laid out before overlay child after OverlayEntry shuffle', (WidgetTester tester) async { int layoutCount = 0; final GlobalKey widgetKey = GlobalKey(debugLabel: 'widget'); @@ -982,8 +1024,11 @@ void main() { }), ); }); + addTearDown(() => overlayEntry1..remove()..dispose()); final OverlayEntry overlayEntry2 = OverlayEntry(builder: (BuildContext context) => const Placeholder()); + addTearDown(() => overlayEntry2..remove()..dispose()); final OverlayEntry overlayEntry3 = OverlayEntry(builder: (BuildContext context) => const Placeholder()); + addTearDown(() => overlayEntry3..remove()..dispose()); await tester.pumpWidget( Directionality( @@ -1094,7 +1139,7 @@ void main() { expect(layoutCount2, 1); }); - testWidgets('Swap child and overlayChild', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Swap child and overlayChild', (WidgetTester tester) async { final RenderBox childBox = RenderConstrainedBox(additionalConstraints: const BoxConstraints()); final RenderBox overlayChildBox = RenderConstrainedBox(additionalConstraints: const BoxConstraints()); @@ -1105,12 +1150,15 @@ void main() { final Widget child1 = WidgetToRenderBoxAdapter(renderBox: overlayChildBox); final Widget child2 = WidgetToRenderBoxAdapter(renderBox: childBox); + late final OverlayEntry overlayEntry; + addTearDown(() => overlayEntry..remove()..dispose()); + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayEntry(builder: (BuildContext context) { + overlayEntry = OverlayEntry(builder: (BuildContext context) { return _ManyRelayoutBoundaries( levels: 50, child: StatefulBuilder(builder: (BuildContext context, StateSetter stateSetter) { @@ -1133,7 +1181,7 @@ void main() { verifyTreeIsClean(); }); - testWidgets('forgetChild', (WidgetTester tester) async { + testWidgetsWithLeakTracking('forgetChild', (WidgetTester tester) async { final RenderBox childBox = RenderConstrainedBox(additionalConstraints: const BoxConstraints()); final RenderBox overlayChildBox = RenderConstrainedBox(additionalConstraints: const BoxConstraints()); @@ -1145,6 +1193,11 @@ void main() { final Widget child1 = WidgetToRenderBoxAdapter(renderBox: overlayChildBox); final Widget child2 = WidgetToRenderBoxAdapter(renderBox: childBox); + late final OverlayEntry overlayEntry1; + addTearDown(() => overlayEntry1..remove()..dispose()); + late final OverlayEntry overlayEntry2; + addTearDown(() => overlayEntry2..remove()..dispose()); + controller1.hide(); await tester.pumpWidget( @@ -1152,7 +1205,7 @@ void main() { textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayEntry(builder: (BuildContext context) { + overlayEntry1 = OverlayEntry(builder: (BuildContext context) { return StatefulBuilder(builder: (BuildContext context, StateSetter stateSetter) { setState2 = stateSetter; return OverlayPortal( @@ -1162,7 +1215,7 @@ void main() { ); }); }), - OverlayEntry(builder: (BuildContext context) { + overlayEntry2 = OverlayEntry(builder: (BuildContext context) { return _ManyRelayoutBoundaries( levels: 50, child: StatefulBuilder(builder: (BuildContext context, StateSetter stateSetter) { @@ -1243,7 +1296,7 @@ void main() { verifyTreeIsClean(); }); - testWidgets('Paint order', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Paint order', (WidgetTester tester) async { final GlobalKey outerKey = GlobalKey(debugLabel: 'Original Outer Widget'); final GlobalKey innerKey = GlobalKey(debugLabel: 'Original Inner Widget'); @@ -1284,12 +1337,15 @@ void main() { ], ); + late final OverlayEntry overlayEntry; + addTearDown(() => overlayEntry..remove()..dispose()); + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayEntry(builder: (BuildContext context) { + overlayEntry = OverlayEntry(builder: (BuildContext context) { return StatefulBuilder(builder: (BuildContext context, StateSetter stateSetter) { setState = stateSetter; return widget; @@ -1365,21 +1421,26 @@ void main() { setState2 = null; }); - testWidgets('between OverlayEntry & overlayChild', (WidgetTester tester) async { + testWidgetsWithLeakTracking('between OverlayEntry & overlayChild', (WidgetTester tester) async { final _RenderLayoutCounter counter1 = _RenderLayoutCounter(); final _RenderLayoutCounter counter2 = _RenderLayoutCounter(); + late final OverlayEntry overlayEntry1; + addTearDown(() => overlayEntry1..remove()..dispose()); + late final OverlayEntry overlayEntry2; + addTearDown(() => overlayEntry2..remove()..dispose()); + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayStatefulEntry(builder: (BuildContext context, StateSetter stateSetter) { + overlayEntry1 = OverlayStatefulEntry(builder: (BuildContext context, StateSetter stateSetter) { setState1 = stateSetter; // WidgetToRenderBoxAdapter is keyed by the render box. return WidgetToRenderBoxAdapter(renderBox: swapped ? counter2 : counter1); }), - OverlayStatefulEntry(builder: (BuildContext context, StateSetter stateSetter) { + overlayEntry2 = OverlayStatefulEntry(builder: (BuildContext context, StateSetter stateSetter) { setState2 = stateSetter; return OverlayPortal( controller: controller1, @@ -1408,20 +1469,25 @@ void main() { expect(counter2.layoutCount, 3); }); - testWidgets('between OverlayEntry & overlayChild, featuring LayoutBuilder', (WidgetTester tester) async { + testWidgetsWithLeakTracking('between OverlayEntry & overlayChild, featuring LayoutBuilder', (WidgetTester tester) async { final _RenderLayoutCounter counter1 = _RenderLayoutCounter(); final _RenderLayoutCounter counter2 = _RenderLayoutCounter(); + late final OverlayEntry overlayEntry1; + addTearDown(() => overlayEntry1..remove()..dispose()); + late final OverlayEntry overlayEntry2; + addTearDown(() => overlayEntry2..remove()..dispose()); + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayStatefulEntry(builder: (BuildContext context, StateSetter stateSetter) { + overlayEntry1 = OverlayStatefulEntry(builder: (BuildContext context, StateSetter stateSetter) { setState1 = stateSetter; return WidgetToRenderBoxAdapter(renderBox: swapped ? counter2 : counter1); }), - OverlayStatefulEntry(builder: (BuildContext context, StateSetter stateSetter) { + overlayEntry2 = OverlayStatefulEntry(builder: (BuildContext context, StateSetter stateSetter) { setState2 = stateSetter; return LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { @@ -1454,16 +1520,21 @@ void main() { expect(counter2.layoutCount, 3); }); - testWidgets('between overlayChild & overlayChild', (WidgetTester tester) async { + testWidgetsWithLeakTracking('between overlayChild & overlayChild', (WidgetTester tester) async { final _RenderLayoutCounter counter1 = _RenderLayoutCounter(); final _RenderLayoutCounter counter2 = _RenderLayoutCounter(); + late final OverlayEntry overlayEntry1; + addTearDown(() => overlayEntry1..remove()..dispose()); + late final OverlayEntry overlayEntry2; + addTearDown(() => overlayEntry2..remove()..dispose()); + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayStatefulEntry(builder: (BuildContext context, StateSetter stateSetter) { + overlayEntry1 = OverlayStatefulEntry(builder: (BuildContext context, StateSetter stateSetter) { setState1 = stateSetter; return OverlayPortal( // WidgetToRenderBoxAdapter is keyed by the render box. @@ -1472,7 +1543,7 @@ void main() { child: const SizedBox(), ); }), - OverlayStatefulEntry(builder: (BuildContext context, StateSetter stateSetter) { + overlayEntry2 = OverlayStatefulEntry(builder: (BuildContext context, StateSetter stateSetter) { setState2 = stateSetter; return OverlayPortal( controller: controller2, @@ -1501,16 +1572,21 @@ void main() { expect(counter2.layoutCount, 3); }); - testWidgets('between overlayChild & overlayChild, featuring LayoutBuilder', (WidgetTester tester) async { + testWidgetsWithLeakTracking('between overlayChild & overlayChild, featuring LayoutBuilder', (WidgetTester tester) async { final _RenderLayoutCounter counter1 = _RenderLayoutCounter(); final _RenderLayoutCounter counter2 = _RenderLayoutCounter(); + late final OverlayEntry overlayEntry1; + addTearDown(() => overlayEntry1..remove()..dispose()); + late final OverlayEntry overlayEntry2; + addTearDown(() => overlayEntry2..remove()..dispose()); + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayStatefulEntry(builder: (BuildContext context, StateSetter stateSetter) { + overlayEntry1 = OverlayStatefulEntry(builder: (BuildContext context, StateSetter stateSetter) { setState1 = stateSetter; return LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { @@ -1522,7 +1598,7 @@ void main() { } ); }), - OverlayStatefulEntry(builder: (BuildContext context, StateSetter stateSetter) { + overlayEntry2 = OverlayStatefulEntry(builder: (BuildContext context, StateSetter stateSetter) { setState2 = stateSetter; return LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { @@ -1555,16 +1631,19 @@ void main() { expect(counter2.layoutCount, 3); }); - testWidgets('between child & overlayChild', (WidgetTester tester) async { + testWidgetsWithLeakTracking('between child & overlayChild', (WidgetTester tester) async { final _RenderLayoutCounter counter1 = _RenderLayoutCounter(); final _RenderLayoutCounter counter2 = _RenderLayoutCounter(); + late final OverlayEntry overlayEntry; + addTearDown(() => overlayEntry..remove()..dispose()); + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayStatefulEntry(builder: (BuildContext context, StateSetter stateSetter) { + overlayEntry = OverlayStatefulEntry(builder: (BuildContext context, StateSetter stateSetter) { setState1 = stateSetter; return OverlayPortal( // WidgetToRenderBoxAdapter is keyed by the render box. @@ -1594,16 +1673,19 @@ void main() { expect(counter2.layoutCount, 3); }); - testWidgets('between child & overlayChild, featuring LayoutBuilder', (WidgetTester tester) async { + testWidgetsWithLeakTracking('between child & overlayChild, featuring LayoutBuilder', (WidgetTester tester) async { final _RenderLayoutCounter counter1 = _RenderLayoutCounter(); final _RenderLayoutCounter counter2 = _RenderLayoutCounter(); + late final OverlayEntry overlayEntry; + addTearDown(() => overlayEntry..remove()..dispose()); + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayStatefulEntry(builder: (BuildContext context, StateSetter stateSetter) { + overlayEntry = OverlayStatefulEntry(builder: (BuildContext context, StateSetter stateSetter) { setState1 = stateSetter; return LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { @@ -1638,19 +1720,25 @@ void main() { }); }); - testWidgets('Safe to move the overlay child to a different Overlay and remove the old Overlay', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Safe to move the overlay child to a different Overlay and remove the old Overlay', (WidgetTester tester) async { controller1.show(); final GlobalKey key = GlobalKey(debugLabel: 'key'); final GlobalKey oldOverlayKey = GlobalKey(debugLabel: 'old overlay'); final GlobalKey newOverlayKey = GlobalKey(debugLabel: 'new overlay'); final GlobalKey overlayChildKey = GlobalKey(debugLabel: 'overlay child key'); + + late final OverlayEntry overlayEntry1; + addTearDown(() => overlayEntry1..remove()..dispose()); + late final OverlayEntry overlayEntry2; + addTearDown(() => overlayEntry2..remove()..dispose()); + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: Overlay( key: oldOverlayKey, initialEntries: [ - OverlayEntry( + overlayEntry1 = OverlayEntry( builder: (BuildContext context) { return OverlayPortal( key: key, @@ -1675,7 +1763,7 @@ void main() { child: Overlay( key: newOverlayKey, initialEntries: [ - OverlayEntry( + overlayEntry2 = OverlayEntry( builder: (BuildContext context) { return OverlayPortal( key: key, @@ -1698,18 +1786,21 @@ void main() { }); group('Paint order', () { - testWidgets('show bringsToTop', (WidgetTester tester) async { + testWidgetsWithLeakTracking('show bringsToTop', (WidgetTester tester) async { controller1.hide(); const _PaintOrder child1 = _PaintOrder(); const _PaintOrder child2 = _PaintOrder(); + late final OverlayEntry overlayEntry; + addTearDown(() => overlayEntry..remove()..dispose()); + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayEntry(builder: (BuildContext context) { + overlayEntry = OverlayEntry(builder: (BuildContext context) { return Column( children: [ OverlayPortal(controller: controller1, overlayChildBuilder: (BuildContext context) => child1), @@ -1762,7 +1853,7 @@ void main() { ); }); - testWidgets('Paint order does not change after global key reparenting', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Paint order does not change after global key reparenting', (WidgetTester tester) async { final GlobalKey key = GlobalKey(); late StateSetter setState; @@ -1787,12 +1878,15 @@ void main() { child: const SizedBox(), ); + late final OverlayEntry overlayEntry; + addTearDown(() => overlayEntry..remove()..dispose()); + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: Overlay( initialEntries: [ - OverlayEntry(builder: (BuildContext context) { + overlayEntry = OverlayEntry(builder: (BuildContext context) { return Column( children: [ StatefulBuilder(builder: (BuildContext context, StateSetter stateSetter) { diff --git a/packages/flutter/test/widgets/overscroll_indicator_test.dart b/packages/flutter/test/widgets/overscroll_indicator_test.dart index 340871db3230b..4caaa3a9714cc 100644 --- a/packages/flutter/test/widgets/overscroll_indicator_test.dart +++ b/packages/flutter/test/widgets/overscroll_indicator_test.dart @@ -6,6 +6,7 @@ import 'dart:math' as math; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; final Matcher doesNotOverscroll = isNot(paints..circle()); @@ -19,7 +20,7 @@ Future slowDrag(WidgetTester tester, Offset start, Offset offset) async { } void main() { - testWidgets('Overscroll indicator color', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Overscroll indicator color', (WidgetTester tester) async { await tester.pumpWidget( const Directionality( textDirection: TextDirection.ltr, @@ -55,7 +56,7 @@ void main() { expect(painter, doesNotOverscroll); }); - testWidgets('Nested scrollable', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Nested scrollable', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -86,7 +87,7 @@ void main() { expect(innerPainter, paints..circle()); }); - testWidgets('Overscroll indicator changes side when you drag on the other side', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Overscroll indicator changes side when you drag on the other side', (WidgetTester tester) async { await tester.pumpWidget( const Directionality( textDirection: TextDirection.ltr, @@ -128,7 +129,7 @@ void main() { expect(painter, doesNotOverscroll); }); - testWidgets('Overscroll indicator changes side when you shift sides', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Overscroll indicator changes side when you shift sides', (WidgetTester tester) async { await tester.pumpWidget( const Directionality( textDirection: TextDirection.ltr, @@ -166,7 +167,7 @@ void main() { }); group("Flipping direction of scrollable doesn't change overscroll behavior", () { - testWidgets('down', (WidgetTester tester) async { + testWidgetsWithLeakTracking('down', (WidgetTester tester) async { await tester.pumpWidget( const Directionality( textDirection: TextDirection.ltr, @@ -186,7 +187,7 @@ void main() { expect(painter, doesNotOverscroll); }); - testWidgets('up', (WidgetTester tester) async { + testWidgetsWithLeakTracking('up', (WidgetTester tester) async { await tester.pumpWidget( const Directionality( textDirection: TextDirection.ltr, @@ -208,7 +209,7 @@ void main() { }); }); - testWidgets('Overscroll in both directions', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Overscroll in both directions', (WidgetTester tester) async { await tester.pumpWidget( const Directionality( textDirection: TextDirection.ltr, @@ -231,7 +232,7 @@ void main() { expect(painter, doesNotOverscroll); }); - testWidgets('Overscroll ignored from alternate axis', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Overscroll ignored from alternate axis', (WidgetTester tester) async { await tester.pumpWidget( const Directionality( textDirection: TextDirection.ltr, @@ -260,7 +261,7 @@ void main() { expect(painter, doesNotOverscroll); }); - testWidgets('Overscroll horizontally', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Overscroll horizontally', (WidgetTester tester) async { await tester.pumpWidget( const Directionality( textDirection: TextDirection.ltr, @@ -291,7 +292,7 @@ void main() { expect(painter, doesNotOverscroll); }); - testWidgets('Nested overscrolls do not throw exceptions', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Nested overscrolls do not throw exceptions', (WidgetTester tester) async { await tester.pumpWidget(Directionality( textDirection: TextDirection.ltr, child: PageView( @@ -313,7 +314,7 @@ void main() { await tester.pumpAndSettle(); }); - testWidgets('Changing settings', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Changing settings', (WidgetTester tester) async { RenderObject painter; await tester.pumpWidget( @@ -359,7 +360,7 @@ void main() { expect(painter, isNot(paints..circle()..circle())); }); - testWidgets('CustomScrollView overscroll indicator works if there is sliver before center', (WidgetTester tester) async { + testWidgetsWithLeakTracking('CustomScrollView overscroll indicator works if there is sliver before center', (WidgetTester tester) async { final Key centerKey = UniqueKey(); await tester.pumpWidget( Directionality( @@ -398,7 +399,7 @@ void main() { expect(painter, paints..save()..translate(y: 0.0)..scale()..circle()); }); - testWidgets('CustomScrollView overscroll indicator works well with [CustomScrollView.center] and [OverscrollIndicatorNotification.paintOffset]', (WidgetTester tester) async { + testWidgetsWithLeakTracking('CustomScrollView overscroll indicator works well with [CustomScrollView.center] and [OverscrollIndicatorNotification.paintOffset]', (WidgetTester tester) async { final Key centerKey = UniqueKey(); await tester.pumpWidget( Directionality( @@ -445,7 +446,7 @@ void main() { expect(painter, paints..save()..translate(y: 50.0)..scale()..circle()); }); - testWidgets('The OverscrollIndicator should not overflow the scrollable view edge', (WidgetTester tester) async { + testWidgetsWithLeakTracking('The OverscrollIndicator should not overflow the scrollable view edge', (WidgetTester tester) async { // Regressing test for https://github.com/flutter/flutter/issues/64149 await tester.pumpWidget( Directionality( @@ -508,7 +509,7 @@ void main() { }); group('[OverscrollIndicatorNotification.paintOffset] test', () { - testWidgets('Leading', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Leading', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -538,7 +539,7 @@ void main() { expect(painter, paints..save()..translate(y: 50.0 - 30.0)..scale()..circle()); }); - testWidgets('Trailing', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Trailing', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, diff --git a/packages/flutter/test/widgets/overscroll_stretch_indicator_test.dart b/packages/flutter/test/widgets/overscroll_stretch_indicator_test.dart index d8aa4e12a4e96..3f48544f7e40a 100644 --- a/packages/flutter/test/widgets/overscroll_stretch_indicator_test.dart +++ b/packages/flutter/test/widgets/overscroll_stretch_indicator_test.dart @@ -10,6 +10,7 @@ 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() { Widget buildTest( @@ -76,10 +77,12 @@ void main() { ); } - testWidgets('Stretch overscroll will do nothing when axes do not match', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Stretch overscroll will do nothing when axes do not match', (WidgetTester tester) async { final GlobalKey box1Key = GlobalKey(); final GlobalKey box2Key = GlobalKey(); final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -135,11 +138,13 @@ void main() { expect(box2.localToGlobal(Offset.zero), const Offset(0.0, 250.0)); }); - testWidgets('Stretch overscroll vertically', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Stretch overscroll vertically', (WidgetTester tester) async { final GlobalKey box1Key = GlobalKey(); final GlobalKey box2Key = GlobalKey(); final GlobalKey box3Key = GlobalKey(); final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); + await tester.pumpWidget( buildTest(box1Key, box2Key, box3Key, controller), ); @@ -212,11 +217,13 @@ void main() { expect(box3.localToGlobal(Offset.zero).dy, 350.0); }); - testWidgets('Stretch overscroll works in reverse - vertical', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Stretch overscroll works in reverse - vertical', (WidgetTester tester) async { final GlobalKey box1Key = GlobalKey(); final GlobalKey box2Key = GlobalKey(); final GlobalKey box3Key = GlobalKey(); final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); + await tester.pumpWidget( buildTest(box1Key, box2Key, box3Key, controller, reverse: true), ); @@ -245,11 +252,13 @@ void main() { ); }); - testWidgets('Stretch overscroll works in reverse - horizontal', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Stretch overscroll works in reverse - horizontal', (WidgetTester tester) async { final GlobalKey box1Key = GlobalKey(); final GlobalKey box2Key = GlobalKey(); final GlobalKey box3Key = GlobalKey(); final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); + await tester.pumpWidget( buildTest( box1Key, @@ -285,11 +294,13 @@ void main() { ); }); - testWidgets('Stretch overscroll works in reverse - horizontal - RTL', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Stretch overscroll works in reverse - horizontal - RTL', (WidgetTester tester) async { final GlobalKey box1Key = GlobalKey(); final GlobalKey box2Key = GlobalKey(); final GlobalKey box3Key = GlobalKey(); final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); + await tester.pumpWidget( buildTest( box1Key, @@ -371,11 +382,13 @@ void main() { expect(box3.localToGlobal(Offset.zero).dx, 500.0); }); - testWidgets('Stretch overscroll horizontally', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Stretch overscroll horizontally', (WidgetTester tester) async { final GlobalKey box1Key = GlobalKey(); final GlobalKey box2Key = GlobalKey(); final GlobalKey box3Key = GlobalKey(); final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); + await tester.pumpWidget( buildTest(box1Key, box2Key, box3Key, controller, axis: Axis.horizontal) ); @@ -448,11 +461,13 @@ void main() { expect(box3.localToGlobal(Offset.zero).dx, 500.0); }); - testWidgets('Stretch overscroll horizontally RTL', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Stretch overscroll horizontally RTL', (WidgetTester tester) async { final GlobalKey box1Key = GlobalKey(); final GlobalKey box2Key = GlobalKey(); final GlobalKey box3Key = GlobalKey(); final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); + await tester.pumpWidget( buildTest( box1Key, @@ -488,12 +503,14 @@ void main() { ); }); - testWidgets('Disallow stretching overscroll', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Disallow stretching overscroll', (WidgetTester tester) async { final GlobalKey box1Key = GlobalKey(); final GlobalKey box2Key = GlobalKey(); final GlobalKey box3Key = GlobalKey(); final ScrollController controller = ScrollController(); - double indicatorNotification =0; + addTearDown(controller.dispose); + + double indicatorNotification = 0; await tester.pumpWidget( NotificationListener( onNotification: (OverscrollIndicatorNotification notification) { @@ -530,7 +547,7 @@ void main() { await tester.pumpAndSettle(); }); - testWidgets('Stretch does not overflow bounds of container', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Stretch does not overflow bounds of container', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/90197 await tester.pumpWidget(Directionality( textDirection: TextDirection.ltr, @@ -587,7 +604,7 @@ void main() { await tester.pumpAndSettle(); }); - testWidgets('Clip behavior is updated as needed', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Clip behavior is updated as needed', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/97867 await tester.pumpWidget( Directionality( @@ -647,7 +664,7 @@ void main() { await tester.pumpAndSettle(); }); - testWidgets('clipBehavior parameter updates overscroll clipping behavior', (WidgetTester tester) async { + testWidgetsWithLeakTracking('clipBehavior parameter updates overscroll clipping behavior', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/103491 Widget buildFrame(Clip clipBehavior) { @@ -711,7 +728,7 @@ void main() { await tester.pumpAndSettle(); }); - testWidgets('Stretch limit', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Stretch limit', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/99264 await tester.pumpWidget( Directionality( @@ -762,7 +779,7 @@ void main() { await tester.pumpAndSettle(); }); - testWidgets('Multiple pointers will not exceed stretch limit', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Multiple pointers will not exceed stretch limit', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/99264 await tester.pumpWidget( Directionality( @@ -832,11 +849,13 @@ void main() { await tester.pumpAndSettle(); }); - testWidgets('Stretch overscroll vertically, change direction mid scroll', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Stretch overscroll vertically, change direction mid scroll', (WidgetTester tester) async { final GlobalKey box1Key = GlobalKey(); final GlobalKey box2Key = GlobalKey(); final GlobalKey box3Key = GlobalKey(); final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); + await tester.pumpWidget( buildTest( box1Key, @@ -901,11 +920,13 @@ void main() { expect(box3.localToGlobal(Offset.zero), const Offset(0.0, 200.0)); }); - testWidgets('Stretch overscroll horizontally, change direction mid scroll', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Stretch overscroll horizontally, change direction mid scroll', (WidgetTester tester) async { final GlobalKey box1Key = GlobalKey(); final GlobalKey box2Key = GlobalKey(); final GlobalKey box3Key = GlobalKey(); final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); + await tester.pumpWidget( buildTest( box1Key, @@ -971,11 +992,13 @@ void main() { expect(box3.localToGlobal(Offset.zero), const Offset(200.0, 0.0)); }); - testWidgets('Fling toward the trailing edge causes stretch toward the leading edge', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Fling toward the trailing edge causes stretch toward the leading edge', (WidgetTester tester) async { final GlobalKey box1Key = GlobalKey(); final GlobalKey box2Key = GlobalKey(); final GlobalKey box3Key = GlobalKey(); final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); + await tester.pumpWidget( buildTest(box1Key, box2Key, box3Key, controller), ); @@ -1011,11 +1034,13 @@ void main() { expect(box3.localToGlobal(Offset.zero).dy, 350.0); }); - testWidgets('Fling toward the leading edge causes stretch toward the trailing edge', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Fling toward the leading edge causes stretch toward the trailing edge', (WidgetTester tester) async { final GlobalKey box1Key = GlobalKey(); final GlobalKey box2Key = GlobalKey(); final GlobalKey box3Key = GlobalKey(); final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); + await tester.pumpWidget( buildTest(box1Key, box2Key, box3Key, controller), ); @@ -1063,11 +1088,13 @@ void main() { expect(box3.localToGlobal(Offset.zero).dy, 500.0); }); - testWidgets('changing scroll direction during recede animation will not change the stretch direction', (WidgetTester tester) async { + testWidgetsWithLeakTracking('changing scroll direction during recede animation will not change the stretch direction', (WidgetTester tester) async { final GlobalKey box1Key = GlobalKey(); final GlobalKey box2Key = GlobalKey(); final GlobalKey box3Key = GlobalKey(); final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); + await tester.pumpWidget( buildTest(box1Key, box2Key, box3Key, controller, boxHeight: 205.0), ); @@ -1125,11 +1152,13 @@ void main() { await gesture.up(); }); - testWidgets('Stretch overscroll only uses image filter during stretch effect', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Stretch overscroll only uses image filter during stretch effect', (WidgetTester tester) async { final GlobalKey box1Key = GlobalKey(); final GlobalKey box2Key = GlobalKey(); final GlobalKey box3Key = GlobalKey(); final ScrollController controller = ScrollController(); + addTearDown(controller.dispose); + await tester.pumpWidget( buildTest( box1Key, diff --git a/packages/flutter/test/widgets/page_forward_transitions_test.dart b/packages/flutter/test/widgets/page_forward_transitions_test.dart index 9ffc019cc670b..da523ac96f40a 100644 --- a/packages/flutter/test/widgets/page_forward_transitions_test.dart +++ b/packages/flutter/test/widgets/page_forward_transitions_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 TestTransition extends AnimatedWidget { const TestTransition({ @@ -57,7 +58,7 @@ void main() { const Duration kTwoTenthsOfTheTransitionDuration = Duration(milliseconds: 30); const Duration kFourTenthsOfTheTransitionDuration = Duration(milliseconds: 60); - testWidgets('Check onstage/offstage handling around transitions', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Check onstage/offstage handling around transitions', (WidgetTester tester) async { final GlobalKey insideKey = GlobalKey(); @@ -196,7 +197,7 @@ void main() { }); - testWidgets('Check onstage/offstage handling of barriers around transitions', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Check onstage/offstage handling of barriers around transitions', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( onGenerateRoute: (RouteSettings settings) { diff --git a/packages/flutter/test/widgets/page_route_builder_test.dart b/packages/flutter/test/widgets/page_route_builder_test.dart index 3e6090fa80195..7e90c9a4e273e 100644 --- a/packages/flutter/test/widgets/page_route_builder_test.dart +++ b/packages/flutter/test/widgets/page_route_builder_test.dart @@ -9,6 +9,7 @@ library; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; class TestPage extends StatelessWidget { const TestPage({ super.key, this.useMaterial3 }); @@ -93,7 +94,7 @@ class ModalPage extends StatelessWidget { } void main() { - testWidgets('Material2 - Barriers show when using PageRouteBuilder', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material2 - Barriers show when using PageRouteBuilder', (WidgetTester tester) async { await tester.pumpWidget(const TestPage(useMaterial3: false)); await tester.tap(find.byType(FloatingActionButton)); await tester.pumpAndSettle(); @@ -103,7 +104,7 @@ void main() { ); }); - testWidgets('Material3 - Barriers show when using PageRouteBuilder', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Material3 - Barriers show when using PageRouteBuilder', (WidgetTester tester) async { await tester.pumpWidget(const TestPage(useMaterial3: true)); await tester.tap(find.byType(FloatingActionButton)); await tester.pumpAndSettle(); diff --git a/packages/flutter/test/widgets/page_storage_test.dart b/packages/flutter/test/widgets/page_storage_test.dart index db74aa58b32d2..ec8d39002de18 100644 --- a/packages/flutter/test/widgets/page_storage_test.dart +++ b/packages/flutter/test/widgets/page_storage_test.dart @@ -4,9 +4,10 @@ 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('PageStorage read and write', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageStorage read and write', (WidgetTester tester) async { const Key builderKey = PageStorageKey('builderKey'); late StateSetter setState; int storedValue = 0; @@ -37,7 +38,7 @@ void main() { expect(PageStorage.of(builderElement).readState(builderElement), equals(storedValue)); }); - testWidgets('PageStorage read and write by identifier', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageStorage read and write by identifier', (WidgetTester tester) async { late StateSetter setState; int storedValue = 0; diff --git a/packages/flutter/test/widgets/page_transitions_test.dart b/packages/flutter/test/widgets/page_transitions_test.dart index 55729ea2395a7..6b1a973ea408b 100644 --- a/packages/flutter/test/widgets/page_transitions_test.dart +++ b/packages/flutter/test/widgets/page_transitions_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 TestOverlayRoute extends OverlayRoute { TestOverlayRoute({ super.settings }); @@ -47,7 +48,7 @@ class PersistentBottomSheetTestState extends State { } void main() { - testWidgets('Check onstage/offstage handling around transitions', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Check onstage/offstage handling around transitions', (WidgetTester tester) async { final GlobalKey containerKey1 = GlobalKey(); final GlobalKey containerKey2 = GlobalKey(); final Map routes = { @@ -129,7 +130,7 @@ void main() { expect(Navigator.canPop(containerKey1.currentContext!), isFalse); }); - testWidgets('Check back gesture disables Heroes', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Check back gesture disables Heroes', (WidgetTester tester) async { final GlobalKey containerKey1 = GlobalKey(); final GlobalKey containerKey2 = GlobalKey(); const String kHeroTag = 'hero'; @@ -198,7 +199,7 @@ void main() { expect(settingsOffset.dy, 100.0); }, variant: const TargetPlatformVariant({ TargetPlatform.iOS, TargetPlatform.macOS })); - testWidgets("Check back gesture doesn't start during transitions", (WidgetTester tester) async { + testWidgetsWithLeakTracking("Check back gesture doesn't start during transitions", (WidgetTester tester) async { final GlobalKey containerKey1 = GlobalKey(); final GlobalKey containerKey2 = GlobalKey(); final Map routes = { @@ -242,7 +243,7 @@ void main() { }, variant: const TargetPlatformVariant({ TargetPlatform.iOS, TargetPlatform.macOS })); // Tests bug https://github.com/flutter/flutter/issues/6451 - testWidgets('Check back gesture with a persistent bottom sheet showing', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Check back gesture with a persistent bottom sheet showing', (WidgetTester tester) async { final GlobalKey containerKey1 = GlobalKey(); final GlobalKey containerKey2 = GlobalKey(); final Map routes = { @@ -295,7 +296,7 @@ void main() { expect(sheet.setStateCalled, isFalse); }, variant: const TargetPlatformVariant({ TargetPlatform.iOS, TargetPlatform.macOS })); - testWidgets('Test completed future', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Test completed future', (WidgetTester tester) async { final Map routes = { '/': (_) => const Center(child: Text('home')), '/next': (_) => const Center(child: Text('next')), diff --git a/packages/flutter/test/widgets/page_view_test.dart b/packages/flutter/test/widgets/page_view_test.dart index 9b94146ee55d8..41405b00e229e 100644 --- a/packages/flutter/test/widgets/page_view_test.dart +++ b/packages/flutter/test/widgets/page_view_test.dart @@ -7,6 +7,7 @@ import 'package:flutter/gestures.dart' show DragStartBehavior; 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; import 'semantics_tester.dart'; @@ -14,7 +15,7 @@ import 'states.dart'; void main() { // Regression test for https://github.com/flutter/flutter/issues/100451 - testWidgets('PageView.builder respects findChildIndexCallback', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageView.builder respects findChildIndexCallback', (WidgetTester tester) async { bool finderCalled = false; int itemCount = 7; late StateSetter stateSetter; @@ -49,11 +50,10 @@ void main() { expect(finderCalled, true); }); - testWidgets('PageView resize from zero-size viewport should not lose state', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageView resize from zero-size viewport should not lose state', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/88956 - final PageController controller = PageController( - initialPage: 1, - ); + final PageController controller = PageController(initialPage: 1); + addTearDown(controller.dispose); Widget build(Size size) { return Directionality( @@ -94,11 +94,10 @@ void main() { expect(find.text('Iowa'), findsOneWidget); }); - testWidgets('Change the page through the controller when zero-size viewport', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Change the page through the controller when zero-size viewport', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/88956 - final PageController controller = PageController( - initialPage: 1, - ); + final PageController controller = PageController(initialPage: 1); + addTearDown(controller.dispose); Widget build(Size size) { return Directionality( @@ -134,11 +133,10 @@ void main() { expect(find.text('Illinois'), findsOneWidget); }); - testWidgets('_PagePosition.applyViewportDimension should not throw', (WidgetTester tester) async { + testWidgetsWithLeakTracking('_PagePosition.applyViewportDimension should not throw', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/101007 - final PageController controller = PageController( - initialPage: 1, - ); + final PageController controller = PageController(initialPage: 1); + addTearDown(controller.dispose); // Set the starting viewportDimension to 0.0 await tester.binding.setSurfaceSize(Size.zero); @@ -173,13 +171,14 @@ void main() { await tester.binding.setSurfaceSize(null); }); - testWidgets('PageController cannot return page while unattached', + testWidgetsWithLeakTracking('PageController cannot return page while unattached', (WidgetTester tester) async { final PageController controller = PageController(); + addTearDown(controller.dispose); expect(() => controller.page, throwsAssertionError); }); - testWidgets('PageView control test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageView control test', (WidgetTester tester) async { final List log = []; await tester.pumpWidget(Directionality( @@ -246,7 +245,7 @@ void main() { expect(find.text('Arizona'), findsNothing); }); - testWidgets('PageView does not squish when overscrolled', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageView does not squish when overscrolled', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( home: PageView( children: List.generate(10, (int i) { @@ -284,8 +283,9 @@ void main() { expect(sizeOf(0), equals(const Size(800.0, 600.0))); }, variant: const TargetPlatformVariant({ TargetPlatform.iOS, TargetPlatform.macOS })); - testWidgets('PageController control test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageController control test', (WidgetTester tester) async { final PageController controller = PageController(initialPage: 4); + addTearDown(controller.dispose); await tester.pumpWidget(Directionality( textDirection: TextDirection.ltr, @@ -330,7 +330,7 @@ void main() { expect(find.text('California'), findsOneWidget); }); - testWidgets('PageController page stability', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageController page stability', (WidgetTester tester) async { await tester.pumpWidget(Directionality( textDirection: TextDirection.ltr, child: Center( @@ -382,8 +382,10 @@ void main() { expect(find.text('Arizona'), findsOneWidget); }); - testWidgets('PageController nextPage and previousPage return Futures that resolve', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageController nextPage and previousPage return Futures that resolve', (WidgetTester tester) async { final PageController controller = PageController(); + addTearDown(controller.dispose); + await tester.pumpWidget(Directionality( textDirection: TextDirection.ltr, child: PageView( @@ -414,7 +416,7 @@ void main() { expect(previousPageCompleted, true); }); - testWidgets('PageView in zero-size container', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageView in zero-size container', (WidgetTester tester) async { await tester.pumpWidget(Directionality( textDirection: TextDirection.ltr, child: Center( @@ -444,7 +446,7 @@ void main() { expect(find.text('Alabama'), findsOneWidget); }); - testWidgets('Page changes at halfway point', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Page changes at halfway point', (WidgetTester tester) async { final List log = []; await tester.pumpWidget(Directionality( textDirection: TextDirection.ltr, @@ -494,9 +496,10 @@ void main() { expect(find.text('Alaska'), findsOneWidget); }); - testWidgets('Bouncing scroll physics ballistics does not overshoot', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Bouncing scroll physics ballistics does not overshoot', (WidgetTester tester) async { final List log = []; final PageController controller = PageController(viewportFraction: 0.9); + addTearDown(controller.dispose); Widget build(PageController controller, { Size? size }) { final Widget pageView = Directionality( @@ -548,8 +551,9 @@ void main() { expect(find.text('Arizona'), findsNothing); }); - testWidgets('PageView viewportFraction', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageView viewportFraction', (WidgetTester tester) async { PageController controller = PageController(viewportFraction: 7/8); + addTearDown(controller.dispose); Widget build(PageController controller) { return Directionality( @@ -583,6 +587,7 @@ void main() { expect(tester.getTopLeft(find.text('Idaho')), const Offset(750.0, 0.0)); controller = PageController(viewportFraction: 39/40); + addTearDown(controller.dispose); await tester.pumpWidget(build(controller)); @@ -591,7 +596,7 @@ void main() { expect(tester.getTopLeft(find.text('Idaho')), const Offset(790.0, 0.0)); }); - testWidgets('Page snapping disable and reenable', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Page snapping disable and reenable', (WidgetTester tester) async { final List log = []; Widget build({ required bool pageSnapping }) { @@ -654,8 +659,9 @@ void main() { expect(find.text('Arkansas'), findsNothing); }); - testWidgets('PageView small viewportFraction', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageView small viewportFraction', (WidgetTester tester) async { final PageController controller = PageController(viewportFraction: 1/8); + addTearDown(controller.dispose); Widget build(PageController controller) { return Directionality( @@ -698,8 +704,9 @@ void main() { expect(tester.getTopLeft(find.text('Iowa')), const Offset(750.0, 0.0)); }); - testWidgets('PageView large viewportFraction', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageView large viewportFraction', (WidgetTester tester) async { final PageController controller = PageController(viewportFraction: 5/4); + addTearDown(controller.dispose); Widget build(PageController controller) { return Directionality( @@ -731,7 +738,7 @@ void main() { expect(tester.getTopLeft(find.text('Hawaii')), const Offset(-100.0, 0.0)); }); - testWidgets( + testWidgetsWithLeakTracking( 'Updating PageView large viewportFraction', (WidgetTester tester) async { Widget build(PageController controller) { @@ -754,12 +761,14 @@ void main() { } final PageController oldController = PageController(viewportFraction: 5/4); + addTearDown(oldController.dispose); await tester.pumpWidget(build(oldController)); expect(tester.getTopLeft(find.text('Alabama')), const Offset(-100, 0)); expect(tester.getBottomRight(find.text('Alabama')), const Offset(900.0, 600.0)); final PageController newController = PageController(viewportFraction: 4); + addTearDown(newController.dispose); await tester.pumpWidget(build(newController)); newController.jumpToPage(10); await tester.pump(); @@ -768,11 +777,12 @@ void main() { }, ); - testWidgets( + testWidgetsWithLeakTracking( 'PageView large viewportFraction can scroll to the last page and snap', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/45096. final PageController controller = PageController(viewportFraction: 5/4); + addTearDown(controller.dispose); Widget build(PageController controller) { return Directionality( @@ -805,11 +815,12 @@ void main() { }, ); - testWidgets( + testWidgetsWithLeakTracking( 'All visible pages are able to receive touch events', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/23873. final PageController controller = PageController(viewportFraction: 1/4); + addTearDown(controller.dispose); late int tappedIndex; Widget build() { @@ -853,12 +864,13 @@ void main() { }, ); - testWidgets('the current item remains centered on constraint change', (WidgetTester tester) async { + testWidgetsWithLeakTracking('the current item remains centered on constraint change', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/50505. final PageController controller = PageController( initialPage: kStates.length - 1, viewportFraction: 0.5, ); + addTearDown(controller.dispose); Widget build(Size size) { return Directionality( @@ -895,10 +907,11 @@ void main() { verifyCentered(); }); - testWidgets('PageView does not report page changed on overscroll', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageView does not report page changed on overscroll', (WidgetTester tester) async { final PageController controller = PageController( initialPage: kStates.length - 1, ); + addTearDown(controller.dispose); int changeIndex = 0; Widget build() { return Directionality( @@ -921,8 +934,9 @@ void main() { expect(changeIndex, 0); }); - testWidgets('PageView can restore page', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageView can restore page', (WidgetTester tester) async { final PageController controller = PageController(); + addTearDown(controller.dispose); expect( () => controller.page, throwsA(isAssertionError.having( @@ -983,6 +997,7 @@ void main() { expect(controller.page, 2); final PageController controller2 = PageController(keepPage: false); + addTearDown(controller2.dispose); await tester.pumpWidget(Directionality( textDirection: TextDirection.ltr, child: PageStorage( @@ -1001,10 +1016,11 @@ void main() { expect(controller2.page, 0); }); - testWidgets('PageView exposes semantics of children', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageView exposes semantics of children', (WidgetTester tester) async { final SemanticsTester semantics = SemanticsTester(tester); final PageController controller = PageController(); + addTearDown(controller.dispose); await tester.pumpWidget(Directionality( textDirection: TextDirection.ltr, child: PageView( @@ -1040,7 +1056,7 @@ void main() { semantics.dispose(); }); - testWidgets('PageMetrics', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageMetrics', (WidgetTester tester) async { final PageMetrics page = PageMetrics( minScrollExtent: 100.0, maxScrollExtent: 200.0, @@ -1057,8 +1073,9 @@ void main() { expect(page2.page, 4.0); }); - testWidgets('Page controller can handle rounding issue', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Page controller can handle rounding issue', (WidgetTester tester) async { final PageController pageController = PageController(); + addTearDown(pageController.dispose); await tester.pumpWidget(Directionality( textDirection: TextDirection.ltr, @@ -1077,10 +1094,11 @@ void main() { expect(pageController.page, 1); }); - testWidgets('PageView can participate in a11y scrolling', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageView can participate in a11y scrolling', (WidgetTester tester) async { final SemanticsTester semantics = SemanticsTester(tester); final PageController controller = PageController(); + addTearDown(controller.dispose); await tester.pumpWidget(Directionality( textDirection: TextDirection.ltr, child: PageView( @@ -1155,7 +1173,7 @@ void main() { expect(context.clipBehavior, equals(Clip.antiAlias)); }); - testWidgets('PageView.padEnds tests', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageView.padEnds tests', (WidgetTester tester) async { Finder viewportFinder() => find.byType(SliverFillViewport, skipOffstage: false); // PageView() defaults to true. @@ -1177,10 +1195,11 @@ void main() { expect(tester.widget(viewportFinder()).padEnds, false); }); - testWidgets('PageView - precision error inside RenderSliverFixedExtentBoxAdaptor', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageView - precision error inside RenderSliverFixedExtentBoxAdaptor', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/95101 - final PageController controller = PageController(initialPage: 152); + addTearDown(controller.dispose); + await tester.pumpWidget( Center( child: SizedBox( @@ -1204,9 +1223,10 @@ void main() { expect(tester.takeException(), isNull); }); - testWidgets('PageView content should not be stretched on precision error', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageView content should not be stretched on precision error', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/126561. final PageController controller = PageController(); + addTearDown(controller.dispose); const double pixel6EmulatorWidth = 411.42857142857144; diff --git a/packages/flutter/test/widgets/pageable_list_test.dart b/packages/flutter/test/widgets/pageable_list_test.dart index 3cab09a14c5ff..0dd30a18da5eb 100644 --- a/packages/flutter/test/widgets/pageable_list_test.dart +++ b/packages/flutter/test/widgets/pageable_list_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'; Size pageSize = const Size(600.0, 300.0); const List defaultPages = [0, 1, 2, 3, 4, 5]; @@ -59,7 +60,7 @@ Future pageRight(WidgetTester tester) { } void main() { - testWidgets('PageView default control', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageView default control', (WidgetTester tester) async { await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -70,7 +71,7 @@ void main() { ); }); - testWidgets('PageView control test (LTR)', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageView control test (LTR)', (WidgetTester tester) async { currentPage = null; await tester.pumpWidget(buildFrame(textDirection: TextDirection.ltr)); expect(currentPage, isNull); @@ -98,7 +99,7 @@ void main() { expect(currentPage, equals(0)); }); - testWidgets('PageView with reverse (LTR)', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageView with reverse (LTR)', (WidgetTester tester) async { currentPage = null; await tester.pumpWidget(buildFrame(reverse: true, textDirection: TextDirection.ltr)); await pageRight(tester); @@ -132,7 +133,7 @@ void main() { expect(find.text('5'), findsNothing); }); - testWidgets('PageView control test (RTL)', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageView control test (RTL)', (WidgetTester tester) async { currentPage = null; await tester.pumpWidget(buildFrame(textDirection: TextDirection.rtl)); await pageRight(tester); @@ -166,7 +167,7 @@ void main() { expect(find.text('5'), findsNothing); }); - testWidgets('PageView with reverse (RTL)', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PageView with reverse (RTL)', (WidgetTester tester) async { currentPage = null; await tester.pumpWidget(buildFrame(reverse: true, textDirection: TextDirection.rtl)); expect(currentPage, isNull); diff --git a/packages/flutter/test/widgets/parent_data_test.dart b/packages/flutter/test/widgets/parent_data_test.dart index d546947c81f9c..525d10816166b 100644 --- a/packages/flutter/test/widgets/parent_data_test.dart +++ b/packages/flutter/test/widgets/parent_data_test.dart @@ -6,6 +6,7 @@ import 'package:flutter/material.dart'; 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'; import 'test_widgets.dart'; @@ -49,7 +50,7 @@ void checkTree(WidgetTester tester, List expectedParentData) { final TestParentData kNonPositioned = TestParentData(); void main() { - testWidgets('ParentDataWidget control test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ParentDataWidget control test', (WidgetTester tester) async { await tester.pumpWidget( const Stack( textDirection: TextDirection.ltr, @@ -249,7 +250,7 @@ void main() { checkTree(tester, []); }); - testWidgets('ParentDataWidget conflicting data', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ParentDataWidget conflicting data', (WidgetTester tester) async { await tester.pumpWidget( const Directionality( textDirection: TextDirection.ltr, @@ -331,7 +332,7 @@ void main() { checkTree(tester, []); }); - testWidgets('ParentDataWidget interacts with global keys', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ParentDataWidget interacts with global keys', (WidgetTester tester) async { final GlobalKey key = GlobalKey(); await tester.pumpWidget( @@ -389,7 +390,7 @@ void main() { ]); }); - testWidgets('Parent data invalid ancestor', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Parent data invalid ancestor', (WidgetTester tester) async { await tester.pumpWidget(Directionality( textDirection: TextDirection.ltr, child: Row( @@ -424,7 +425,7 @@ void main() { ); }); - testWidgets('ParentDataWidget can be used with different ancestor RenderObjectWidgets', (WidgetTester tester) async { + testWidgetsWithLeakTracking('ParentDataWidget can be used with different ancestor RenderObjectWidgets', (WidgetTester tester) async { await tester.pumpWidget( OneAncestorWidget( child: Container(), diff --git a/packages/flutter/test/widgets/performance_overlay_test.dart b/packages/flutter/test/widgets/performance_overlay_test.dart index 8c337f1182a8a..9af1f11012fc5 100644 --- a/packages/flutter/test/widgets/performance_overlay_test.dart +++ b/packages/flutter/test/widgets/performance_overlay_test.dart @@ -5,14 +5,15 @@ import 'package:flutter/src/rendering/performance_overlay.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('Performance overlay smoke test', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Performance overlay smoke test', (WidgetTester tester) async { await tester.pumpWidget(const PerformanceOverlay()); await tester.pumpWidget(PerformanceOverlay.allEnabled()); }); - testWidgets('update widget field checkerboardRasterCacheImages', + testWidgetsWithLeakTracking('update widget field checkerboardRasterCacheImages', (WidgetTester tester) async { await tester.pumpWidget(const PerformanceOverlay()); await tester.pumpWidget( @@ -25,7 +26,7 @@ void main() { true); }); - testWidgets('update widget field checkerboardOffscreenLayers', + testWidgetsWithLeakTracking('update widget field checkerboardOffscreenLayers', (WidgetTester tester) async { await tester.pumpWidget(const PerformanceOverlay()); await tester.pumpWidget( diff --git a/packages/flutter/test/widgets/physical_model_test.dart b/packages/flutter/test/widgets/physical_model_test.dart index 7d3146b9c1b76..066d1c7573259 100644 --- a/packages/flutter/test/widgets/physical_model_test.dart +++ b/packages/flutter/test/widgets/physical_model_test.dart @@ -10,9 +10,10 @@ library; 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('PhysicalModel updates clipBehavior in updateRenderObject', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PhysicalModel updates clipBehavior in updateRenderObject', (WidgetTester tester) async { await tester.pumpWidget( const MaterialApp(home: PhysicalModel(color: Colors.red)), ); @@ -28,7 +29,7 @@ void main() { expect(renderPhysicalModel.clipBehavior, equals(Clip.antiAlias)); }); - testWidgets('PhysicalShape updates clipBehavior in updateRenderObject', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PhysicalShape updates clipBehavior in updateRenderObject', (WidgetTester tester) async { await tester.pumpWidget( const MaterialApp(home: PhysicalShape(color: Colors.red, clipper: ShapeBorderClipper(shape: CircleBorder()))), ); @@ -44,7 +45,7 @@ void main() { expect(renderPhysicalShape.clipBehavior, equals(Clip.antiAlias)); }); - testWidgets('PhysicalModel - clips when overflows and elevation is 0', (WidgetTester tester) async { + testWidgetsWithLeakTracking('PhysicalModel - clips when overflows and elevation is 0', (WidgetTester tester) async { const Key key = Key('test'); await tester.pumpWidget( Theme( diff --git a/packages/flutter/test/widgets/placeholder_test.dart b/packages/flutter/test/widgets/placeholder_test.dart index 980f6473edc77..28aadb0dbf213 100644 --- a/packages/flutter/test/widgets/placeholder_test.dart +++ b/packages/flutter/test/widgets/placeholder_test.dart @@ -4,9 +4,10 @@ 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('Placeholder', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Placeholder', (WidgetTester tester) async { await tester.pumpWidget(const Placeholder()); expect(tester.renderObject(find.byType(Placeholder)).size, const Size(800.0, 600.0)); await tester.pumpWidget(const Center(child: Placeholder())); @@ -19,21 +20,21 @@ void main() { expect(tester.renderObject(find.byType(Placeholder)).size, const Size(200.0, 300.0)); }); - testWidgets('Placeholder color', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Placeholder color', (WidgetTester tester) async { await tester.pumpWidget(const Placeholder()); expect(tester.renderObject(find.byType(Placeholder)), paints..path(color: const Color(0xFF455A64))); await tester.pumpWidget(const Placeholder(color: Color(0xFF00FF00))); expect(tester.renderObject(find.byType(Placeholder)), paints..path(color: const Color(0xFF00FF00))); }); - testWidgets('Placeholder stroke width', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Placeholder stroke width', (WidgetTester tester) async { await tester.pumpWidget(const Placeholder()); expect(tester.renderObject(find.byType(Placeholder)), paints..path(strokeWidth: 2.0)); await tester.pumpWidget(const Placeholder(strokeWidth: 10.0)); expect(tester.renderObject(find.byType(Placeholder)), paints..path(strokeWidth: 10.0)); }); - testWidgets('Placeholder child widget', (WidgetTester tester) async { + testWidgetsWithLeakTracking('Placeholder child widget', (WidgetTester tester) async { await tester.pumpWidget(const Placeholder()); expect(find.text('Label'), findsNothing); await tester.pumpWidget(const MaterialApp(home: Placeholder(child: Text('Label')))); diff --git a/packages/flutter/test/widgets/platform_menu_bar_test.dart b/packages/flutter/test/widgets/platform_menu_bar_test.dart index 8828115a91c39..c72e85130e4a1 100644 --- a/packages/flutter/test/widgets/platform_menu_bar_test.dart +++ b/packages/flutter/test/widgets/platform_menu_bar_test.dart @@ -8,6 +8,7 @@ import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter/src/foundation/diagnostics.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -47,7 +48,7 @@ void main() { group('PlatformMenuBar', () { group('basic menu structure is transmitted to platform', () { - testWidgets('using onSelected', (WidgetTester tester) async { + testWidgetsWithLeakTracking('using onSelected', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Material( @@ -78,7 +79,7 @@ void main() { equals(expectedStructure), ); }); - testWidgets('using onSelectedIntent', (WidgetTester tester) async { + testWidgetsWithLeakTracking('using onSelectedIntent', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Material( @@ -126,7 +127,7 @@ void main() { ); expect(tester.takeException(), isA()); }); - testWidgets('diagnostics', (WidgetTester tester) async { + testWidgetsWithLeakTracking('diagnostics', (WidgetTester tester) async { const PlatformMenuItem item = PlatformMenuItem( label: 'label2', shortcut: SingleActivator(LogicalKeyboardKey.keyA), @@ -158,7 +159,7 @@ void main() { }); }); group('MenuBarItem', () { - testWidgets('diagnostics', (WidgetTester tester) async { + testWidgetsWithLeakTracking('diagnostics', (WidgetTester tester) async { const PlatformMenuItem childItem = PlatformMenuItem( label: 'label', ); @@ -182,7 +183,7 @@ void main() { }); group('ShortcutSerialization', () { - testWidgets('character constructor', (WidgetTester tester) async { + testWidgetsWithLeakTracking('character constructor', (WidgetTester tester) async { final ShortcutSerialization serialization = ShortcutSerialization.character('?'); expect(serialization.toChannelRepresentation(), equals({ 'shortcutCharacter': '?', @@ -195,7 +196,7 @@ void main() { })); }); - testWidgets('modifier constructor', (WidgetTester tester) async { + testWidgetsWithLeakTracking('modifier constructor', (WidgetTester tester) async { final ShortcutSerialization serialization = ShortcutSerialization.modifier(LogicalKeyboardKey.home); expect(serialization.toChannelRepresentation(), equals({ 'shortcutTrigger': LogicalKeyboardKey.home.keyId,