Unverified Commit e6d160a5 authored by Kostia Sokolovskyi's avatar Kostia Sokolovskyi Committed by GitHub

Cover more test/widgets tests with leak tracking #7 (#134943)

parent b0a90aee
......@@ -6,6 +6,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'navigator_utils.dart';
......@@ -34,7 +35,7 @@ void main() {
.setMockMethodCallHandler(SystemChannels.platform, null);
});
testWidgets('toggling canPop on root route allows/prevents backs', (WidgetTester tester) async {
testWidgetsWithLeakTracking('toggling canPop on root route allows/prevents backs', (WidgetTester tester) async {
bool canPop = false;
late StateSetter setState;
late BuildContext context;
......@@ -79,7 +80,7 @@ void main() {
variant: TargetPlatformVariant.all(),
);
testWidgets('toggling canPop on secondary route allows/prevents backs', (WidgetTester tester) async {
testWidgetsWithLeakTracking('toggling canPop on secondary route allows/prevents backs', (WidgetTester tester) async {
final GlobalKey<NavigatorState> nav = GlobalKey<NavigatorState>();
bool canPop = true;
late StateSetter setState;
......@@ -247,7 +248,7 @@ void main() {
variant: TargetPlatformVariant.all(),
);
testWidgets('removing PopScope from the tree removes its effect on navigation', (WidgetTester tester) async {
testWidgetsWithLeakTracking('removing PopScope from the tree removes its effect on navigation', (WidgetTester tester) async {
bool usePopScope = true;
late StateSetter setState;
late BuildContext context;
......@@ -299,7 +300,7 @@ void main() {
variant: TargetPlatformVariant.all(),
);
testWidgets('identical PopScopes', (WidgetTester tester) async {
testWidgetsWithLeakTracking('identical PopScopes', (WidgetTester tester) async {
bool usePopScope1 = true;
bool usePopScope2 = true;
late StateSetter setState;
......
......@@ -7,9 +7,10 @@ import 'dart:async';
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('Positioned constructors', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Positioned constructors', (WidgetTester tester) async {
final Widget child = Container();
final Positioned a = Positioned(
left: 101.0,
......@@ -56,7 +57,7 @@ void main() {
expect(c.height, null);
});
testWidgets('Can animate position data', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Can animate position data', (WidgetTester tester) async {
final RelativeRectTween rect = RelativeRectTween(
begin: RelativeRect.fromRect(
const Rect.fromLTRB(10.0, 20.0, 20.0, 30.0),
......
......@@ -6,6 +6,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
class ExpandingBox extends StatefulWidget {
const ExpandingBox({ super.key, required this.collapsedSize, required this.expandedSize });
......@@ -53,7 +54,7 @@ class _ExpandingBoxState extends State<ExpandingBox> with AutomaticKeepAliveClie
}
void main() {
testWidgets('shrink listview', (WidgetTester tester) async {
testWidgetsWithLeakTracking('shrink listview', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: ListView.builder(
itemBuilder: (BuildContext context, int index) => index == 0
......@@ -98,7 +99,7 @@ void main() {
expect(position.pixels, 100.0);
});
testWidgets('shrink listview while dragging', (WidgetTester tester) async {
testWidgetsWithLeakTracking('shrink listview while dragging', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: ListView.builder(
itemBuilder: (BuildContext context, int index) => index == 0
......@@ -157,7 +158,7 @@ void main() {
expect(position.pixels, 50.0);
});
testWidgets('shrink listview while ballistic', (WidgetTester tester) async {
testWidgetsWithLeakTracking('shrink listview while ballistic', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: GestureDetector(
onTap: () { assert(false); },
......@@ -220,7 +221,7 @@ void main() {
expect(position.pixels, 0.0);
});
testWidgets('expanding page views', (WidgetTester tester) async {
testWidgetsWithLeakTracking('expanding page views', (WidgetTester tester) async {
await tester.pumpWidget(const Padding(padding: EdgeInsets.only(right: 200.0), child: TabBarDemo()));
await tester.tap(find.text('bike'));
await tester.pump();
......@@ -231,7 +232,7 @@ void main() {
expect(bike2.center, bike1.shift(const Offset(100.0, 0.0)).center);
});
testWidgets('changing the size of the viewport when overscrolled', (WidgetTester tester) async {
testWidgetsWithLeakTracking('changing the size of the viewport when overscrolled', (WidgetTester tester) async {
Widget build(double height) {
return Directionality(
textDirection: TextDirection.rtl,
......@@ -265,7 +266,7 @@ void main() {
expect(oldPosition, newPosition);
});
testWidgets('inserting and removing an item when overscrolled', (WidgetTester tester) async {
testWidgetsWithLeakTracking('inserting and removing an item when overscrolled', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/62890
const double itemExtent = 100.0;
......
......@@ -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(RawKeyboardListener(focusNode: focusNode, child: Container()));
await tester.pumpWidget(RawKeyboardListener(focusNode: focusNode, child: Container()));
await tester.pumpWidget(Container());
});
testWidgets('Fuchsia key event', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Fuchsia key event', (WidgetTester tester) async {
final List<RawKeyEvent> events = <RawKeyEvent>[];
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
RawKeyboardListener(
......@@ -43,13 +46,13 @@ void main() {
expect(typedData.isModifierPressed(ModifierKey.metaModifier, side: KeyboardSide.left), isTrue);
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<RawKeyEvent> events = <RawKeyEvent>[];
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
RawKeyboardListener(
......@@ -74,13 +77,13 @@ void main() {
expect(typedData.isModifierPressed(ModifierKey.metaModifier, side: KeyboardSide.left), isTrue);
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<RawKeyEvent> events = <RawKeyEvent>[];
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
RawKeyboardListener(
......@@ -108,6 +111,5 @@ void main() {
expect(events.length, 0);
await tester.pumpWidget(Container());
focusNode.dispose();
});
}
......@@ -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('reassemble does not crash', (WidgetTester tester) async {
testWidgetsWithLeakTracking('reassemble does not crash', (WidgetTester tester) async {
await tester.pumpWidget(const MaterialApp(
home: Text('Hello World'),
));
......
......@@ -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';
@immutable
class Pair<T> {
......@@ -239,7 +240,7 @@ class RenderSwapper extends RenderBox {
BoxParentData parentDataFor(RenderObject renderObject) => renderObject.parentData! as BoxParentData;
void main() {
testWidgets('RenderObjectElement *RenderObjectChild methods get called with correct arguments', (WidgetTester tester) async {
testWidgetsWithLeakTracking('RenderObjectElement *RenderObjectChild methods get called with correct arguments', (WidgetTester tester) async {
const Key redKey = ValueKey<String>('red');
const Key blueKey = ValueKey<String>('blue');
Widget widget() {
......
......@@ -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';
final BoxDecoration kBoxDecorationA = BoxDecoration(border: nonconst(null));
final BoxDecoration kBoxDecorationB = BoxDecoration(border: nonconst(null));
......@@ -75,7 +76,7 @@ class TestNonVisitingRenderObject extends RenderBox with RenderObjectWithChildMi
}
void main() {
testWidgets('RenderObjectWidget smoke test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('RenderObjectWidget smoke test', (WidgetTester tester) async {
await tester.pumpWidget(DecoratedBox(decoration: kBoxDecorationA));
SingleChildRenderObjectElement element =
tester.element(find.byElementType(SingleChildRenderObjectElement));
......@@ -94,7 +95,7 @@ void main() {
expect(renderObject.position, equals(DecorationPosition.background));
});
testWidgets('RenderObjectWidget can add and remove children', (WidgetTester tester) async {
testWidgetsWithLeakTracking('RenderObjectWidget can add and remove children', (WidgetTester tester) async {
void checkFullTree() {
final SingleChildRenderObjectElement element =
......@@ -178,7 +179,7 @@ void main() {
childBareTree();
});
testWidgets('Detached render tree is intact', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Detached render tree is intact', (WidgetTester tester) async {
await tester.pumpWidget(DecoratedBox(
decoration: kBoxDecorationA,
......@@ -220,7 +221,7 @@ void main() {
expect(grandChild.child, isNull);
});
testWidgets('Can watch inherited widgets', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Can watch inherited widgets', (WidgetTester tester) async {
final Key boxKey = UniqueKey();
final TestOrientedBox box = TestOrientedBox(key: boxKey);
......@@ -242,7 +243,7 @@ void main() {
expect(decoration.color, equals(const Color(0xFF0000FF)));
});
testWidgets('RenderObject not visiting children provides helpful error message', (WidgetTester tester) async {
testWidgetsWithLeakTracking('RenderObject not visiting children provides helpful error message', (WidgetTester tester) async {
await tester.pumpWidget(
TestNonVisitingWidget(
child: Container(color: const Color(0xFFED1D7F)),
......
......@@ -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';
// This is a regression test for https://github.com/flutter/flutter/issues/5588.
......@@ -92,7 +93,7 @@ class RekeyableDummyStatefulWidgetWrapperState extends State<RekeyableDummyState
}
void main() {
testWidgets('Handle GlobalKey reparenting in weird orders', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Handle GlobalKey reparenting in weird orders', (WidgetTester tester) async {
// This is a bit of a weird test so let's try to explain it a bit.
//
......
......@@ -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 StateMarker extends StatefulWidget {
const StateMarker({ super.key, this.child });
......@@ -50,7 +51,7 @@ class DeactivateLoggerState extends State<DeactivateLogger> {
}
void main() {
testWidgets('can reparent state', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can reparent state', (WidgetTester tester) async {
final GlobalKey left = GlobalKey();
final GlobalKey right = GlobalKey();
......@@ -130,7 +131,7 @@ void main() {
expect(right.currentState, isNull);
});
testWidgets('can reparent state with multichild widgets', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can reparent state with multichild widgets', (WidgetTester tester) async {
final GlobalKey left = GlobalKey();
final GlobalKey right = GlobalKey();
......@@ -198,7 +199,7 @@ void main() {
expect(right.currentState, isNull);
});
testWidgets('can with scrollable list', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can with scrollable list', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
await tester.pumpWidget(StateMarker(key: key));
......@@ -231,7 +232,7 @@ void main() {
expect(keyState.marker, equals('marked'));
});
testWidgets('Reparent during update children', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Reparent during update children', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
await tester.pumpWidget(Stack(
......@@ -268,7 +269,7 @@ void main() {
expect(keyState.marker, equals('marked'));
});
testWidgets('Reparent to child during update children', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Reparent to child during update children', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
await tester.pumpWidget(Stack(
......@@ -330,7 +331,7 @@ void main() {
expect(keyState.marker, equals('marked'));
});
testWidgets('Deactivate implies build', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Deactivate implies build', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
final List<String> log = <String>[];
final DeactivateLogger logger = DeactivateLogger(key: key, log: log);
......@@ -352,7 +353,7 @@ void main() {
expect(log, isEmpty);
});
testWidgets('Reparenting with multiple moves', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Reparenting with multiple moves', (WidgetTester tester) async {
final GlobalKey key1 = GlobalKey();
final GlobalKey key2 = GlobalKey();
final GlobalKey key3 = GlobalKey();
......
......@@ -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';
// This is a regression test for https://github.com/flutter/flutter/issues/5840.
......@@ -65,7 +66,7 @@ class StatefulCreationCounterState extends State<StatefulCreationCounter> {
}
void main() {
testWidgets('reparent state with layout builder', (WidgetTester tester) async {
testWidgetsWithLeakTracking('reparent state with layout builder', (WidgetTester tester) async {
expect(StatefulCreationCounterState.creationCount, 0);
await tester.pumpWidget(const Bar());
expect(StatefulCreationCounterState.creationCount, 1);
......@@ -75,7 +76,7 @@ void main() {
expect(StatefulCreationCounterState.creationCount, 1);
});
testWidgets('Clean then reparent with dependencies', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Clean then reparent with dependencies', (WidgetTester tester) async {
int layoutBuilderBuildCount = 0;
late StateSetter keyedSetState;
......
......@@ -4,13 +4,15 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'restoration.dart';
void main() {
testWidgets('claims bucket', (WidgetTester tester) async {
testWidgetsWithLeakTracking('claims bucket', (WidgetTester tester) async {
const String id = 'hello world 1234';
final MockRestorationManager manager = MockRestorationManager();
addTearDown(manager.dispose);
final Map<String, dynamic> rawData = <String, dynamic>{};
final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: rawData);
expect(rawData, isEmpty);
......@@ -35,8 +37,9 @@ void main() {
expect(state.restoreStateLog.single, isNull);
});
testWidgets('claimed bucket with data', (WidgetTester tester) async {
testWidgetsWithLeakTracking('claimed bucket with data', (WidgetTester tester) async {
final MockRestorationManager manager = MockRestorationManager();
addTearDown(manager.dispose);
final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: _createRawDataSet());
await tester.pumpWidget(
......@@ -57,8 +60,9 @@ void main() {
expect(state.restoreStateLog.single, isNull);
});
testWidgets('renames existing bucket when new ID is provided via widget', (WidgetTester tester) async {
testWidgetsWithLeakTracking('renames existing bucket when new ID is provided via widget', (WidgetTester tester) async {
final MockRestorationManager manager = MockRestorationManager();
addTearDown(manager.dispose);
final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: _createRawDataSet());
await tester.pumpWidget(
......@@ -99,8 +103,9 @@ void main() {
expect(state.toggleBucketLog, isEmpty);
});
testWidgets('renames existing bucket when didUpdateRestorationId is called', (WidgetTester tester) async {
testWidgetsWithLeakTracking('renames existing bucket when didUpdateRestorationId is called', (WidgetTester tester) async {
final MockRestorationManager manager = MockRestorationManager();
addTearDown(manager.dispose);
final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: _createRawDataSet());
await tester.pumpWidget(
......@@ -134,8 +139,9 @@ void main() {
expect(state.toggleBucketLog, isEmpty);
});
testWidgets('Disposing widget removes its data', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Disposing widget removes its data', (WidgetTester tester) async {
final MockRestorationManager manager = MockRestorationManager();
addTearDown(manager.dispose);
final Map<String, dynamic> rawData = _createRawDataSet();
final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: rawData);
......@@ -162,8 +168,9 @@ void main() {
expect((rawData[childrenMapKey] as Map<String, dynamic>).containsKey('child1'), isFalse);
});
testWidgets('toggling id between null and non-null', (WidgetTester tester) async {
testWidgetsWithLeakTracking('toggling id between null and non-null', (WidgetTester tester) async {
final MockRestorationManager manager = MockRestorationManager();
addTearDown(manager.dispose);
final Map<String, dynamic> rawData = _createRawDataSet();
final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: rawData);
......@@ -222,9 +229,10 @@ void main() {
expect(state.toggleBucketLog.single, same(bucket));
});
testWidgets('move in and out of scope', (WidgetTester tester) async {
testWidgetsWithLeakTracking('move in and out of scope', (WidgetTester tester) async {
final Key key = GlobalKey();
final MockRestorationManager manager = MockRestorationManager();
addTearDown(manager.dispose);
final Map<String, dynamic> rawData = _createRawDataSet();
final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: rawData);
......@@ -284,8 +292,9 @@ void main() {
expect(state.toggleBucketLog.single, same(bucket));
});
testWidgets('moving scope moves its data', (WidgetTester tester) async {
testWidgetsWithLeakTracking('moving scope moves its data', (WidgetTester tester) async {
final MockRestorationManager manager = MockRestorationManager();
addTearDown(manager.dispose);
final Map<String, dynamic> rawData = <String, dynamic>{};
final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: rawData);
final Key key = GlobalKey();
......@@ -349,7 +358,7 @@ void main() {
expect((rawData[childrenMapKey] as Map<Object?, Object?>).containsKey('moving-child'), isTrue);
});
testWidgets('restartAndRestore', (WidgetTester tester) async {
testWidgetsWithLeakTracking('restartAndRestore', (WidgetTester tester) async {
await tester.pumpWidget(
const RootRestorationScope(
restorationId: 'root-child',
......@@ -388,7 +397,7 @@ void main() {
expect(state.toggleBucketLog, isEmpty);
});
testWidgets('restore while running', (WidgetTester tester) async {
testWidgetsWithLeakTracking('restore while running', (WidgetTester tester) async {
await tester.pumpWidget(
const RootRestorationScope(
restorationId: 'root-child',
......@@ -427,7 +436,7 @@ void main() {
expect(state.toggleBucketLog, isEmpty);
});
testWidgets('can register additional property outside of restoreState', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can register additional property outside of restoreState', (WidgetTester tester) async {
await tester.pumpWidget(
const RootRestorationScope(
restorationId: 'root-child',
......@@ -464,7 +473,7 @@ void main() {
expect(state.property.log, <String>['fromPrimitives', 'initWithValue']);
});
testWidgets('cannot register same property twice', (WidgetTester tester) async {
testWidgetsWithLeakTracking('cannot register same property twice', (WidgetTester tester) async {
await tester.pumpWidget(
const RootRestorationScope(
restorationId: 'root-child',
......@@ -494,7 +503,7 @@ void main() {
expect(() => state.registerPropertyUnderSameId(), throwsAssertionError);
});
testWidgets('data of disabled property is not stored', (WidgetTester tester) async {
testWidgetsWithLeakTracking('data of disabled property is not stored', (WidgetTester tester) async {
await tester.pumpWidget(
const RootRestorationScope(
restorationId: 'root-child',
......@@ -534,7 +543,7 @@ void main() {
expect(state.property.value, 10); // Initialized to default value.
});
testWidgets('Enabling property stores its data again', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Enabling property stores its data again', (WidgetTester tester) async {
await tester.pumpWidget(
const RootRestorationScope(
restorationId: 'root-child',
......@@ -572,7 +581,7 @@ void main() {
expect(state.property.value, 40);
});
testWidgets('Unregistering a property removes its data', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Unregistering a property removes its data', (WidgetTester tester) async {
await tester.pumpWidget(
const RootRestorationScope(
restorationId: 'root-child',
......@@ -598,7 +607,7 @@ void main() {
expect(state.bucket!.read<int>('additional'), 11);
});
testWidgets('Disposing a property unregisters it, but keeps data', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Disposing a property unregisters it, but keeps data', (WidgetTester tester) async {
await tester.pumpWidget(
const RootRestorationScope(
restorationId: 'root-child',
......
......@@ -4,12 +4,13 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'restoration.dart';
void main() {
group('UnmanagedRestorationScope', () {
testWidgets('makes bucket available to descendants', (WidgetTester tester) async {
testWidgetsWithLeakTracking('makes bucket available to descendants', (WidgetTester tester) async {
final RestorationBucket bucket1 = RestorationBucket.empty(
restorationId: 'foo',
debugOwner: 'owner',
......@@ -39,7 +40,7 @@ void main() {
expect(state.bucket, bucket2);
});
testWidgets('null bucket disables restoration', (WidgetTester tester) async {
testWidgetsWithLeakTracking('null bucket disables restoration', (WidgetTester tester) async {
await tester.pumpWidget(
const UnmanagedRestorationScope(
child: BucketSpy(),
......@@ -51,7 +52,7 @@ void main() {
});
group('RestorationScope', () {
testWidgets('asserts when none is found', (WidgetTester tester) async {
testWidgetsWithLeakTracking('asserts when none is found', (WidgetTester tester) async {
late BuildContext capturedContext;
await tester.pumpWidget(WidgetsApp(
color: const Color(0xD0FF0000),
......@@ -97,9 +98,10 @@ void main() {
expect(RestorationScope.of(capturedContext), scope.bucket);
});
testWidgets('makes bucket available to descendants', (WidgetTester tester) async {
testWidgetsWithLeakTracking('makes bucket available to descendants', (WidgetTester tester) async {
const String id = 'hello world 1234';
final MockRestorationManager manager = MockRestorationManager();
addTearDown(manager.dispose);
final Map<String, dynamic> rawData = <String, dynamic>{};
final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: rawData);
expect(rawData, isEmpty);
......@@ -120,8 +122,9 @@ void main() {
expect((rawData[childrenMapKey] as Map<Object?, Object?>).containsKey(id), isTrue);
});
testWidgets('bucket for descendants contains data claimed from parent', (WidgetTester tester) async {
testWidgetsWithLeakTracking('bucket for descendants contains data claimed from parent', (WidgetTester tester) async {
final MockRestorationManager manager = MockRestorationManager();
addTearDown(manager.dispose);
final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: _createRawDataSet());
await tester.pumpWidget(
......@@ -140,8 +143,9 @@ void main() {
expect(state.bucket!.read<int>('foo'), 22);
});
testWidgets('renames existing bucket when new ID is provided', (WidgetTester tester) async {
testWidgetsWithLeakTracking('renames existing bucket when new ID is provided', (WidgetTester tester) async {
final MockRestorationManager manager = MockRestorationManager();
addTearDown(manager.dispose);
final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: _createRawDataSet());
await tester.pumpWidget(
......@@ -178,8 +182,9 @@ void main() {
expect(state.bucket, same(bucket));
});
testWidgets('Disposing a scope removes its data', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Disposing a scope removes its data', (WidgetTester tester) async {
final MockRestorationManager manager = MockRestorationManager();
addTearDown(manager.dispose);
final Map<String, dynamic> rawData = _createRawDataSet();
final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: rawData);
......@@ -207,8 +212,9 @@ void main() {
expect((rawData[childrenMapKey] as Map<String, dynamic>).containsKey('child1'), isFalse);
});
testWidgets('no bucket for descendants when id is null', (WidgetTester tester) async {
testWidgetsWithLeakTracking('no bucket for descendants when id is null', (WidgetTester tester) async {
final MockRestorationManager manager = MockRestorationManager();
addTearDown(manager.dispose);
final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: <String, dynamic>{});
await tester.pumpWidget(
......@@ -251,7 +257,7 @@ void main() {
expect(state.bucket, isNull);
});
testWidgets('no bucket for descendants when scope is null', (WidgetTester tester) async {
testWidgetsWithLeakTracking('no bucket for descendants when scope is null', (WidgetTester tester) async {
final Key scopeKey = GlobalKey();
await tester.pumpWidget(
......@@ -266,6 +272,7 @@ void main() {
// Move it under a valid scope.
final MockRestorationManager manager = MockRestorationManager();
addTearDown(manager.dispose);
final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: <String, dynamic>{});
await tester.pumpWidget(
UnmanagedRestorationScope(
......@@ -293,7 +300,7 @@ void main() {
expect(state.bucket, isNull);
});
testWidgets('no bucket for descendants when scope and id are null', (WidgetTester tester) async {
testWidgetsWithLeakTracking('no bucket for descendants when scope and id are null', (WidgetTester tester) async {
await tester.pumpWidget(
const RestorationScope(
restorationId: null,
......@@ -304,8 +311,9 @@ void main() {
expect(state.bucket, isNull);
});
testWidgets('moving scope moves its data', (WidgetTester tester) async {
testWidgetsWithLeakTracking('moving scope moves its data', (WidgetTester tester) async {
final MockRestorationManager manager = MockRestorationManager();
addTearDown(manager.dispose);
final Map<String, dynamic> rawData = <String, dynamic>{};
final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: rawData);
final Key scopeKey = GlobalKey();
......
......@@ -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('widget moves scopes during restore', (WidgetTester tester) async {
testWidgetsWithLeakTracking('widget moves scopes during restore', (WidgetTester tester) async {
await tester.pumpWidget(const RootRestorationScope(
restorationId: 'root',
child: Directionality(
......@@ -68,7 +69,7 @@ void main() {
expect(tester.state<TestWidgetWithCounterChildState>(find.byType(TestWidgetWithCounterChild)).toggleCount, 0);
});
testWidgets('restoration is turned on later', (WidgetTester tester) async {
testWidgetsWithLeakTracking('restoration is turned on later', (WidgetTester tester) async {
tester.binding.restorationManager.disableRestoration();
await tester.pumpWidget(const RootRestorationScope(
restorationId: 'root-child',
......
......@@ -6,9 +6,10 @@ 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';
void main() {
testWidgets('RichText with recognizers without handlers does not throw', (WidgetTester tester) async {
testWidgetsWithLeakTracking('RichText with recognizers without handlers does not throw', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -40,7 +41,7 @@ void main() {
));
});
testWidgets('TextSpan Locale works', (WidgetTester tester) async {
testWidgetsWithLeakTracking('TextSpan Locale works', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -89,7 +90,7 @@ void main() {
));
});
testWidgets('TextSpan spellOut works', (WidgetTester tester) async {
testWidgetsWithLeakTracking('TextSpan spellOut works', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -138,7 +139,7 @@ void main() {
));
});
testWidgets('WidgetSpan calculate correct intrinsic heights', (WidgetTester tester) async {
testWidgetsWithLeakTracking('WidgetSpan calculate correct intrinsic heights', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -170,7 +171,7 @@ void main() {
expect(tester.getSize(find.byType(IntrinsicHeight)).height, 3 * 16);
});
testWidgets('RichText implements debugFillProperties', (WidgetTester tester) async {
testWidgetsWithLeakTracking('RichText implements debugFillProperties', (WidgetTester tester) async {
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
RichText(
text: const TextSpan(text: 'rich text'),
......
......@@ -7,6 +7,7 @@ import 'dart:async';
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';
import 'restoration.dart';
......@@ -17,8 +18,13 @@ void main() {
binding._restorationManager = MockRestorationManager();
});
testWidgets('does not inject root bucket if inside scope', (WidgetTester tester) async {
tearDown(() {
binding._restorationManager.dispose();
});
testWidgetsWithLeakTracking('does not inject root bucket if inside scope', (WidgetTester tester) async {
final MockRestorationManager manager = MockRestorationManager();
addTearDown(manager.dispose);
final Map<String, dynamic> rawData = <String, dynamic>{};
final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: rawData);
expect(rawData, isEmpty);
......@@ -47,7 +53,7 @@ void main() {
expect(find.text('Hello'), findsOneWidget);
});
testWidgets('waits for root bucket', (WidgetTester tester) async {
testWidgetsWithLeakTracking('waits for root bucket', (WidgetTester tester) async {
final Completer<RestorationBucket> bucketCompleter = Completer<RestorationBucket>();
binding.restorationManager.rootBucket = bucketCompleter.future;
......@@ -83,7 +89,7 @@ void main() {
expect((rawData[childrenMapKey] as Map<Object?, Object?>).containsKey('root-child'), isTrue);
});
testWidgets('no delay when root is available synchronously', (WidgetTester tester) async {
testWidgetsWithLeakTracking('no delay when root is available synchronously', (WidgetTester tester) async {
final Map<String, dynamic> rawData = <String, dynamic>{};
final RestorationBucket root = RestorationBucket.root(manager: binding.restorationManager, rawData: rawData);
binding.restorationManager.rootBucket = SynchronousFuture<RestorationBucket>(root);
......@@ -109,7 +115,7 @@ void main() {
expect((rawData[childrenMapKey] as Map<Object?, Object?>).containsKey('root-child'), isTrue);
});
testWidgets('does not insert root when restoration id is null', (WidgetTester tester) async {
testWidgetsWithLeakTracking('does not insert root when restoration id is null', (WidgetTester tester) async {
await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,
......@@ -175,9 +181,10 @@ void main() {
expect(state.bucket, isNull);
});
testWidgets('injects root bucket when moved out of scope', (WidgetTester tester) async {
testWidgetsWithLeakTracking('injects root bucket when moved out of scope', (WidgetTester tester) async {
final Key rootScopeKey = GlobalKey();
final MockRestorationManager manager = MockRestorationManager();
addTearDown(manager.dispose);
final Map<String, dynamic> inScopeRawData = <String, dynamic>{};
final RestorationBucket inScopeRootBucket = RestorationBucket.root(manager: manager, rawData: inScopeRawData);
......@@ -257,7 +264,7 @@ void main() {
expect((inScopeRawData[childrenMapKey] as Map<Object?, Object?>).containsKey('root-child'), isTrue);
});
testWidgets('injects new root when old one is decommissioned', (WidgetTester tester) async {
testWidgetsWithLeakTracking('injects new root when old one is decommissioned', (WidgetTester tester) async {
final Map<String, dynamic> firstRawData = <String, dynamic>{};
final RestorationBucket firstRoot = RestorationBucket.root(manager: binding.restorationManager, rawData: firstRawData);
binding.restorationManager.rootBucket = SynchronousFuture<RestorationBucket>(firstRoot);
......@@ -300,7 +307,7 @@ void main() {
expect(state.bucket!.read<int>('foo'), 22);
});
testWidgets('injects null when rootBucket is null', (WidgetTester tester) async {
testWidgetsWithLeakTracking('injects null when rootBucket is null', (WidgetTester tester) async {
final Completer<RestorationBucket?> completer = Completer<RestorationBucket?>();
binding.restorationManager.rootBucket = completer.future;
......@@ -337,7 +344,7 @@ void main() {
expect(state.bucket, isNotNull);
});
testWidgets('can switch to null', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can switch to null', (WidgetTester tester) async {
final RestorationBucket root = RestorationBucket.root(manager: binding.restorationManager, rawData: null);
binding.restorationManager.rootBucket = SynchronousFuture<RestorationBucket>(root);
......
......@@ -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('Rotated box control test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Rotated box control test', (WidgetTester tester) async {
final List<String> log = <String>[];
final Key rotatedBoxKey = UniqueKey();
......
......@@ -9,6 +9,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
class OnTapPage extends StatelessWidget {
const OnTapPage({super.key, required this.id, required this.onTap});
......@@ -32,7 +33,7 @@ class OnTapPage extends StatelessWidget {
}
void main() {
testWidgets('Push and Pop should send platform messages', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Push and Pop should send platform messages', (WidgetTester tester) async {
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
'/': (BuildContext context) => OnTapPage(
id: '/',
......@@ -107,7 +108,7 @@ void main() {
);
});
testWidgets('Navigator does not report route name by default', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Navigator does not report route name by default', (WidgetTester tester) async {
final List<MethodCall> log = <MethodCall>[];
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.navigation, (MethodCall methodCall) async {
log.add(methodCall);
......@@ -141,7 +142,7 @@ void main() {
expect(log, hasLength(0));
});
testWidgets('Replace should send platform messages', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Replace should send platform messages', (WidgetTester tester) async {
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
'/': (BuildContext context) => OnTapPage(
id: '/',
......@@ -217,7 +218,7 @@ void main() {
);
});
testWidgets('Nameless routes should send platform messages', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Nameless routes should send platform messages', (WidgetTester tester) async {
final List<MethodCall> log = <MethodCall>[];
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.navigation, (MethodCall methodCall) async {
log.add(methodCall);
......@@ -261,7 +262,7 @@ void main() {
expect(log, isEmpty);
});
testWidgets('PlatformRouteInformationProvider reports URL', (WidgetTester tester) async {
testWidgetsWithLeakTracking('PlatformRouteInformationProvider reports URL', (WidgetTester tester) async {
final List<MethodCall> log = <MethodCall>[];
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.navigation, (MethodCall methodCall) async {
log.add(methodCall);
......@@ -273,12 +274,14 @@ void main() {
uri: Uri.parse('initial'),
),
);
addTearDown(provider.dispose);
final SimpleRouterDelegate delegate = SimpleRouterDelegate(
reportConfiguration: true,
builder: (BuildContext context, RouteInformation information) {
return Text(information.uri.toString());
},
);
addTearDown(delegate.dispose);
await tester.pumpWidget(MaterialApp.router(
routeInformationProvider: provider,
......@@ -313,7 +316,12 @@ void main() {
'replace': false,
}),
]);
});
},
leakTrackingTestConfig: const LeakTrackingTestConfig(
// TODO(ksokolovskyi): remove after fixing
// https://github.com/flutter/flutter/issues/134205
notDisposedAllowList: <String, int?> {'_RestorableRouteInformation': 1},
));
}
typedef SimpleRouterDelegateBuilder = Widget Function(BuildContext, RouteInformation);
......
This diff is collapsed.
......@@ -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('Padding RTL', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Padding RTL', (WidgetTester tester) async {
const Widget child = Padding(
padding: EdgeInsetsDirectional.only(start: 10.0),
child: Placeholder(),
......@@ -43,7 +44,7 @@ void main() {
);
});
testWidgets('Container padding/margin RTL', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Container padding/margin RTL', (WidgetTester tester) async {
final Widget child = Container(
padding: const EdgeInsetsDirectional.only(start: 6.0),
margin: const EdgeInsetsDirectional.only(end: 20.0, start: 4.0),
......@@ -63,7 +64,7 @@ void main() {
expect(tester.getTopRight(find.byType(Placeholder)), const Offset(790.0, 0.0));
});
testWidgets('Container padding/margin mixed RTL/absolute', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Container padding/margin mixed RTL/absolute', (WidgetTester tester) async {
final Widget child = Container(
padding: const EdgeInsets.only(left: 6.0),
margin: const EdgeInsetsDirectional.only(end: 20.0, start: 4.0),
......@@ -83,7 +84,7 @@ void main() {
expect(tester.getTopRight(find.byType(Placeholder)), const Offset(796.0, 0.0));
});
testWidgets('EdgeInsetsDirectional without Directionality', (WidgetTester tester) async {
testWidgetsWithLeakTracking('EdgeInsetsDirectional without Directionality', (WidgetTester tester) async {
await tester.pumpWidget(const Padding(padding: EdgeInsetsDirectional.zero));
expect(tester.takeException(), isAssertionError);
});
......
......@@ -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('runApp inside onPressed does not throw', (WidgetTester tester) async {
testWidgetsWithLeakTracking('runApp inside onPressed does not throw', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......
......@@ -5,10 +5,11 @@
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() {
group('SafeArea', () {
testWidgets('SafeArea - basic', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SafeArea - basic', (WidgetTester tester) async {
await tester.pumpWidget(
const MediaQuery(
data: MediaQueryData(padding: EdgeInsets.all(20.0)),
......@@ -22,7 +23,7 @@ void main() {
expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(780.0, 580.0));
});
testWidgets('SafeArea - with minimums', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SafeArea - with minimums', (WidgetTester tester) async {
await tester.pumpWidget(
const MediaQuery(
data: MediaQueryData(padding: EdgeInsets.all(20.0)),
......@@ -37,7 +38,7 @@ void main() {
expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(780.0, 570.0));
});
testWidgets('SafeArea - nested', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SafeArea - nested', (WidgetTester tester) async {
await tester.pumpWidget(
const MediaQuery(
data: MediaQueryData(padding: EdgeInsets.all(20.0)),
......@@ -54,7 +55,7 @@ void main() {
expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(780.0, 580.0));
});
testWidgets('SafeArea - changing', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SafeArea - changing', (WidgetTester tester) async {
const Widget child = SafeArea(
bottom: false,
child: SafeArea(
......@@ -85,7 +86,7 @@ void main() {
expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(800.0, 600.0));
});
testWidgets('SafeArea - properties', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SafeArea - properties', (WidgetTester tester) async {
final SafeArea child = SafeArea(
right: false,
bottom: false,
......@@ -112,7 +113,7 @@ void main() {
);
}
testWidgets('SafeArea alone.', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SafeArea alone.', (WidgetTester tester) async {
final Widget child = boilerplate(const SafeArea(
maintainBottomViewPadding: true,
child: Column(
......@@ -147,7 +148,7 @@ void main() {
expect(initialPoint, finalPoint);
});
testWidgets('SafeArea alone - partial ViewInsets consume Padding', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SafeArea alone - partial ViewInsets consume Padding', (WidgetTester tester) async {
final Widget child = boilerplate(const SafeArea(
maintainBottomViewPadding: true,
child: Column(
......@@ -180,7 +181,7 @@ void main() {
expect(initialPoint, finalPoint);
});
testWidgets('SafeArea with nested Scaffold', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SafeArea with nested Scaffold', (WidgetTester tester) async {
final Widget child = boilerplate(const SafeArea(
maintainBottomViewPadding: true,
child: Scaffold(
......@@ -218,7 +219,7 @@ void main() {
expect(initialPoint, finalPoint);
});
testWidgets('SafeArea with nested Scaffold - partial ViewInsets consume Padding', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SafeArea with nested Scaffold - partial ViewInsets consume Padding', (WidgetTester tester) async {
final Widget child = boilerplate(const SafeArea(
maintainBottomViewPadding: true,
child: Scaffold(
......@@ -258,12 +259,15 @@ void main() {
group('SliverSafeArea', () {
Widget buildWidget(EdgeInsets mediaPadding, Widget sliver) {
late final ViewportOffset offset;
addTearDown(() => offset.dispose());
return MediaQuery(
data: MediaQueryData(padding: mediaPadding),
child: Directionality(
textDirection: TextDirection.ltr,
child: Viewport(
offset: ViewportOffset.fixed(0.0),
offset: offset = ViewportOffset.fixed(0.0),
slivers: <Widget>[
const SliverToBoxAdapter(child: SizedBox(width: 800.0, height: 100.0, child: Text('before'))),
sliver,
......@@ -285,7 +289,7 @@ void main() {
expect(testAnswers, equals(expectedRects));
}
testWidgets('SliverSafeArea - basic', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverSafeArea - basic', (WidgetTester tester) async {
await tester.pumpWidget(
buildWidget(
const EdgeInsets.all(20.0),
......@@ -302,7 +306,7 @@ void main() {
]);
});
testWidgets('SliverSafeArea - basic', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverSafeArea - basic', (WidgetTester tester) async {
await tester.pumpWidget(
buildWidget(
const EdgeInsets.all(20.0),
......@@ -320,7 +324,7 @@ void main() {
]);
});
testWidgets('SliverSafeArea - nested', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverSafeArea - nested', (WidgetTester tester) async {
await tester.pumpWidget(
buildWidget(
const EdgeInsets.all(20.0),
......@@ -340,7 +344,7 @@ void main() {
]);
});
testWidgets('SliverSafeArea - changing', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverSafeArea - changing', (WidgetTester tester) async {
const Widget sliver = SliverSafeArea(
bottom: false,
sliver: SliverSafeArea(
......@@ -379,7 +383,7 @@ void main() {
});
});
testWidgets('SliverSafeArea - properties', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverSafeArea - properties', (WidgetTester tester) async {
const SliverSafeArea child = SliverSafeArea(
right: false,
bottom: false,
......
......@@ -6,6 +6,7 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
List<Widget> children(int n) {
return List<Widget>.generate(n, (int i) {
......@@ -14,8 +15,9 @@ List<Widget> children(int n) {
}
void main() {
testWidgets('Scrolling with list view changes, leaving the overscroll', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scrolling with list view changes, leaving the overscroll', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(MaterialApp(home: ListView(controller: controller, children: children(30))));
final double thirty = controller.position.maxScrollExtent;
controller.jumpTo(thirty);
......@@ -28,8 +30,9 @@ void main() {
expect(controller.position.pixels, thirty + 100.0); // and ends up at the end
});
testWidgets('Scrolling with list view changes, remaining overscrolled', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scrolling with list view changes, remaining overscrolled', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(MaterialApp(home: ListView(controller: controller, children: children(30))));
final double thirty = controller.position.maxScrollExtent;
controller.jumpTo(thirty);
......@@ -42,7 +45,7 @@ void main() {
expect(controller.position.pixels, thirty + 100.0); // and ends up at the end
});
testWidgets('Ability to keep a PageView at the end manually (issue 62209)', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Ability to keep a PageView at the end manually (issue 62209)', (WidgetTester tester) async {
await tester.pumpWidget(const MaterialApp(home: PageView62209()));
expect(find.text('Page 1'), findsOneWidget);
expect(find.text('Page 100'), findsNothing);
......@@ -129,8 +132,9 @@ void main() {
expect(find.text('Page 9'), findsOneWidget);
});
testWidgets('Pointer is not ignored during trackpad scrolling.', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Pointer is not ignored during trackpad scrolling.', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
int? lastTapped;
int? lastHovered;
await tester.pumpWidget(MaterialApp(
......
......@@ -6,6 +6,7 @@ import 'dart:ui' as ui show Image;
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import '../painting/image_test_utils.dart';
......@@ -17,6 +18,10 @@ void main() {
testImage = await createTestImage(width: 10, height: 10);
});
tearDownAll(() {
testImage.dispose();
});
tearDown(() {
imageCache.clear();
});
......@@ -29,7 +34,7 @@ void main() {
return Scrollable.of(find.byType(TestWidget).evaluate().first).position;
}
testWidgets('ScrollAwareImageProvider does not delay if widget is not in scrollable', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ScrollAwareImageProvider does not delay if widget is not in scrollable', (WidgetTester tester) async {
final GlobalKey<TestWidgetState> key = GlobalKey<TestWidgetState>();
await tester.pumpWidget(TestWidget(key));
......@@ -56,7 +61,7 @@ void main() {
expect(imageCache.currentSize, 1);
});
testWidgets('ScrollAwareImageProvider does not delay if in scrollable that is not scrolling', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ScrollAwareImageProvider does not delay if in scrollable that is not scrolling', (WidgetTester tester) async {
final GlobalKey<TestWidgetState> key = GlobalKey<TestWidgetState>();
await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr,
......@@ -92,9 +97,10 @@ void main() {
expect(findPhysics<RecordingPhysics>(tester).velocities, <double>[0]);
});
testWidgets('ScrollAwareImageProvider does not delay if in scrollable that is scrolling slowly', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ScrollAwareImageProvider does not delay if in scrollable that is scrolling slowly', (WidgetTester tester) async {
final List<GlobalKey<TestWidgetState>> keys = <GlobalKey<TestWidgetState>>[];
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr,
child: ListView.builder(
......@@ -149,9 +155,10 @@ void main() {
expect(imageCache.currentSize, 1);
});
testWidgets('ScrollAwareImageProvider delays if in scrollable that is scrolling fast', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ScrollAwareImageProvider delays if in scrollable that is scrolling fast', (WidgetTester tester) async {
final List<GlobalKey<TestWidgetState>> keys = <GlobalKey<TestWidgetState>>[];
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr,
child: ListView.builder(
......@@ -216,9 +223,10 @@ void main() {
expect(imageCache.currentSize, 1);
});
testWidgets('ScrollAwareImageProvider delays if in scrollable that is scrolling fast and fizzles if disposed', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ScrollAwareImageProvider delays if in scrollable that is scrolling fast and fizzles if disposed', (WidgetTester tester) async {
final List<GlobalKey<TestWidgetState>> keys = <GlobalKey<TestWidgetState>>[];
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr,
child: ListView.builder(
......@@ -285,9 +293,10 @@ void main() {
expect(imageCache.currentSize, 0);
});
testWidgets('ScrollAwareImageProvider resolves from ImageCache and does not set completer twice', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ScrollAwareImageProvider resolves from ImageCache and does not set completer twice', (WidgetTester tester) async {
final GlobalKey<TestWidgetState> key = GlobalKey<TestWidgetState>();
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr,
child: SingleChildScrollView(
......@@ -333,12 +342,13 @@ void main() {
expect(stream.completer, null);
});
testWidgets('ScrollAwareImageProvider does not block LRU updates to image cache', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ScrollAwareImageProvider does not block LRU updates to image cache', (WidgetTester tester) async {
final int oldSize = imageCache.maximumSize;
imageCache.maximumSize = 1;
final GlobalKey<TestWidgetState> key = GlobalKey<TestWidgetState>();
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr,
child: SingleChildScrollView(
......
......@@ -6,6 +6,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
late GestureVelocityTrackerBuilder lastCreatedBuilder;
class TestScrollBehavior extends ScrollBehavior {
......@@ -33,7 +34,7 @@ class TestScrollBehavior extends ScrollBehavior {
}
void main() {
testWidgets('Assert in buildScrollbar that controller != null when using it', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Assert in buildScrollbar that controller != null when using it', (WidgetTester tester) async {
const ScrollBehavior defaultBehavior = ScrollBehavior();
late BuildContext capturedContext;
......@@ -75,14 +76,14 @@ void main() {
}, variant: TargetPlatformVariant.all());
// Regression test for https://github.com/flutter/flutter/issues/89681
testWidgets('_WrappedScrollBehavior shouldNotify test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('_WrappedScrollBehavior shouldNotify test', (WidgetTester tester) async {
final ScrollBehavior behavior1 = const ScrollBehavior().copyWith();
final ScrollBehavior behavior2 = const ScrollBehavior().copyWith();
expect(behavior1.shouldNotify(behavior2), false);
});
testWidgets('Inherited ScrollConfiguration changed', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Inherited ScrollConfiguration changed', (WidgetTester tester) async {
final GlobalKey key = GlobalKey(debugLabel: 'scrollable');
TestScrollBehavior? behavior;
late ScrollPositionWithSingleContext position;
......@@ -131,7 +132,7 @@ void main() {
expect(metrics.viewportDimension, equals(600.0));
});
testWidgets('ScrollBehavior default android overscroll indicator', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ScrollBehavior default android overscroll indicator', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -155,7 +156,7 @@ void main() {
}, variant: TargetPlatformVariant.only(TargetPlatform.android));
group('ScrollBehavior configuration is maintained over multiple copies', () {
testWidgets('dragDevices', (WidgetTester tester) async {
testWidgetsWithLeakTracking('dragDevices', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/91673
const ScrollBehavior defaultBehavior = ScrollBehavior();
expect(defaultBehavior.dragDevices, <PointerDeviceKind>{
......@@ -177,7 +178,7 @@ void main() {
expect(twiceCopiedBehavior.dragDevices, PointerDeviceKind.values.toSet());
});
testWidgets('physics', (WidgetTester tester) async {
testWidgetsWithLeakTracking('physics', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/91673
late ScrollPhysics defaultPhysics;
late ScrollPhysics onceCopiedPhysics;
......@@ -219,7 +220,7 @@ void main() {
expect(twiceCopiedPhysics, const BouncingScrollPhysics());
});
testWidgets('platform', (WidgetTester tester) async {
testWidgetsWithLeakTracking('platform', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/91673
late TargetPlatform defaultPlatform;
late TargetPlatform onceCopiedPlatform;
......@@ -276,7 +277,7 @@ void main() {
);
}
testWidgets('scrollbar', (WidgetTester tester) async {
testWidgetsWithLeakTracking('scrollbar', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/91673
const ScrollBehavior defaultBehavior = ScrollBehavior();
await tester.pumpWidget(wrap(defaultBehavior));
......@@ -296,7 +297,7 @@ void main() {
// For default scrollbars
}, variant: TargetPlatformVariant.desktop());
testWidgets('overscroll', (WidgetTester tester) async {
testWidgetsWithLeakTracking('overscroll', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/91673
const ScrollBehavior defaultBehavior = ScrollBehavior();
await tester.pumpWidget(wrap(defaultBehavior));
......
......@@ -11,8 +11,9 @@ import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'states.dart';
void main() {
testWidgets('ScrollController control test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ScrollController control test', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(
Directionality(
......@@ -77,6 +78,7 @@ void main() {
expect(realOffset(), equals(controller.offset));
final ScrollController controller2 = ScrollController();
addTearDown(controller2.dispose);
await tester.pumpWidget(
Directionality(
......@@ -132,10 +134,11 @@ void main() {
expect(realOffset(), equals(controller2.offset));
});
testWidgets('ScrollController control test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ScrollController control test', (WidgetTester tester) async {
final ScrollController controller = ScrollController(
initialScrollOffset: 209.0,
);
addTearDown(controller.dispose);
await tester.pumpWidget(
Directionality(
......@@ -177,8 +180,9 @@ void main() {
expect(realOffset(), equals(controller.offset));
});
testWidgets('DrivenScrollActivity ending after dispose', (WidgetTester tester) async {
testWidgetsWithLeakTracking('DrivenScrollActivity ending after dispose', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(
Directionality(
......@@ -198,14 +202,17 @@ void main() {
await tester.pumpWidget(Container(), const Duration(seconds: 2));
});
testWidgets('Read operations on ScrollControllers with no positions fail', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Read operations on ScrollControllers with no positions fail', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
expect(() => controller.offset, throwsAssertionError);
expect(() => controller.position, throwsAssertionError);
});
testWidgets('Read operations on ScrollControllers with more than one position fail', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Read operations on ScrollControllers with more than one position fail', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -238,14 +245,17 @@ void main() {
expect(() => controller.position, throwsAssertionError);
});
testWidgets('Write operations on ScrollControllers with no positions fail', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Write operations on ScrollControllers with no positions fail', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
expect(() => controller.animateTo(1.0, duration: const Duration(seconds: 1), curve: Curves.linear), throwsAssertionError);
expect(() => controller.jumpTo(1.0), throwsAssertionError);
});
testWidgets('Write operations on ScrollControllers with more than one position do not throw', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Write operations on ScrollControllers with more than one position do not throw', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -279,7 +289,7 @@ void main() {
await tester.pumpAndSettle();
});
testWidgets('Scroll controllers notify when the position changes', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scroll controllers notify when the position changes', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
final List<double> log = <double>[];
......@@ -313,7 +323,7 @@ void main() {
expect(log, isEmpty);
});
testWidgets('keepScrollOffset', (WidgetTester tester) async {
testWidgetsWithLeakTracking('keepScrollOffset', (WidgetTester tester) async {
final PageStorageBucket bucket = PageStorageBucket();
Widget buildFrame(ScrollController controller) {
......@@ -341,6 +351,7 @@ void main() {
// The initialScrollOffset is used in this case, because there's no saved
// scroll offset.
ScrollController controller = ScrollController(initialScrollOffset: 200.0);
addTearDown(controller.dispose);
await tester.pumpWidget(buildFrame(controller));
expect(tester.getTopLeft(find.widgetWithText(SizedBox, 'Item 2')), Offset.zero);
......@@ -351,6 +362,7 @@ void main() {
// The initialScrollOffset isn't used in this case, because the scrolloffset
// can be restored.
controller = ScrollController(initialScrollOffset: 25.0);
addTearDown(controller.dispose);
await tester.pumpWidget(buildFrame(controller));
expect(controller.offset, 2000.0);
expect(tester.getTopLeft(find.widgetWithText(SizedBox, 'Item 20')), Offset.zero);
......@@ -360,13 +372,14 @@ void main() {
// the initialScrollOffset is used.
controller = ScrollController(keepScrollOffset: false, initialScrollOffset: 100.0);
addTearDown(controller.dispose);
await tester.pumpWidget(buildFrame(controller));
expect(controller.offset, 100.0);
expect(tester.getTopLeft(find.widgetWithText(SizedBox, 'Item 1')), Offset.zero);
});
testWidgets('isScrollingNotifier works with pointer scroll', (WidgetTester tester) async {
testWidgetsWithLeakTracking('isScrollingNotifier works with pointer scroll', (WidgetTester tester) async {
Widget buildFrame(ScrollController controller) {
return Directionality(
textDirection: TextDirection.ltr,
......@@ -381,6 +394,7 @@ void main() {
bool isScrolling = false;
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
controller.addListener((){
isScrolling = controller.position.isScrollingNotifier.value;
});
......@@ -396,6 +410,6 @@ void main() {
});
test('$ScrollController dispatches object creation in constructor', () {
expect(()=> ScrollController().dispose(), dispatchesMemoryEvents(ScrollController));
expect(() => ScrollController().dispose(), dispatchesMemoryEvents(ScrollController));
});
}
......@@ -6,6 +6,7 @@ import 'dart:async';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
Widget _buildScroller({ required List<String> log }) {
return NotificationListener<ScrollNotification>(
......@@ -38,7 +39,7 @@ void main() {
scrollable.position.jumpTo(newScrollOffset);
}
testWidgets('Scroll event drag', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scroll event drag', (WidgetTester tester) async {
final List<String> log = <String>[];
await tester.pumpWidget(_buildScroller(log: log));
......@@ -57,7 +58,7 @@ void main() {
expect(log, equals(<String>['scroll-start', 'scroll-update', 'scroll-end']));
});
testWidgets('Scroll animateTo', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scroll animateTo', (WidgetTester tester) async {
final List<String> log = <String>[];
await tester.pumpWidget(_buildScroller(log: log));
......@@ -74,7 +75,7 @@ void main() {
expect(completer.isCompleted, isTrue);
});
testWidgets('Scroll jumpTo', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scroll jumpTo', (WidgetTester tester) async {
final List<String> log = <String>[];
await tester.pumpWidget(_buildScroller(log: log));
......@@ -85,7 +86,7 @@ void main() {
expect(log, equals(<String>['scroll-start', 'scroll-update', 'scroll-end']));
});
testWidgets('Scroll jumpTo during animation', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scroll jumpTo during animation', (WidgetTester tester) async {
final List<String> log = <String>[];
await tester.pumpWidget(_buildScroller(log: log));
......@@ -110,7 +111,7 @@ void main() {
expect(completer.isCompleted, isTrue);
});
testWidgets('Scroll scrollTo during animation', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scroll scrollTo during animation', (WidgetTester tester) async {
final List<String> log = <String>[];
await tester.pumpWidget(_buildScroller(log: log));
......@@ -134,7 +135,7 @@ void main() {
expect(completer.isCompleted, isTrue);
});
testWidgets('fling, fling generates two start/end pairs', (WidgetTester tester) async {
testWidgetsWithLeakTracking('fling, fling generates two start/end pairs', (WidgetTester tester) async {
final List<String> log = <String>[];
await tester.pumpWidget(_buildScroller(log: log));
......@@ -157,7 +158,7 @@ void main() {
expect(log, equals(<String>['scroll-start', 'scroll-end', 'scroll-start', 'scroll-end']));
});
testWidgets('fling, pause, fling generates two start/end pairs', (WidgetTester tester) async {
testWidgetsWithLeakTracking('fling, pause, fling generates two start/end pairs', (WidgetTester tester) async {
final List<String> log = <String>[];
await tester.pumpWidget(_buildScroller(log: log));
......@@ -176,7 +177,7 @@ void main() {
expect(log, equals(<String>['scroll-start', 'scroll-end', 'scroll-start', 'scroll-end']));
});
testWidgets('fling up ends', (WidgetTester tester) async {
testWidgetsWithLeakTracking('fling up ends', (WidgetTester tester) async {
final List<String> log = <String>[];
await tester.pumpWidget(_buildScroller(log: log));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment