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)),
......
......@@ -6,11 +6,12 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'semantics_tester.dart';
void main() {
testWidgets('SliverReorderableList works well when having gestureSettings', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverReorderableList works well when having gestureSettings', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/103404
const int itemCount = 5;
int onReorderCallCount = 0;
......@@ -67,7 +68,7 @@ void main() {
expect(items, orderedEquals(<int>[1, 0, 2, 3, 4]));
});
testWidgets('SliverReorderableList item has correct semantics', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverReorderableList item has correct semantics', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
const int itemCount = 5;
int onReorderCallCount = 0;
......@@ -127,7 +128,7 @@ void main() {
semantics.dispose();
});
testWidgets('SliverReorderableList custom semantics action has correct label', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverReorderableList custom semantics action has correct label', (WidgetTester tester) async {
const int itemCount = 5;
final List<int> items = List<int>.generate(itemCount, (int index) => index);
// The list has five elements of height 100
......@@ -166,7 +167,7 @@ void main() {
});
// Regression test for https://github.com/flutter/flutter/issues/100451
testWidgets('SliverReorderableList.builder respects findChildIndexCallback', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverReorderableList.builder respects findChildIndexCallback', (WidgetTester tester) async {
bool finderCalled = false;
int itemCount = 7;
late StateSetter stateSetter;
......@@ -206,7 +207,7 @@ void main() {
});
// Regression test for https://github.com/flutter/flutter/issues/88191
testWidgets('Do not crash when dragging with two fingers simultaneously', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Do not crash when dragging with two fingers simultaneously', (WidgetTester tester) async {
final List<int> items = List<int>.generate(3, (int index) => index);
void handleReorder(int fromIndex, int toIndex) {
if (toIndex > fromIndex) {
......@@ -252,7 +253,7 @@ void main() {
expect(tester.takeException(), isNull);
});
testWidgets('negative itemCount should assert', (WidgetTester tester) async {
testWidgetsWithLeakTracking('negative itemCount should assert', (WidgetTester tester) async {
final List<int> items = <int>[1, 2, 3];
await tester.pumpWidget(MaterialApp(
home: StatefulBuilder(
......@@ -284,7 +285,7 @@ void main() {
expect(tester.takeException(), isA<AssertionError>());
});
testWidgets('zero itemCount should not build widget', (WidgetTester tester) async {
testWidgetsWithLeakTracking('zero itemCount should not build widget', (WidgetTester tester) async {
final List<int> items = <int>[1, 2, 3];
await tester.pumpWidget(MaterialApp(
home: StatefulBuilder(
......@@ -331,7 +332,7 @@ void main() {
expect(find.text('after'), findsOneWidget);
});
testWidgets('SliverReorderableList, drag and drop, fixed height items', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverReorderableList, drag and drop, fixed height items', (WidgetTester tester) async {
final List<int> items = List<int>.generate(8, (int index) => index);
Future<void> pressDragRelease(Offset start, Offset delta) async {
......@@ -397,7 +398,7 @@ void main() {
expect(items, orderedEquals(<int>[0, 1, 2, 3, 4, 5, 6, 7]));
});
testWidgets('SliverReorderableList, items inherit DefaultTextStyle, IconTheme', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverReorderableList, items inherit DefaultTextStyle, IconTheme', (WidgetTester tester) async {
const Color textColor = Color(0xffffffff);
const Color iconColor = Color(0xff0000ff);
......@@ -450,7 +451,7 @@ void main() {
expect(getTextStyle().color, textColor);
});
testWidgets('SliverReorderableList - custom proxyDecorator', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverReorderableList - custom proxyDecorator', (WidgetTester tester) async {
const ValueKey<String> fadeTransitionKey = ValueKey<String>('reordered-fade');
await tester.pumpWidget(
......@@ -513,7 +514,7 @@ void main() {
expect(getItemFadeTransition(), findsNothing);
});
testWidgets('ReorderableList supports items with nested list views without throwing layout exception.', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ReorderableList supports items with nested list views without throwing layout exception.', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
builder: (BuildContext context, Widget? child) {
......@@ -567,7 +568,7 @@ void main() {
expect(tester.takeException(), isNull);
});
testWidgets('ReorderableList supports items with nested list views without throwing layout exception.', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ReorderableList supports items with nested list views without throwing layout exception.', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/83224.
await tester.pumpWidget(
MaterialApp(
......@@ -622,7 +623,7 @@ void main() {
expect(tester.takeException(), isNull);
});
testWidgets('SliverReorderableList - properly animates the drop in a reversed list', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverReorderableList - properly animates the drop in a reversed list', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/110949
final List<int> items = List<int>.generate(8, (int index) => index);
......@@ -673,7 +674,7 @@ void main() {
expect(tester.getTopLeft(find.text('item 0')), const Offset(0, 400));
});
testWidgets('SliverReorderableList - properly animates the drop at starting position in a reversed list', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverReorderableList - properly animates the drop at starting position in a reversed list', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/84625
final List<int> items = List<int>.generate(8, (int index) => index);
......@@ -716,7 +717,7 @@ void main() {
expect(tester.getTopLeft(find.text('item 0')), const Offset(0, 500));
});
testWidgets('SliverReorderableList calls onReorderStart and onReorderEnd correctly', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverReorderableList calls onReorderStart and onReorderEnd correctly', (WidgetTester tester) async {
final List<int> items = List<int>.generate(8, (int index) => index);
int? startIndex, endIndex;
final Finder item0 = find.textContaining('item 0');
......@@ -767,7 +768,7 @@ void main() {
expect(endIndex, equals(0));
});
testWidgets('ReorderableList calls onReorderStart and onReorderEnd correctly', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ReorderableList calls onReorderStart and onReorderEnd correctly', (WidgetTester tester) async {
final List<int> items = List<int>.generate(8, (int index) => index);
int? startIndex, endIndex;
final Finder item0 = find.textContaining('item 0');
......@@ -840,7 +841,7 @@ void main() {
testWidgets('ReorderableList asserts on both non-null itemExtent and prototypeItem', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ReorderableList asserts on both non-null itemExtent and prototypeItem', (WidgetTester tester) async {
final List<int> numbers = <int>[0,1,2];
expect(() => ReorderableList(
itemBuilder: (BuildContext context, int index) {
......@@ -860,7 +861,7 @@ void main() {
), throwsAssertionError);
});
testWidgets('SliverReorderableList asserts on both non-null itemExtent and prototypeItem', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverReorderableList asserts on both non-null itemExtent and prototypeItem', (WidgetTester tester) async {
final List<int> numbers = <int>[0,1,2];
expect(() => SliverReorderableList(
itemBuilder: (BuildContext context, int index) {
......@@ -880,7 +881,7 @@ void main() {
), throwsAssertionError);
});
testWidgets('if itemExtent is non-null, children have same extent in the scroll direction', (WidgetTester tester) async {
testWidgetsWithLeakTracking('if itemExtent is non-null, children have same extent in the scroll direction', (WidgetTester tester) async {
final List<int> numbers = <int>[0,1,2];
await tester.pumpWidget(
......@@ -925,7 +926,7 @@ void main() {
expect(item2Height, 30.0);
});
testWidgets('if prototypeItem is non-null, children have same extent in the scroll direction', (WidgetTester tester) async {
testWidgetsWithLeakTracking('if prototypeItem is non-null, children have same extent in the scroll direction', (WidgetTester tester) async {
final List<int> numbers = <int>[0,1,2];
await tester.pumpWidget(
......@@ -968,7 +969,7 @@ void main() {
});
group('ReorderableDragStartListener', () {
testWidgets('It should allow the item to be dragged when enabled is true', (WidgetTester tester) async {
testWidgetsWithLeakTracking('It should allow the item to be dragged when enabled is true', (WidgetTester tester) async {
const int itemCount = 5;
int onReorderCallCount = 0;
final List<int> items = List<int>.generate(itemCount, (int index) => index);
......@@ -1014,7 +1015,7 @@ void main() {
expect(items, orderedEquals(<int>[1, 0, 2, 3, 4]));
});
testWidgets('It should not allow the item to be dragged when enabled is false', (WidgetTester tester) async {
testWidgetsWithLeakTracking('It should not allow the item to be dragged when enabled is false', (WidgetTester tester) async {
const int itemCount = 5;
int onReorderCallCount = 0;
final List<int> items = List<int>.generate(itemCount, (int index) => index);
......@@ -1063,7 +1064,7 @@ void main() {
});
group('ReorderableDelayedDragStartListener', () {
testWidgets('It should allow the item to be dragged when enabled is true', (WidgetTester tester) async {
testWidgetsWithLeakTracking('It should allow the item to be dragged when enabled is true', (WidgetTester tester) async {
const int itemCount = 5;
int onReorderCallCount = 0;
final List<int> items = List<int>.generate(itemCount, (int index) => index);
......@@ -1110,7 +1111,7 @@ void main() {
expect(items, orderedEquals(<int>[1, 0, 2, 3, 4]));
});
testWidgets('It should not allow the item to be dragged when enabled is false', (WidgetTester tester) async {
testWidgetsWithLeakTracking('It should not allow the item to be dragged when enabled is false', (WidgetTester tester) async {
const int itemCount = 5;
int onReorderCallCount = 0;
final List<int> items = List<int>.generate(itemCount, (int index) => index);
......@@ -1158,7 +1159,7 @@ void main() {
});
});
testWidgets('SliverReorderableList properly disposes items', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverReorderableList properly disposes items', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/105010
const int itemCount = 5;
final List<int> items = List<int>.generate(itemCount, (int index) => index);
......@@ -1225,7 +1226,7 @@ void main() {
expect(item0, findsNothing);
});
testWidgets('SliverReorderableList auto scrolls speed is configurable', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SliverReorderableList auto scrolls speed is configurable', (WidgetTester tester) async {
Future<void> pumpFor({
required Duration duration,
Duration interval = const Duration(milliseconds: 50),
......@@ -1243,6 +1244,7 @@ void main() {
Future<double> pumpListAndDrag({required double autoScrollerVelocityScalar}) async {
final List<int> items = List<int>.generate(10, (int index) => index);
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
MaterialApp(
......@@ -1310,7 +1312,7 @@ void main() {
expect(offsetForFastScroller / offsetForSlowScroller, fastVelocityScalar / slowVelocityScalar);
});
testWidgets('Null check error when dragging and dropping last element into last index with reverse:true', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Null check error when dragging and dropping last element into last index with reverse:true', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/132077
const int itemCount = 5;
final List<String> items = List<String>.generate(itemCount, (int index) => 'Item ${index+1}');
......
......@@ -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;
......
......@@ -7,30 +7,62 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() {
testWidgets('value is not accessible when not registered', (WidgetTester tester) async {
expect(() => RestorableNum<num>(0).value, throwsAssertionError);
expect(() => RestorableDouble(1.0).value, throwsAssertionError);
expect(() => RestorableInt(1).value, throwsAssertionError);
expect(() => RestorableString('hello').value, throwsAssertionError);
expect(() => RestorableBool(true).value, throwsAssertionError);
expect(() => RestorableNumN<num?>(0).value, throwsAssertionError);
expect(() => RestorableDoubleN(1.0).value, throwsAssertionError);
expect(() => RestorableIntN(1).value, throwsAssertionError);
expect(() => RestorableStringN('hello').value, throwsAssertionError);
expect(() => RestorableBoolN(true).value, throwsAssertionError);
expect(() => RestorableTextEditingController().value, throwsAssertionError);
expect(() => RestorableDateTime(DateTime(2020, 4, 3)).value, throwsAssertionError);
expect(() => RestorableDateTimeN(DateTime(2020, 4, 3)).value, throwsAssertionError);
expect(() => RestorableEnumN<TestEnum>(TestEnum.one, values: TestEnum.values).value, throwsAssertionError);
expect(() => RestorableEnum<TestEnum>(TestEnum.one, values: TestEnum.values).value, throwsAssertionError);
expect(() => _TestRestorableValue().value, throwsAssertionError);
testWidgetsWithLeakTracking('value is not accessible when not registered', (WidgetTester tester) async {
final RestorableNum<num> numValue = RestorableNum<num>(0);
addTearDown(numValue.dispose);
expect(() => numValue.value, throwsAssertionError);
final RestorableDouble doubleValue = RestorableDouble(1.0);
addTearDown(doubleValue.dispose);
expect(() => doubleValue.value, throwsAssertionError);
final RestorableInt intValue = RestorableInt(1);
addTearDown(intValue.dispose);
expect(() => intValue.value, throwsAssertionError);
final RestorableString stringValue = RestorableString('hello');
addTearDown(stringValue.dispose);
expect(() => stringValue.value, throwsAssertionError);
final RestorableBool boolValue = RestorableBool(true);
addTearDown(boolValue.dispose);
expect(() => boolValue.value, throwsAssertionError);
final RestorableNumN<num?> nullableNumValue = RestorableNumN<num?>(0);
addTearDown(nullableNumValue.dispose);
expect(() => nullableNumValue.value, throwsAssertionError);
final RestorableDoubleN nullableDoubleValue = RestorableDoubleN(1.0);
addTearDown(nullableDoubleValue.dispose);
expect(() => nullableDoubleValue.value, throwsAssertionError);
final RestorableIntN nullableIntValue = RestorableIntN(1);
addTearDown(nullableIntValue.dispose);
expect(() => nullableIntValue.value, throwsAssertionError);
final RestorableStringN nullableStringValue = RestorableStringN('hello');
addTearDown(nullableStringValue.dispose);
expect(() => nullableStringValue.value, throwsAssertionError);
final RestorableBoolN nullableBoolValue = RestorableBoolN(true);
addTearDown(nullableBoolValue.dispose);
expect(() => nullableBoolValue.value, throwsAssertionError);
final RestorableTextEditingController controllerValue = RestorableTextEditingController();
addTearDown(controllerValue.dispose);
expect(() => controllerValue.value, throwsAssertionError);
final RestorableDateTime dateTimeValue = RestorableDateTime(DateTime(2020, 4, 3));
addTearDown(dateTimeValue.dispose);
expect(() => dateTimeValue.value, throwsAssertionError);
final RestorableDateTimeN nullableDateTimeValue = RestorableDateTimeN(DateTime(2020, 4, 3));
addTearDown(nullableDateTimeValue.dispose);
expect(() => nullableDateTimeValue.value, throwsAssertionError);
final RestorableEnumN<TestEnum> nullableEnumValue = RestorableEnumN<TestEnum>(TestEnum.one, values: TestEnum.values);
addTearDown(nullableEnumValue.dispose);
expect(() => nullableEnumValue.value, throwsAssertionError);
final RestorableEnum<TestEnum> enumValue = RestorableEnum<TestEnum>(TestEnum.one, values: TestEnum.values);
addTearDown(enumValue.dispose);
expect(() => enumValue.value, throwsAssertionError);
final _TestRestorableValue objectValue = _TestRestorableValue();
addTearDown(objectValue.dispose);
expect(() => objectValue.value, throwsAssertionError);
});
testWidgetsWithLeakTracking('$RestorableProperty dispatches creation in constructor', (WidgetTester widgetTester) async {
expect(()=> RestorableDateTimeN(null).dispose(), dispatchesMemoryEvents(RestorableDateTimeN));
expect(() => RestorableDateTimeN(null).dispose(), dispatchesMemoryEvents(RestorableDateTimeN));
});
testWidgets('work when not in restoration scope', (WidgetTester tester) async {
testWidgetsWithLeakTracking('work when not in restoration scope', (WidgetTester tester) async {
await tester.pumpWidget(const _RestorableWidget());
expect(find.text('hello world'), findsOneWidget);
......@@ -94,7 +126,7 @@ void main() {
expect(find.text('guten tag'), findsOneWidget);
});
testWidgets('restart and restore', (WidgetTester tester) async {
testWidgetsWithLeakTracking('restart and restore', (WidgetTester tester) async {
await tester.pumpWidget(const RootRestorationScope(
restorationId: 'root-child',
child: _RestorableWidget(),
......@@ -185,7 +217,7 @@ void main() {
expect(find.text('guten tag'), findsOneWidget);
});
testWidgets('restore to older state', (WidgetTester tester) async {
testWidgetsWithLeakTracking('restore to older state', (WidgetTester tester) async {
await tester.pumpWidget(const RootRestorationScope(
restorationId: 'root-child',
child: _RestorableWidget(),
......@@ -283,7 +315,7 @@ void main() {
expect(find.text('hello world'), findsOneWidget);
});
testWidgets('call notifiers when value changes', (WidgetTester tester) async {
testWidgetsWithLeakTracking('call notifiers when value changes', (WidgetTester tester) async {
await tester.pumpWidget(const RootRestorationScope(
restorationId: 'root-child',
child: _RestorableWidget(),
......@@ -465,7 +497,7 @@ void main() {
expect(notifyLog, isEmpty);
});
testWidgets('RestorableValue calls didUpdateValue', (WidgetTester tester) async {
testWidgetsWithLeakTracking('RestorableValue calls didUpdateValue', (WidgetTester tester) async {
await tester.pumpWidget(const RootRestorationScope(
restorationId: 'root-child',
child: _RestorableWidget(),
......@@ -489,7 +521,7 @@ void main() {
expect(state.objectValue.didUpdateValueCallCount, 1);
});
testWidgets('RestorableEnum and RestorableEnumN assert if default value is not in enum', (WidgetTester tester) async {
testWidgetsWithLeakTracking('RestorableEnum and RestorableEnumN assert if default value is not in enum', (WidgetTester tester) async {
expect(() => RestorableEnum<TestEnum>(
TestEnum.four,
values: TestEnum.values.toSet().difference(<TestEnum>{TestEnum.four})), throwsAssertionError);
......@@ -498,33 +530,37 @@ void main() {
values: TestEnum.values.toSet().difference(<TestEnum>{TestEnum.four})), throwsAssertionError);
});
testWidgets('RestorableEnum and RestorableEnumN assert if unknown values are set', (WidgetTester tester) async {
testWidgetsWithLeakTracking('RestorableEnum and RestorableEnumN assert if unknown values are set', (WidgetTester tester) async {
final RestorableEnum<TestEnum> enumMissingValue = RestorableEnum<TestEnum>(
TestEnum.one,
values: TestEnum.values.toSet().difference(<TestEnum>{TestEnum.four}),
);
addTearDown(enumMissingValue.dispose);
expect(() => enumMissingValue.value = TestEnum.four, throwsAssertionError);
final RestorableEnumN<TestEnum> nullableEnumMissingValue = RestorableEnumN<TestEnum>(
null,
values: TestEnum.values.toSet().difference(<TestEnum>{TestEnum.four}),
);
addTearDown(nullableEnumMissingValue.dispose);
expect(() => nullableEnumMissingValue.value = TestEnum.four, throwsAssertionError);
});
testWidgets('RestorableEnum and RestorableEnumN assert if unknown values are restored', (WidgetTester tester) async {
testWidgetsWithLeakTracking('RestorableEnum and RestorableEnumN assert if unknown values are restored', (WidgetTester tester) async {
final RestorableEnum<TestEnum> enumMissingValue = RestorableEnum<TestEnum>(
TestEnum.one,
values: TestEnum.values.toSet().difference(<TestEnum>{TestEnum.four}),
);
addTearDown(enumMissingValue.dispose);
expect(() => enumMissingValue.fromPrimitives('four'), throwsAssertionError);
final RestorableEnumN<TestEnum> nullableEnumMissingValue = RestorableEnumN<TestEnum>(
null,
values: TestEnum.values.toSet().difference(<TestEnum>{TestEnum.four}),
);
addTearDown(nullableEnumMissingValue.dispose);
expect(() => nullableEnumMissingValue.fromPrimitives('four'), throwsAssertionError);
});
testWidgets('RestorableN types are properly defined', (WidgetTester tester) async {
testWidgetsWithLeakTracking('RestorableN types are properly defined', (WidgetTester tester) async {
await tester.pumpWidget(const RootRestorationScope(
restorationId: 'root-child',
child: _RestorableWidget(),
......@@ -631,6 +667,27 @@ class _RestorableWidgetState extends State<_RestorableWidget> with RestorationMi
registerForRestoration(objectValue, 'object');
}
@override
void dispose() {
numValue.dispose();
doubleValue.dispose();
intValue.dispose();
stringValue.dispose();
boolValue.dispose();
dateTimeValue.dispose();
enumValue.dispose();
nullableNumValue.dispose();
nullableDoubleValue.dispose();
nullableIntValue.dispose();
nullableStringValue.dispose();
nullableBoolValue.dispose();
nullableDateTimeValue.dispose();
nullableEnumValue.dispose();
controllerValue.dispose();
objectValue.dispose();
super.dispose();
}
void setProperties(VoidCallback callback) {
setState(callback);
}
......
......@@ -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);
......
......@@ -8,6 +8,7 @@ import 'dart:ui';
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 'semantics_tester.dart';
......@@ -89,6 +90,9 @@ class TestRoute extends Route<String?> with LocalHistoryRoute<String?> {
@override
void dispose() {
log('dispose');
for (final OverlayEntry e in _entries) {
e.dispose();
}
_entries.clear();
routes.remove(this);
super.dispose();
......@@ -113,12 +117,12 @@ Future<void> runNavigatorTest(
}
void main() {
testWidgets('Route settings', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Route settings', (WidgetTester tester) async {
const RouteSettings settings = RouteSettings(name: 'A');
expect(settings, hasOneLineDescription);
});
testWidgets('Route settings arguments', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Route settings arguments', (WidgetTester tester) async {
const RouteSettings settings = RouteSettings(name: 'A');
expect(settings.arguments, isNull);
......@@ -127,7 +131,7 @@ void main() {
expect(settings2.arguments, same(arguments));
});
testWidgets('Route management - push, replace, pop sequence', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Route management - push, replace, pop sequence', (WidgetTester tester) async {
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
await tester.pumpWidget(
Directionality(
......@@ -214,7 +218,7 @@ void main() {
results.clear();
});
testWidgets('Route management - push, remove, pop', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Route management - push, remove, pop', (WidgetTester tester) async {
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
await tester.pumpWidget(
Directionality(
......@@ -329,7 +333,7 @@ void main() {
results.clear();
});
testWidgets('Route management - push, replace, popUntil', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Route management - push, replace, popUntil', (WidgetTester tester) async {
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
await tester.pumpWidget(
Directionality(
......@@ -406,7 +410,7 @@ void main() {
results.clear();
});
testWidgets('Route localHistory - popUntil', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Route localHistory - popUntil', (WidgetTester tester) async {
final TestRoute routeA = TestRoute('A');
routeA.addLocalHistoryEntry(LocalHistoryEntry(
onRemove: () { routeA.log('onRemove 0'); },
......@@ -543,7 +547,7 @@ void main() {
});
});
testWidgets('Can autofocus a TextField nested in a Focus in a route.', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Can autofocus a TextField nested in a Focus in a route.', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController();
final FocusNode focusNode = FocusNode(debugLabel: 'Test Node');
......@@ -573,7 +577,7 @@ void main() {
});
group('PageRouteBuilder', () {
testWidgets('reverseTransitionDuration defaults to 300ms', (WidgetTester tester) async {
testWidgetsWithLeakTracking('reverseTransitionDuration defaults to 300ms', (WidgetTester tester) async {
// Default PageRouteBuilder reverse transition duration should be 300ms.
await tester.pumpWidget(
MaterialApp(
......@@ -624,7 +628,7 @@ void main() {
expect(find.text('Open page'), findsOneWidget);
});
testWidgets('reverseTransitionDuration can be customized', (WidgetTester tester) async {
testWidgetsWithLeakTracking('reverseTransitionDuration can be customized', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
onGenerateRoute: (RouteSettings settings) {
return MaterialPageRoute<dynamic>(
......@@ -676,7 +680,7 @@ void main() {
});
group('TransitionRoute', () {
testWidgets('secondary animation is kDismissed when next route finishes pop', (WidgetTester tester) async {
testWidgetsWithLeakTracking('secondary animation is kDismissed when next route finishes pop', (WidgetTester tester) async {
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
await tester.pumpWidget(
MaterialApp(
......@@ -734,7 +738,7 @@ void main() {
expect(secondaryAnimationPageOne.parent, kAlwaysDismissedAnimation);
});
testWidgets('secondary animation is kDismissed when next route is removed', (WidgetTester tester) async {
testWidgetsWithLeakTracking('secondary animation is kDismissed when next route is removed', (WidgetTester tester) async {
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
await tester.pumpWidget(
MaterialApp(
......@@ -789,7 +793,7 @@ void main() {
expect(secondaryAnimationPageOne.parent, kAlwaysDismissedAnimation);
});
testWidgets('secondary animation is kDismissed after train hopping finishes and pop', (WidgetTester tester) async {
testWidgetsWithLeakTracking('secondary animation is kDismissed after train hopping finishes and pop', (WidgetTester tester) async {
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
await tester.pumpWidget(
MaterialApp(
......@@ -861,7 +865,7 @@ void main() {
expect(secondaryAnimationPageOne.parent, kAlwaysDismissedAnimation);
});
testWidgets('secondary animation is kDismissed when train hopping is interrupted', (WidgetTester tester) async {
testWidgetsWithLeakTracking('secondary animation is kDismissed when train hopping is interrupted', (WidgetTester tester) async {
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
await tester.pumpWidget(
MaterialApp(
......@@ -930,7 +934,7 @@ void main() {
expect(trainHopper2.currentTrain, isNull); // Has been disposed.
});
testWidgets('secondary animation is triggered when pop initial route', (WidgetTester tester) async {
testWidgetsWithLeakTracking('secondary animation is triggered when pop initial route', (WidgetTester tester) async {
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
late Animation<double> secondaryAnimationOfRouteOne;
late Animation<double> primaryAnimationOfRouteTwo;
......@@ -968,7 +972,7 @@ void main() {
expect(secondaryAnimationOfRouteOne.value, primaryAnimationOfRouteTwo.value);
});
testWidgets('showGeneralDialog handles transparent barrier color', (WidgetTester tester) async {
testWidgetsWithLeakTracking('showGeneralDialog handles transparent barrier color', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Builder(
builder: (BuildContext context) {
......@@ -1002,7 +1006,7 @@ void main() {
expect(find.byType(ModalBarrier), findsNWidgets(1));
});
testWidgets('showGeneralDialog adds non-dismissible barrier when barrierDismissible is false', (WidgetTester tester) async {
testWidgetsWithLeakTracking('showGeneralDialog adds non-dismissible barrier when barrierDismissible is false', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Builder(
builder: (BuildContext context) {
......@@ -1037,7 +1041,7 @@ void main() {
expect(find.byType(ModalBarrier), findsNWidgets(1));
});
testWidgets('showGeneralDialog uses null as a barrierLabel by default', (WidgetTester tester) async {
testWidgetsWithLeakTracking('showGeneralDialog uses null as a barrierLabel by default', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Builder(
builder: (BuildContext context) {
......@@ -1072,7 +1076,7 @@ void main() {
expect(find.byType(ModalBarrier), findsNWidgets(1));
});
testWidgets('showGeneralDialog uses root navigator by default', (WidgetTester tester) async {
testWidgetsWithLeakTracking('showGeneralDialog uses root navigator by default', (WidgetTester tester) async {
final DialogObserver rootObserver = DialogObserver();
final DialogObserver nestedObserver = DialogObserver();
......@@ -1108,7 +1112,7 @@ void main() {
expect(nestedObserver.dialogCount, 0);
});
testWidgets('showGeneralDialog uses nested navigator if useRootNavigator is false', (WidgetTester tester) async {
testWidgetsWithLeakTracking('showGeneralDialog uses nested navigator if useRootNavigator is false', (WidgetTester tester) async {
final DialogObserver rootObserver = DialogObserver();
final DialogObserver nestedObserver = DialogObserver();
......@@ -1145,7 +1149,7 @@ void main() {
expect(nestedObserver.dialogCount, 1);
});
testWidgets('showGeneralDialog default argument values', (WidgetTester tester) async {
testWidgetsWithLeakTracking('showGeneralDialog default argument values', (WidgetTester tester) async {
final DialogObserver rootObserver = DialogObserver();
await tester.pumpWidget(MaterialApp(
......@@ -1181,7 +1185,7 @@ void main() {
});
group('showGeneralDialog avoids overlapping display features', () {
testWidgets('positioning with anchorPoint', (WidgetTester tester) async {
testWidgetsWithLeakTracking('positioning with anchorPoint', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
builder: (BuildContext context, Widget? child) {
......@@ -1219,7 +1223,7 @@ void main() {
expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(800.0, 600.0));
});
testWidgets('positioning with Directionality', (WidgetTester tester) async {
testWidgetsWithLeakTracking('positioning with Directionality', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
builder: (BuildContext context, Widget? child) {
......@@ -1259,7 +1263,7 @@ void main() {
expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(800.0, 600.0));
});
testWidgets('positioning by default', (WidgetTester tester) async {
testWidgetsWithLeakTracking('positioning by default', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
builder: (BuildContext context, Widget? child) {
......@@ -1297,7 +1301,7 @@ void main() {
});
});
testWidgets('reverseTransitionDuration defaults to transitionDuration', (WidgetTester tester) async {
testWidgetsWithLeakTracking('reverseTransitionDuration defaults to transitionDuration', (WidgetTester tester) async {
final GlobalKey containerKey = GlobalKey();
// Default MaterialPageRoute transition duration should be 300ms.
......@@ -1349,7 +1353,7 @@ void main() {
expect(find.byKey(containerKey), findsNothing);
});
testWidgets('reverseTransitionDuration can be customized', (WidgetTester tester) async {
testWidgetsWithLeakTracking('reverseTransitionDuration can be customized', (WidgetTester tester) async {
final GlobalKey containerKey = GlobalKey();
await tester.pumpWidget(MaterialApp(
onGenerateRoute: (RouteSettings settings) {
......@@ -1401,7 +1405,7 @@ void main() {
expect(find.byKey(containerKey), findsNothing);
});
testWidgets('custom reverseTransitionDuration does not result in interrupted animations', (WidgetTester tester) async {
testWidgetsWithLeakTracking('custom reverseTransitionDuration does not result in interrupted animations', (WidgetTester tester) async {
final GlobalKey containerKey = GlobalKey();
await tester.pumpWidget(MaterialApp(
theme: ThemeData(
......@@ -1469,7 +1473,7 @@ void main() {
});
group('ModalRoute', () {
testWidgets('default barrierCurve', (WidgetTester tester) async {
testWidgetsWithLeakTracking('default barrierCurve', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Material(
child: Builder(
......@@ -1531,7 +1535,7 @@ void main() {
expect(modalBarrierAnimation.value, Colors.black);
});
testWidgets('custom barrierCurve', (WidgetTester tester) async {
testWidgetsWithLeakTracking('custom barrierCurve', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Material(
child: Builder(
......@@ -1594,7 +1598,7 @@ void main() {
expect(modalBarrierAnimation.value, Colors.black);
});
testWidgets('white barrierColor', (WidgetTester tester) async {
testWidgetsWithLeakTracking('white barrierColor', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Material(
child: Builder(
......@@ -1657,7 +1661,7 @@ void main() {
expect(modalBarrierAnimation.value, Colors.white);
});
testWidgets('modal route semantics order', (WidgetTester tester) async {
testWidgetsWithLeakTracking('modal route semantics order', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/46625.
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(MaterialApp(
......@@ -1730,7 +1734,7 @@ void main() {
semantics.dispose();
}, variant: const TargetPlatformVariant(<TargetPlatform>{TargetPlatform.iOS}));
testWidgets('focus traverse correct when pop multiple page simultaneously', (WidgetTester tester) async {
testWidgetsWithLeakTracking('focus traverse correct when pop multiple page simultaneously', (WidgetTester tester) async {
// Regression test: https://github.com/flutter/flutter/issues/48903
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
await tester.pumpWidget(MaterialApp(
......@@ -1776,7 +1780,7 @@ void main() {
expect(focusNodeOnPageOne.hasFocus, isTrue);
});
testWidgets('focus traversal is correct when popping multiple pages simultaneously - with focused children', (WidgetTester tester) async {
testWidgetsWithLeakTracking('focus traversal is correct when popping multiple pages simultaneously - with focused children', (WidgetTester tester) async {
// Regression test: https://github.com/flutter/flutter/issues/48903
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
await tester.pumpWidget(MaterialApp(
......@@ -1828,7 +1832,7 @@ void main() {
expect(focusNodeOnPageOne.hasFocus, isTrue);
});
testWidgets('child with local history can be disposed', (WidgetTester tester) async {
testWidgetsWithLeakTracking('child with local history can be disposed', (WidgetTester tester) async {
// Regression test: https://github.com/flutter/flutter/issues/52478
await tester.pumpWidget(const MaterialApp(
home: WidgetWithLocalHistory(),
......@@ -1849,7 +1853,7 @@ void main() {
expect(tester.takeException(), null);
});
testWidgets('child with no local history can be disposed', (WidgetTester tester) async {
testWidgetsWithLeakTracking('child with no local history can be disposed', (WidgetTester tester) async {
await tester.pumpWidget(const MaterialApp(
home: WidgetWithNoLocalHistory(),
));
......@@ -1869,7 +1873,7 @@ void main() {
});
});
testWidgets('can be dismissed with escape keyboard shortcut', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can be dismissed with escape keyboard shortcut', (WidgetTester tester) async {
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
await tester.pumpWidget(MaterialApp(
navigatorKey: navigatorKey,
......@@ -1891,7 +1895,7 @@ void main() {
expect(find.text('dialog1'), findsNothing);
});
testWidgets('can not be dismissed with escape keyboard shortcut if barrier not dismissible', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can not be dismissed with escape keyboard shortcut if barrier not dismissible', (WidgetTester tester) async {
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
await tester.pumpWidget(MaterialApp(
navigatorKey: navigatorKey,
......@@ -1914,7 +1918,7 @@ void main() {
expect(find.text('dialog1'), findsOneWidget);
});
testWidgets('ModalRoute.of works for void routes', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ModalRoute.of works for void routes', (WidgetTester tester) async {
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
await tester.pumpWidget(MaterialApp(
navigatorKey: navigatorKey,
......@@ -1936,7 +1940,7 @@ void main() {
expect(parentRoute, isA<MaterialPageRoute<void>>());
});
testWidgets('RawDialogRoute is state restorable', (WidgetTester tester) async {
testWidgetsWithLeakTracking('RawDialogRoute is state restorable', (WidgetTester tester) async {
await tester.pumpWidget(
const MaterialApp(
restorationScopeId: 'app',
......
......@@ -6,6 +6,7 @@ import 'package:flutter/foundation.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';
class OrderPainter extends CustomPainter {
const OrderPainter(this.index);
......@@ -28,7 +29,7 @@ Widget log(int index) => CustomPaint(painter: OrderPainter(index));
void main() {
// NO DIRECTION
testWidgets('Row with one Flexible child - no textDirection', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row with one Flexible child - no textDirection', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('row');
const Key child0Key = Key('child0');
......@@ -59,7 +60,7 @@ void main() {
expect(OrderPainter.log, <int>[]);
});
testWidgets('Row with default main axis parameters - no textDirection', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row with default main axis parameters - no textDirection', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('row');
const Key child0Key = Key('child0');
......@@ -90,7 +91,7 @@ void main() {
expect(OrderPainter.log, <int>[]);
});
testWidgets('Row with MainAxisAlignment.center - no textDirection', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row with MainAxisAlignment.center - no textDirection', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('row');
const Key child0Key = Key('child0');
......@@ -120,7 +121,7 @@ void main() {
expect(OrderPainter.log, <int>[]);
});
testWidgets('Row with MainAxisAlignment.end - no textDirection', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row with MainAxisAlignment.end - no textDirection', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('row');
const Key child0Key = Key('child0');
......@@ -152,7 +153,7 @@ void main() {
expect(OrderPainter.log, <int>[]);
});
testWidgets('Row with MainAxisAlignment.spaceBetween - no textDirection', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row with MainAxisAlignment.spaceBetween - no textDirection', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('row');
const Key child0Key = Key('child0');
......@@ -184,7 +185,7 @@ void main() {
expect(OrderPainter.log, <int>[]);
});
testWidgets('Row with MainAxisAlignment.spaceAround - no textDirection', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row with MainAxisAlignment.spaceAround - no textDirection', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('row');
const Key child0Key = Key('child0');
......@@ -218,7 +219,7 @@ void main() {
expect(OrderPainter.log, <int>[]);
});
testWidgets('Row with MainAxisAlignment.spaceEvenly - no textDirection', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row with MainAxisAlignment.spaceEvenly - no textDirection', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('row');
const Key child0Key = Key('child0');
......@@ -250,7 +251,7 @@ void main() {
expect(OrderPainter.log, <int>[]);
});
testWidgets('Row and MainAxisSize.min - no textDirection', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row and MainAxisSize.min - no textDirection', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('rowKey');
const Key child0Key = Key('child0');
......@@ -280,7 +281,7 @@ void main() {
expect(OrderPainter.log, <int>[]);
});
testWidgets('Row MainAxisSize.min layout at zero size - no textDirection', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row MainAxisSize.min layout at zero size - no textDirection', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key childKey = Key('childKey');
......@@ -308,7 +309,7 @@ void main() {
// LTR
testWidgets('Row with one Flexible child - LTR', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row with one Flexible child - LTR', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('row');
const Key child0Key = Key('child0');
......@@ -358,7 +359,7 @@ void main() {
expect(OrderPainter.log, <int>[1, 2, 3]);
});
testWidgets('Row with default main axis parameters - LTR', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row with default main axis parameters - LTR', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('row');
const Key child0Key = Key('child0');
......@@ -408,7 +409,7 @@ void main() {
expect(OrderPainter.log, <int>[1, 2, 3]);
});
testWidgets('Row with MainAxisAlignment.center - LTR', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row with MainAxisAlignment.center - LTR', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('row');
const Key child0Key = Key('child0');
......@@ -450,7 +451,7 @@ void main() {
expect(OrderPainter.log, <int>[1, 2]);
});
testWidgets('Row with MainAxisAlignment.end - LTR', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row with MainAxisAlignment.end - LTR', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('row');
const Key child0Key = Key('child0');
......@@ -500,7 +501,7 @@ void main() {
expect(OrderPainter.log, <int>[1, 2, 3]);
});
testWidgets('Row with MainAxisAlignment.spaceBetween - LTR', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row with MainAxisAlignment.spaceBetween - LTR', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('row');
const Key child0Key = Key('child0');
......@@ -550,7 +551,7 @@ void main() {
expect(OrderPainter.log, <int>[1, 2, 3]);
});
testWidgets('Row with MainAxisAlignment.spaceAround - LTR', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row with MainAxisAlignment.spaceAround - LTR', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('row');
const Key child0Key = Key('child0');
......@@ -608,7 +609,7 @@ void main() {
expect(OrderPainter.log, <int>[1, 2, 3, 4]);
});
testWidgets('Row with MainAxisAlignment.spaceEvenly - LTR', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row with MainAxisAlignment.spaceEvenly - LTR', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('row');
const Key child0Key = Key('child0');
......@@ -658,7 +659,7 @@ void main() {
expect(OrderPainter.log, <int>[1, 2, 3]);
});
testWidgets('Row and MainAxisSize.min - LTR', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row and MainAxisSize.min - LTR', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('rowKey');
const Key child0Key = Key('child0');
......@@ -700,7 +701,7 @@ void main() {
expect(OrderPainter.log, <int>[1, 2]);
});
testWidgets('Row MainAxisSize.min layout at zero size - LTR', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row MainAxisSize.min layout at zero size - LTR', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key childKey = Key('childKey');
......@@ -729,7 +730,7 @@ void main() {
// RTL
testWidgets('Row with one Flexible child - RTL', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row with one Flexible child - RTL', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('row');
const Key child0Key = Key('child0');
......@@ -779,7 +780,7 @@ void main() {
expect(OrderPainter.log, <int>[1, 2, 3]);
});
testWidgets('Row with default main axis parameters - RTL', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row with default main axis parameters - RTL', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('row');
const Key child0Key = Key('child0');
......@@ -829,7 +830,7 @@ void main() {
expect(OrderPainter.log, <int>[1, 2, 3]);
});
testWidgets('Row with MainAxisAlignment.center - RTL', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row with MainAxisAlignment.center - RTL', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('row');
const Key child0Key = Key('child0');
......@@ -871,7 +872,7 @@ void main() {
expect(OrderPainter.log, <int>[1, 2]);
});
testWidgets('Row with MainAxisAlignment.end - RTL', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row with MainAxisAlignment.end - RTL', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('row');
const Key child0Key = Key('child0');
......@@ -921,7 +922,7 @@ void main() {
expect(OrderPainter.log, <int>[1, 2, 3]);
});
testWidgets('Row with MainAxisAlignment.spaceBetween - RTL', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row with MainAxisAlignment.spaceBetween - RTL', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('row');
const Key child0Key = Key('child0');
......@@ -971,7 +972,7 @@ void main() {
expect(OrderPainter.log, <int>[1, 2, 3]);
});
testWidgets('Row with MainAxisAlignment.spaceAround - RTL', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row with MainAxisAlignment.spaceAround - RTL', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('row');
const Key child0Key = Key('child0');
......@@ -1029,7 +1030,7 @@ void main() {
expect(OrderPainter.log, <int>[1, 2, 3, 4]);
});
testWidgets('Row with MainAxisAlignment.spaceEvenly - RTL', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row with MainAxisAlignment.spaceEvenly - RTL', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('row');
const Key child0Key = Key('child0');
......@@ -1079,7 +1080,7 @@ void main() {
expect(OrderPainter.log, <int>[1, 2, 3]);
});
testWidgets('Row and MainAxisSize.min - RTL', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row and MainAxisSize.min - RTL', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key rowKey = Key('rowKey');
const Key child0Key = Key('child0');
......@@ -1121,7 +1122,7 @@ void main() {
expect(OrderPainter.log, <int>[1, 2]);
});
testWidgets('Row MainAxisSize.min layout at zero size - RTL', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Row MainAxisSize.min layout at zero size - RTL', (WidgetTester tester) async {
OrderPainter.log.clear();
const Key childKey = Key('childKey');
......
......@@ -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